Changeset 20
- Timestamp:
- 12/06/12 18:35:28 (12 years ago)
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/TODO
r19 r20 3 3 4 4 * PaddingOracle 5 - change print statements to configurable debug statements 6 7 * New tools for easy scripted encoding/decoding at command line 5 - Enable resumption of decryption in case of failure 8 6 9 7 -
lib/bletchley/CBC/__init__.py
r18 r20 35 35 WTLS" by Serge Vaudenay (2002) 36 36 37 POA objects are not thread-safe. If multiple threads need to work37 POA objects are not caller thread-safe. If multiple threads need to work 38 38 simultaneously on the same ciphertext and oracle, create a 39 separate instance. 39 separate instance. POA objects can execute tasks internally using 40 multiple threads, however. 40 41 41 42 """ … … 63 64 results in a correct padding upon decryption and False 64 65 otherwise. This function should implement the prototype: 65 def myOracle(ciphertext, iv) 66 def myOracle(ciphertext, iv): ... 66 67 If the initialization vector (iv) is unknown is not included in 67 68 the ciphertext message, it can be ignored in the oracle … … 210 211 211 212 if self._thread_result == None: 213 self.log_message("Value of a byte could not be determined. Current plaintext suffix: "+ repr(self.decrypted)) 212 214 raise Exception 213 215 … … 230 232 # XXX: Add logic to begin where decryption previously left off 231 233 def decrypt(self): 232 """Decrypts a message using CBC mode. If the IV is not provided,233 it assumes a null IV.234 """Decrypts the previously supplied ciphertext. If the IV was 235 not provided, it assumes a IV of zero bytes. 234 236 235 237 """ … … 237 239 blocks = buffertools.splitBuffer(self._ciphertext, self.block_size) 238 240 239 final = blocks[-1] 240 iv = self._iv 241 if iv == None: 242 iv = '\x00'*self.block_size 243 if len(blocks) == 1: 244 # If only one block present, then try to use IV as prior 245 prior = iv 246 else: 247 prior = blocks[-2] 248 249 # Decrypt last block, starting with padding (quicker to decrypt) 250 pad_bytes = self.probe_padding(prior, final) 251 decrypted = self.decrypt_block(prior, final, pad_bytes) 252 253 # Now decrypt all other blocks except first block 254 for i in range(len(blocks)-2, 0, -1): 255 decrypted = self.decrypt_block(blocks[i-1], blocks[i]) + decrypted 256 257 # Finally decrypt first block 258 decrypted = self.decrypt_block(iv, blocks[0]) + decrypted 259 241 if len(self.decrypted) == 0: 242 243 final = blocks[-1] 244 iv = self._iv 245 if iv == None: 246 iv = '\x00'*self.block_size 247 if len(blocks) == 1: 248 # If only one block present, then try to use IV as prior 249 prior = iv 250 else: 251 prior = blocks[-2] 252 253 # Decrypt last block, starting with padding (quicker to decrypt) 254 pad_bytes = self.probe_padding(prior, final) 255 decrypted = self.decrypt_block(prior, final, pad_bytes) 256 257 # Now decrypt all other blocks except first block 258 for i in range(len(blocks)-2, 0, -1): 259 decrypted = self.decrypt_block(blocks[i-1], blocks[i]) + decrypted 260 261 # Finally decrypt first block 262 decrypted = self.decrypt_block(iv, blocks[0]) + decrypted 263 264 # Start where we left off last 265 # XXX: test this 266 else: 267 num_partial = len(self.decrypted) % self.block_size 268 finished_blocks = len(self.decrypted) / self.block_size 269 partial = self.decrypted[0:num_partial] 270 decrypted = self.decrypted[num_partial:] 271 272 for i in range(-1-finished_blocks, 0, -1): 273 decrypted = self.decrypt_block(blocks[i-1], blocks[i], partial) 274 partial = '' 275 276 # Finally decrypt first block 277 decrypted = self.decrypt_block(iv, blocks[0]) + decrypted 278 260 279 return buffertools.stripPKCS7Pad(decrypted) 261 280 262 281 263 282 def encrypt_block(self, plaintext, ciphertext): 283 """Encrypts a block of plaintext. This is accomplished by 284 decrypting the supplied ciphertext and then computing the prior 285 block needed to create the desired plaintext at the ciphertext's 286 location. 287 288 Returns the calculated prior block and the provided ciphertext 289 block as a tuple. 290 291 """ 264 292 if len(plaintext) != self.block_size or len(plaintext) != len(ciphertext): 265 293 raise InvalidBlockError(self.block_size,len(plaintext)) … … 270 298 271 299 272 # XXX: Add option to encrypt only the last N blocks. Supplying a shorter273 # plaintext and subsequent concatenation can easily achieve this as well...274 300 def encrypt(self,plaintext): 301 """Encrypts a plaintext value through "CBC-R" style prior-block 302 propagation. 303 304 Returns a tuple of the IV and ciphertext. 305 306 NOTE: If your target messages do not include an IV with the 307 ciphertext, you can instead opt to encrypt a suffix of the 308 message and include the IV as if it were a ciphertext block. 309 This block will decrypt to an uncontrollable random value, but 310 with careful placement, this might be ok. 311 312 """ 313 275 314 blocks = buffertools.splitBuffer(buffertools.pkcs7PadBuffer(plaintext, self.block_size), 276 315 self.block_size) -
lib/bletchley/blobtools.py
r1 r20 41 41 def isExample(self, blob): 42 42 sblob = frozenset(blob) 43 return ((self.charset == None or sblob.issubset(self.charset)) and self.extraTests(blob)) 43 if self.charset != None and not sblob.issubset(self.charset): 44 return False 45 return self.extraTests(blob) 44 46 45 47 def extraTests(self, blob): 48 """May return True, False, or None, for is an example, isn't an 49 example, or unknown, respectively. 50 51 """ 46 52 return True 47 53 … … 254 260 chunks = blob.split('%') 255 261 if len(chunks) < 2: 256 return False262 return None 257 263 for c in chunks[1:]: 258 264 if len(c) < 2: … … 320 326 321 327 def possibleEncodings(blob): 322 ret_val = set() 328 likely = set() 329 possible = set() 323 330 for name,encoding in encodings.items(): 324 if encoding.isExample(blob): 325 ret_val.add(name) 326 return ret_val 331 result = encoding.isExample(blob) 332 if result == True: 333 likely.add(name) 334 elif result == None: 335 possible.add(name) 336 return likely,possible 327 337 328 338 329 339 def encodingIntersection(blobs): 330 340 ret_val = set(encodings.keys()) 341 p = set(encodings.keys()) 331 342 for b in blobs: 332 ret_val &= possibleEncodings(b) 333 334 return ret_val 343 likely,possible = possibleEncodings(b) 344 ret_val &= likely | possible 345 p &= possible 346 return ret_val - p 335 347 336 348 … … 404 416 405 417 418 #XXX: move this to buffertools 406 419 def smartPermutateBlobs(blobs, block_size=8): 407 420 """
Note: See TracChangeset
for help on using the changeset viewer.