def test_aes_decrypt(self): aes = AESCrypto() # Test data is not padded so we assume pad is a no-op aes._unpad_data aes._unpad_data = lambda data: data for item in AES_CBC_TEST_VECTORS: key = item['key'].decode('hex') iv = item['iv'].decode('hex') expected_plain_text = item['plaintext'].decode('hex') cipher_text = item['ciphertext'].decode('hex') # Decrypt assumes data contains IV and is padded, but test data is # not padded data = iv + cipher_text decrypted = aes.decrypt(key=key, data=data) self.assertEqual(decrypted, expected_plain_text)
def test_aes_encrypt(self, mock_func): aes = AESCrypto() for item in AES_CBC_TEST_VECTORS: key = item['key'].decode('hex') iv = item['iv'].decode('hex') plain_text = item['plaintext'].decode('hex') expected_cipher_text = item['ciphertext'].decode('hex') mock_func.return_value = iv encrypted_with_iv_and_pad = aes.encrypt(key=key, data=plain_text) # Remove IV encrypted = encrypted_with_iv_and_pad[len(iv):] # Unpad encrypted = encrypted[:-len(plain_text)] self.assertEqual(encrypted, expected_cipher_text) # Also test round-trip decrypted = aes.decrypt(key=key, data=encrypted_with_iv_and_pad) self.assertEqual(decrypted, plain_text)
class HybridCryptoDecrypter(HybridCryptoMixin): def __init__(self, keys_path): """ :param keys_path: Path to the directory containg private keys. :type keys_path: ``str`` """ if not os.path.exists(keys_path): raise ValueError('Directory with private keys doesnt exist') self._keys_path = keys_path self._keyczar = Crypter.Read(self._keys_path) self._aes = AESCrypto() def decrypt(self, data): """ Decypt provided data. """ header = self._get_header(data=data) if header not in ['hpkc', 'haes']: msg = 'Invalid cipher text (missing or corrupted header)' raise ValueError(msg) if header == 'haes': plain_text = self._decrypt_long_message(data=data) elif header == 'hpkc': plain_text = self._decrypt_short_message(data=data) return plain_text def _decrypt_short_message(self, data): """ Decrypt a short message. """ data = self._remove_header(data=data) plain_text = self._keyczar.Decrypt(data) return plain_text def _decrypt_long_message(self, data): """ Decrypt a long message. """ data = self._remove_header(data=data) delimiter_index = data.rindex(self.delimiter) aes_key_cipher_text = data[:delimiter_index] aes_key = self._keyczar.Decrypt(aes_key_cipher_text) data_cipher_text = data[delimiter_index + 1:] data_cipher_text = Base64WSDecode(data_cipher_text) plain_text = self._aes.decrypt(key=aes_key, data=data_cipher_text) return plain_text def _aes_decrypt(self, key, data): header = self._get_header(data=data) if header != 'paes': raise ValueError('Invalid or missing header') data = self._remove_header(data=data) plain_text = self._aes.decrypt(key=key, data=data) return plain_text