Changeset 38


Ignore:
Timestamp:
02/13/13 21:02:54 (12 years ago)
Author:
tmorgan
Message:

simplified decrypt() and interface to probe_padding()

sanity checks

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/bletchley/CBC/__init__.py

    r37 r38  
    8888         previously left off.  This argument is assumed to contain the
    8989         final N bytes (for an N-byte argument) of the plaintext; that
    90          is, the tail of the plaintext.
     90         is, the tail of the plaintext including the pad.
    9191
    9292        log_file -- A Python file object where log messages will be
     
    9999        if(iv != None and len(iv)%block_size != 0):
    100100            raise InvalidBlockError(block_size,len(iv))
    101 
     101        if len(decrypted) > len(ciphertext):
     102            raise Exception #XXX: custom exception
     103       
    102104        self.block_size = block_size
    103105        self.decrypted = decrypted
     
    118120
    119121
    120     def probe_padding(self, prior, final):
     122    def probe_padding(self):
    121123        """Attempts to verify that a CBC padding oracle exists and then determines the
    122124        pad value. 
     
    125127        XXX: Currently only works for PKCS 5/7.
    126128        """
     129
     130        blocks = buffertools.splitBuffer(self._ciphertext, self.block_size)
     131        final = blocks[-1]
     132        if len(blocks) == 1:
     133            # If only one block present, then try to use IV as prior
     134            prior = self._iv
     135        else:
     136            prior = blocks[-2]
    127137
    128138        ret_val = None
     
    157167                    # XXX: Save the decrypted byte for later
    158168                    ret_val = buffertools.pkcs7Pad(pad_length)
    159 
    160         if ret_val:
    161             self.decrypted = ret_val
    162169
    163170        return ret_val
     
    216223        if self._thread_result == None:
    217224            self.log_message("Value of a byte could not be determined.  Current plaintext suffix: "+ repr(self.decrypted))
    218             raise Exception
     225            raise Exception #XXX: custom exception
    219226
    220227        decrypted = struct.pack("B",self._thread_result^base^(numKnownBytes+1))
     
    236243
    237244
    238     # XXX: Add logic to begin where decryption previously left off
    239245    def decrypt(self):
    240246        """Decrypts the previously supplied ciphertext. If the IV was
     
    243249        """
    244250
    245         blocks = buffertools.splitBuffer(self._ciphertext, self.block_size)
    246 
    247251        if len(self.decrypted) == 0:
    248            
    249             final = blocks[-1]
    250             if len(blocks) == 1:
    251                 # If only one block present, then try to use IV as prior
    252                 prior = self._iv
    253             else:
    254                 prior = blocks[-2]
    255 
    256             # Decrypt last block, starting with padding (quicker to decrypt)
    257             pad_bytes = self.probe_padding(prior, final)
     252            # First decrypt the padding (quick to decrypt and good sanity check)
     253            pad_bytes = self.probe_padding()
    258254            if pad_bytes == None:
    259255                # XXX: custom exception
    260256                raise Exception
    261 
    262             decrypted = self.decrypt_block(prior, final, pad_bytes)
    263 
    264             # Now decrypt all other blocks except first block
    265             for i in range(len(blocks)-2, 0, -1):
    266                 decrypted = self.decrypt_block(blocks[i-1], blocks[i]) + decrypted
    267 
    268             # Finally decrypt first block
    269             decrypted = self.decrypt_block(self._iv, blocks[0]) + decrypted
    270        
    271         # Start where we left off last
    272         # XXX: test this more
    273         else:
    274             num_partial = len(self.decrypted) % self.block_size
    275             finished_blocks = len(self.decrypted) / self.block_size
    276             partial = self.decrypted[0:num_partial]
    277             decrypted = self.decrypted[num_partial:]
    278 
    279             for i in range(len(blocks)-1-finished_blocks, 0, -1):
    280                 decrypted = self.decrypt_block(blocks[i-1], blocks[i], partial) + decrypted
    281                 partial = ''
     257           
     258            self.decrypted = pad_bytes
     259
     260
     261        # Start where we left off last, whether that be with just a pad,
     262        # or with additional decrypted blocks.
     263
     264        # number of bytes in any partially decrypted blocks
     265        num_partial = len(self.decrypted) % self.block_size
     266
     267        # number of blocks fully decrypted
     268        finished_blocks = len(self.decrypted) / self.block_size
     269
     270        # contents of the partial block
     271        partial = self.decrypted[0:num_partial]
     272
     273        # contents of fully decrypted blocks
     274        decrypted = self.decrypted[num_partial:]
     275       
     276        blocks = buffertools.splitBuffer(self._ciphertext, self.block_size)
     277
     278        # Start with the partially decrypted block at the end, and work
     279        # our way to the front.  Don't decrypt the very first block of
     280        # the ciphertext yet.
     281        for i in range(len(blocks)-1-finished_blocks, 0, -1):
     282            decrypted = self.decrypt_block(blocks[i-1], blocks[i], partial) + decrypted
     283            partial = ''
    282284               
    283             # Finally decrypt first block
    284             decrypted = self.decrypt_block(self._iv, blocks[0]) + decrypted
    285            
     285        # Finally decrypt first block
     286        decrypted = self.decrypt_block(self._iv, blocks[0], partial) + decrypted
     287       
     288        # Remove the padding and return
    286289        return buffertools.stripPKCS7Pad(decrypted, self.block_size, self.log_fh)
    287290
Note: See TracChangeset for help on using the changeset viewer.