def cbc_decrypt(key, data, pad=True, sbox=DEFAULT_SBOX, mesh=False): """ CBC decryption mode of operation :param bytes key: encryption key :param bytes data: ciphertext :type bool pad: perform ISO/IEC 7816-4 unpadding after decryption :param sbox: S-box parameters to use :type sbox: str, SBOXES'es key :param bool mesh: enable key meshing :returns: plaintext :rtype: bytes """ validate_key(key) validate_sbox(sbox) if not data or len(data) % BLOCKSIZE != 0: raise ValueError("Data is not blocksize aligned") if len(data) < 2 * BLOCKSIZE: raise ValueError("There is no either data, or IV in ciphertext") iv = data[:BLOCKSIZE] plaintext = [] for i in xrange(BLOCKSIZE, len(data), BLOCKSIZE): if ( mesh and (i - BLOCKSIZE) >= MESH_MAX_DATA and (i - BLOCKSIZE) % MESH_MAX_DATA == 0 ): key, _ = meshing(key, iv, sbox=sbox) plaintext.append(strxor( ns2block(decrypt(sbox, key, block2ns(data[i:i + BLOCKSIZE]))), data[i - BLOCKSIZE:i], )) if pad: plaintext[-1] = unpad2(plaintext[-1], BLOCKSIZE) return b"".join(plaintext)
def test_symmetric(self): for _ in range(100): for blocksize in (8, 16): data = urandom(randint(0, blocksize * 3)) self.assertSequenceEqual( unpad2(pad2(data, blocksize), blocksize), data, )
def __init__(self, blockcipher, pad=None, unpad=None): self.enc = blockcipher.encrypt self.dec = blockcipher.decrypt self.blen = blockcipher.blen if pad == None: self.padding = lambda x: gost3413.pad2(x, self.blen) else: self.padding = pad if unpad == None: self.unpadding = lambda x: gost3413.unpad2(x, self.blen) else: self.unpadding = unpad