def _get_cipher(self, iv=None): key = self.key if not isinstance(key, bytes): key = key.encode() if iv is None: iv = os.urandom(16) cipher = Cipher(AES(key), CBC(iv), backend=backend) return cipher, iv
def test_unknown_error_in_cipher_finalize(self): cipher = Cipher(AES(b"\0" * 16), CBC(b"\0" * 16), backend=backend) enc = cipher.encryptor() enc.update(b"\0") backend._lib.ERR_put_error(0, 0, 1, b"test_openssl.py", -1) with pytest.raises(InternalError): enc.finalize()
def test_validate_encryption(self): # Arrange queue = self._create_queue() kek = KeyWrapper('key1') queue.key_encryption_key = kek queue.enqueue_message(u'message') # Act queue.key_encryption_key = None # Message will not be decrypted li = queue.peek_messages() message = li[0].content message = loads(message) encryption_data = message['EncryptionData'] wrapped_content_key = encryption_data['WrappedContentKey'] wrapped_content_key = _WrappedContentKey( wrapped_content_key['Algorithm'], b64decode( wrapped_content_key['EncryptedKey'].encode(encoding='utf-8')), wrapped_content_key['KeyId']) encryption_agent = encryption_data['EncryptionAgent'] encryption_agent = _EncryptionAgent( encryption_agent['EncryptionAlgorithm'], encryption_agent['Protocol']) encryption_data = _EncryptionData( b64decode(encryption_data['ContentEncryptionIV'].encode( encoding='utf-8')), encryption_agent, wrapped_content_key, {'EncryptionLibrary': VERSION}) message = message['EncryptedMessageContents'] content_encryption_key = kek.unwrap_key( encryption_data.wrapped_content_key.encrypted_key, encryption_data.wrapped_content_key.algorithm) # Create decryption cipher backend = backends.default_backend() algorithm = AES(content_encryption_key) mode = CBC(encryption_data.content_encryption_IV) cipher = Cipher(algorithm, mode, backend) # decode and decrypt data decrypted_data = _decode_base64_to_bytes(message) decryptor = cipher.decryptor() decrypted_data = (decryptor.update(decrypted_data) + decryptor.finalize()) # unpad data unpadder = PKCS7(128).unpadder() decrypted_data = (unpadder.update(decrypted_data) + unpadder.finalize()) decrypted_data = decrypted_data.decode(encoding='utf-8') # Assert self.assertEqual(decrypted_data, u'message')
def __init__(self, session_key=None): if session_key: assert len(session_key) == self.SESSION_KEY_SIZE self.c2_public_key = load_der_public_key(self.C2_PUBLIC_KEY_DER) self.session_key = session_key or os.urandom(self.SESSION_KEY_SIZE) self.session_key_algorithm = AES(self.session_key) self.session_key_cipher = Cipher(self.session_key_algorithm, CBC(b'\0' * (self.session_key_algorithm.block_size // 8))) self.session_key_padding = PKCS7(self.session_key_algorithm.block_size) self.digest_algorithm = SHA1()
def to_encrypted_bytes(self, ec_key, aes_key): iv = os.urandom(16) encryptor = Cipher(aes_key, CBC(iv), default_backend()).encryptor() b_encrypted = iv b_encrypted += encryptor.update(self._to_bytes(ec_key)) b_encrypted += encryptor.finalize() return b_encrypted
def __init__(self, data_secret: bytes, data_hash: bytes) -> None: digest = Hash(SHA512()) digest.update(data_secret) digest.update(data_hash) secret_hash = digest.finalize() key = secret_hash[:self._key_size] iv = secret_hash[self._key_size:self._key_size + self._iv_size] self._data_hash: Final[bytes] = data_hash self._cipher: Final[Cipher] = Cipher(AES(key), CBC(iv))
def aes_cipher_from_key(key): """ Given an AES key, return a Cipher object that has `encryptor()` and `decryptor()` methods. It will create the cipher to use CBC mode, and create the initialization vector as Software Secure expects it. """ return Cipher(AES(key), CBC(generate_aes_iv(key)), backend=default_backend())
def from_encrypted_bytes(cls, b, peer_ec_key, aes_key): assert len(b) == 256 + 16 iv = b[:16] decryptor = Cipher(aes_key, CBC(iv), default_backend()).decryptor() decrypted = decryptor.update(b[16:]) decrypted += decryptor.finalize() return cls._from_bytes(decrypted, peer_ec_key)
def decrypt(secret, hash, data, file=False): """ Decrypt per telegram docs at https://core.telegram.org/passport. Args: secret (:obj:`str` or :obj:`bytes`): The encryption secret, either as bytes or as a base64 encoded string. hash (:obj:`str` or :obj:`bytes`): The hash, either as bytes or as a base64 encoded string. data (:obj:`str` or :obj:`bytes`): The data to decrypt, either as bytes or as a base64 encoded string. file (:obj:`bool`): Force data to be treated as raw data, instead of trying to b64decode it. Raises: :class:`TelegramDecryptionError`: Given hash does not match hash of decrypted data. Returns: :obj:`bytes`: The decrypted data as bytes. """ # First make sure that if secret, hash, or data was base64 encoded, to decode it into bytes try: secret = b64decode(secret) except (binascii.Error, TypeError): pass try: hash = b64decode(hash) except (binascii.Error, TypeError): pass if not file: try: data = b64decode(data) except (binascii.Error, TypeError): pass # Make a SHA512 hash of secret + update digest = Hash(SHA512(), backend=default_backend()) digest.update(secret + hash) secret_hash_hash = digest.finalize() # First 32 chars is our key, next 16 is the initialisation vector key, iv = secret_hash_hash[:32], secret_hash_hash[32:32 + 16] # Init a AES-CBC cipher and decrypt the data cipher = Cipher(AES(key), CBC(iv), backend=default_backend()) decryptor = cipher.decryptor() data = decryptor.update(data) + decryptor.finalize() # Calculate SHA256 hash of the decrypted data digest = Hash(SHA256(), backend=default_backend()) digest.update(data) data_hash = digest.finalize() # If the newly calculated hash did not match the one telegram gave us if data_hash != hash: # Raise a error that is caught inside telegram.PassportData and transformed into a warning raise TelegramDecryptionError("Hashes are not equal! {} != {}".format(data_hash, hash)) # Return data without padding return data[bord(data[0]):]
def aes_cbc_enc(aesKey, sPlainMsg): ''' AuthenticatedEncryption - Do a encrypt then mac operation on given message. a random iv is generated but not transmitted, instead a random block is prepended to the message and encrypted. Inturn the same can be discarded during decrypting. Each CBC block depends on the previous encrypted block so the 0th block acts as a inplace iv at one level. Encryption uses AES in CBC mode with PKCS7 padding where required. MAC uses HMAC with SHA256 As encryption and mac using independent algorithms so the key is shared wrt encryption and mac operations. With aes length of key passed is independent of the block size used, and user can use any valid aes key size. This is similar to the age old encrypt as well as sign messages to ensure confidentiality as well as authenticity. But then instead of using asymm logic for signing, use a hash with hidden key based logic. Also make sure that one checks the authenticity before trying to use it or work on it, so that new oracles arent opened up, beyond the minimal unavoidable oracle. ''' ### Prepare for encryption blockLen = 16 iv = os.urandom(blockLen) aes = AES(aesKey) cbc = CBC(iv) aesCbc = Cipher(aes, cbc, default_backend()) aesCbcEnc = aesCbc.encryptor() random0thBlock = os.urandom(blockLen) # This allows iv to be discarded # so also while decrypting discard the 0th block plainMsg = random0thBlock + sPlainMsg.encode('utf-8') # do PKCS7 padding if bInternalPadder: padLen = blockLen - (len(plainMsg) % blockLen) for i in range(padLen): plainMsg += int.to_bytes(padLen, 1, 'little') else: pad = PKCS7(blockLen * 8).padder() plainMsg = pad.update(plainMsg) plainMsg += pad.finalize() ### do encrypt encMsg = aesCbcEnc.update(plainMsg) encFina = aesCbcEnc.finalize() encMsg = encMsg + encFina ### Prepare for mac sha256 = SHA256() hmac = HMAC(aesKey, sha256, default_backend()) ### do mac hmac.update(encMsg) macMsg = hmac.finalize() return encMsg, macMsg
def _encrypt(enc_key, mac_key, salt, data, version): iv = os.urandom(_IV_LEN) padder = PKCS7(AES.block_size).padder() padded_data = padder.update(data) + padder.finalize() encryptor = Cipher(AES(enc_key), CBC(iv), _backend).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() all_data = b''.join((version.value, salt, iv, ciphertext)) h = HMAC(mac_key, _MAC_HASH, _backend) h.update(all_data) hmac = h.finalize() return all_data + hmac
def crypt(key: bytes, username: str) -> bytes: backend = default_backend() iv: bytes = urandom(BLOCK_SIZE) cipher = Cipher(AES(key), CBC(iv), backend=backend) encryptor = cipher.encryptor() padder = padding.PKCS7(BLOCK_SIZE * 8).padder() padded = (padder.update(username.encode('utf-8')) + padder.finalize()) return iv + encryptor.update(padded) + encryptor.finalize()
def nc_decrypt(key, ct, iv) -> list: """ :param key: either cli2ser_key or ser2cli_key :param ct: bytes :param iv: bytes :return: list Return values: rv[1] = derived key rv[2] = pt """ validate_aes256_key("nc_decrypt", key) validate_ct("nc_decrypt", ct) validate_iv("nc_decrypt", iv) rv = [] # NOTE: same block used for encryption dec1 = HMAC(NC_KEY, SHA256(), backend=default_backend()) dec1.update(key) dec1_out = dec1.finalize() # log.debug("nc_decrypt dec1_out: {}, {}".format(dec1_out, type(dec1_out))) rv.append(dec1_out) dec2 = HMAC(dec1_out, SHA256(), backend=default_backend()) dec2.update(NC_STR_ENC2) dec2.update(b'\x01') dec2_out = dec2.finalize() # log.debug("nc_decrypt dec2_out: {}, {}".format(dec2_out, type(dec2_out))) # log.debug("nc_decrypt dec2_out is the symmetric key: {}".format(dec2_out)) rv.append(dec2_out) mode = CBC(iv) cipher = Cipher(AES(dec2_out), mode, backend=default_backend()) # NOTE: decryptor does not unpad automatically decryptor = cipher.decryptor() pt_p = decryptor.update(ct) + decryptor.finalize() # log.debug("nc_decrypt: pt_p: {}, {}. {}".format(pt_p, len(pt_p), type(pt_p))) # if (len(pt_p) % AES_BLOCK_BYTES != 0): # unpadder = PKCS7(AES_BLOCK_BITS).unpadder() # pt = unpadder.update(pt_p) + unpadder.finalize() # else: # pt = pt_p unpadder = PKCS7(AES_BLOCK_BITS).unpadder() pt = unpadder.update(pt_p) + unpadder.finalize() # log.debug("nc_decrypt: pt: {}, {}. {}".format(pt, len(pt), type(pt))) rv.append(pt) return rv
def _decrypt(enc_key, mac_key, salt, data): if not _verify(data, mac_key): raise DecryptError('signature could not be verified') from None pos = _VERSION_LEN + len(salt) + _IV_LEN iv = data[_VERSION_LEN + len(salt):pos] decryptor = Cipher(AES(enc_key), CBC(iv), _backend).decryptor() try: padded_plaintext = (decryptor.update(data[pos:-_MAC_LEN]) + decryptor.finalize()) unpadder = PKCS7(AES.block_size).unpadder() return unpadder.update(padded_plaintext) + unpadder.finalize() except ValueError: raise DecryptError('data could not be decrypted') from None
def decrypt(key: bytes, value: bytes) -> str: backend = default_backend() iv = value[:BLOCK_SIZE] data = value[BLOCK_SIZE:] cipher = Cipher(AES(key), CBC(iv), backend=backend) decryptor = cipher.decryptor() padded = decryptor.update(data) + decryptor.finalize() unpadder = padding.PKCS7(BLOCK_SIZE * 8).unpadder() return (unpadder.update(padded) + unpadder.finalize()).decode('utf-8')
def nc_encrypt(key, pt, iv) -> list: """ :param key: either cli2ser_key or ser2cli_key :param pt: bytes :param iv: bytes :return: list Return values: rv[1] = derived key rv[2] = ct """ validate_aes256_key("nc_encrypt", key) validate_pt("nc_encrypt", pt) validate_iv("nc_encrypt", iv) rv = [] # NOTE: same block used for decryption enc1 = HMAC(NC_KEY, SHA256(), backend=default_backend()) enc1.update(key) enc1_out = enc1.finalize() # log.debug("nc_encrypt enc1_out: {}, {}".format(enc1_out, type(enc1_out))) rv.append(enc1_out) enc2 = HMAC(enc1_out, SHA256(), backend=default_backend()) enc2.update(NC_STR_ENC2) enc2.update(b'\x01') enc2_out = enc2.finalize() # log.debug("nc_encrypt enc2_out: {}, {}".format(enc2_out, type(enc2_out))) # log.debug("nc_encrypt enc2_out is the symmetric key: {}".format(enc2_out)) rv.append(enc2_out) mode = CBC(iv) cipher = Cipher(AES(enc2_out), mode, backend=default_backend()) # NOTE: encryptor does not pad automatically encryptor = cipher.encryptor() if (len(pt) % AES_BLOCK_BYTES != 0): padder = PKCS7(AES_BLOCK_BITS).padder() pt_p = padder.update(pt) + padder.finalize() else: pt_p = pt # log.debug("nc_encrypt: pt_p {}, {}, {}".format(pt_p, len(pt_p), type(pt_p))) ct = encryptor.update(pt_p) + encryptor.finalize() # log.debug("nc_encrypt ct {}, {}, {}".format(ct, len(ct), type(ct))) rv.append(ct) return rv
def _generate_AES_CBC_cipher(cek, iv): ''' Generates and returns an encryption cipher for AES CBC using the given cek and iv. :param bytes[] cek: The content encryption key for the cipher. :param bytes[] iv: The initialization vector for the cipher. :return: A cipher for encrypting in AES256 CBC. :rtype: ~cryptography.hazmat.primitives.ciphers.Cipher ''' backend = default_backend() algorithm = AES(cek) mode = CBC(iv) return Cipher(algorithm, mode, backend)
def encryptField(self, field): iv = urandom(int(AES.block_size / 8)) cipher = Cipher(AES(self.key), CBC(iv), default_backend()) bytesField = str(field).encode("utf-8") padder = self.padding.padder() paddedBytes = padder.update(bytesField) + padder.finalize() encryptor = cipher.encryptor() ct = encryptor.update(paddedBytes) + encryptor.finalize() return b64encode(ct).decode("ascii") + "\n" + b64encode(iv).decode( "ascii")
def getClientBids(self, clientId): assert self.getAuctionInfo( )["type"] == "BlindShown" or "key" in self.blockChain.tail.data.keys() block = self.blockChain.head.next if block == None: return [] bids = [] while block != None: if "winnerBlockNumber" in block.data.keys(): break if self.getAuctionInfo()["type"] == "BlindShown": blockClientId = block.data["bid"]["clientId"] else: key = b64decode( bytes(self.blockChain.tail.data["key"], "ascii")) field, iv = block.data["bid"]["clientId"].split("\n") fieldBytes = b64decode(bytes(field, "ascii")) iv = b64decode(bytes(iv, "ascii")) decryptor = Cipher(AES(key), CBC(iv), default_backend()).decryptor() uncryptedField = decryptor.update( fieldBytes) + decryptor.finalize() unpadder = PKCS7(AES.block_size).unpadder() unpaddedField = unpadder.update( uncryptedField) + unpadder.finalize() blockClientId = unpaddedField.decode("ascii") if blockClientId == clientId: bids.append(block.data["bid"]) block = block.next if bids == []: return [] if "key" in self.blockChain.tail.data.keys(): key = self.getKey() return {"key": key, "bidsList": bids} return bids
def encrypt(message: bytes): iv = urandom(ivSize) kdf = PBKDF2HMAC( algorithm=SHA256(), length=32, salt=iv, iterations=1000, backend=backend) key2 = kdf.derive(key1) cipher = Cipher(AES(key2), CBC(iv), backend) encryptor = cipher.encryptor() padder = pkcs7.padder() with open('temp', 'wb') as f: f.write(iv) f.write(encryptor.update(padder.update(message) + padder.finalize())) f.write(encryptor.finalize())
def encrypt_with_key_and_iv_tripledes_cbc(key: bytes, iv: bytes, msg: bytes) -> bytes: from cryptography.hazmat.primitives.ciphers import Cipher from cryptography.hazmat.primitives.ciphers.algorithms import TripleDES from cryptography.hazmat.primitives.ciphers.modes import CBC from cryptography.hazmat.backends import default_backend tripledes_cbc_cipher = Cipher(TripleDES(key), mode=CBC(iv), backend=default_backend()) tripledes_cbc_encryptor = tripledes_cbc_cipher.encryptor() final = tripledes_cbc_encryptor.update(msg) final += tripledes_cbc_encryptor.finalize() return final
def encrypt(self, plaintext): if not getattr(self, '_cipher_key', None): self._cipher_salt = token_bytes(32) self._cipher_key = derive_key(password, self._cipher_salt) self._known_keys[self._cipher_salt] = self._cipher_key # The salt (IV) can only be as large as the AES block-size. salt = token_bytes(AES.block_size // 8) padder = PKCS7(AES.block_size).padder() padded_data = padder.update(plaintext) + padder.finalize() encryptor = Cipher(AES(self._cipher_key), CBC(salt)).encryptor() ciphertext = encryptor.update(padded_data) + encryptor.finalize() return self._cipher_salt + salt + ciphertext
def test_challenge10(play_that_funky_music_padded): key = b'YELLOW SUBMARINE' iv = urandom(16) cipher = challenge10.AESCBC(key, iv) reference = Cipher(AES(key), CBC(iv), default_backend()) check_cipher_interoperability( cipher, reference, b'welcome to the wonderful world of cryptography\x02\x02', ) cipher = challenge10.AESCBC(key, bytes(16)) with open('data/10.txt') as f: ciphertext = b64decode(f.read()) plaintext = cipher.decrypt(ciphertext) assert plaintext == play_that_funky_music_padded
def decryptField(key, padding, field): field, iv = field.split("\n") fieldBytes = b64decode(bytes(field, "ascii")) iv = b64decode(bytes(iv, "ascii")) cipher = Cipher(AES(key), CBC(iv), default_backend()) fieldBytes = b64decode(bytes(field, "ascii")) decryptor = cipher.decryptor() uncryptedField = decryptor.update(fieldBytes) + decryptor.finalize() unpadder = padding.unpadder() unpaddedField = unpadder.update(uncryptedField) + unpadder.finalize() return unpaddedField.decode("utf-8")
def decrypt(secret, hash, data): """ Decrypt per telegram docs at https://core.telegram.org/passport. Args: secret (:obj:`str` or :obj:`bytes`): The encryption secret, either as bytes or as a base64 encoded string. hash (:obj:`str` or :obj:`bytes`): The hash, either as bytes or as a base64 encoded string. data (:obj:`str` or :obj:`bytes`): The data to decrypt, either as bytes or as a base64 encoded string. file (:obj:`bool`): Force data to be treated as raw data, instead of trying to b64decode it. Raises: :class:`PassportDecryptionError`: Given hash does not match hash of decrypted data. Returns: :obj:`bytes`: The decrypted data as bytes. """ if not CRYPTO_INSTALLED: raise RuntimeError( "To use Telegram Passports, PTB must be installed via `pip install " "python-telegram-bot[passport]`." ) # Make a SHA512 hash of secret + update digest = Hash(SHA512(), backend=default_backend()) digest.update(secret + hash) secret_hash_hash = digest.finalize() # First 32 chars is our key, next 16 is the initialisation vector key, init_vector = secret_hash_hash[:32], secret_hash_hash[32 : 32 + 16] # Init a AES-CBC cipher and decrypt the data cipher = Cipher(AES(key), CBC(init_vector), backend=default_backend()) decryptor = cipher.decryptor() data = decryptor.update(data) + decryptor.finalize() # Calculate SHA256 hash of the decrypted data digest = Hash(SHA256(), backend=default_backend()) digest.update(data) data_hash = digest.finalize() # If the newly calculated hash did not match the one telegram gave us if data_hash != hash: # Raise a error that is caught inside telegram.PassportData and transformed into a warning raise PassportDecryptionError(f"Hashes are not equal! {data_hash} != {hash}") # Return data without padding return data[data[0] :]
def decrypt(self, ciphertext): cipher_salt = ciphertext[:32] cipher_key = self._known_keys.get(cipher_salt) if not cipher_key: cipher_key = derive_key(self._password, cipher_salt) self._known_keys[cipher_salt] = cipher_key salt = ciphertext[32:(AES.block_size // 8) + 32] ciphertext = ciphertext[(AES.block_size // 8) + 32:] decryptor = Cipher(AES(cipher_key), CBC(salt)).decryptor() padded_data = decryptor.update(ciphertext) + decryptor.finalize() unpadder = PKCS7(AES.block_size).unpadder() plaintext = unpadder.update(padded_data) + unpadder.finalize() return plaintext
def decrypt(): with open('temp', 'rb') as f: iv = f.read(ivSize) kdf = PBKDF2HMAC( algorithm=SHA256(), length=32, salt=iv, iterations=1000, backend=backend) key2 = kdf.derive(key1) cipher = Cipher(AES(key2), CBC(iv), backend) decryptor = cipher.decryptor() unpadder = pkcs7.unpadder() data = BytesIO() data.write(unpadder.update(decryptor.update(f.read()))) data.write(unpadder.update(decryptor.finalize())) data.write(unpadder.finalize()) return data.getvalue()
def __init__(self, config): self.keylist_file = config.path / 'keys' p = getpass.getpass('Enter encryption phrase for key database: ') sha = hashlib.sha256(p.encode('ascii')) self.nonce_file = config.path / 'nonce' if not self.nonce_file.exists(): self.nonce = os.urandom(16) with self.nonce_file.open('wb') as f: f.write(self.nonce) else: with self.nonce_file.open('rb') as f: self.nonce = f.read() self.keylist_cipher = Cipher(AES(sha.digest()), CBC(self.nonce)) if not self.keylist_file.exists(): self.keys = {} else: self.parse_keylist()
def encrypt(plaintext, aes_key, hmac_key, iv): """ Encrypt a manifest or an image """ padder = padding.PKCS7(128).padder() padded_plaintext = padder.update(plaintext) + padder.finalize() cipher = Cipher(AES(aes_key), CBC(iv), default_backend()) encryptor = cipher.encryptor() encrypted_data = encryptor.update(padded_plaintext) + encryptor.finalize() # Create the HMAC hmac_o = hmac.HMAC(hmac_key, hashes.SHA256(), default_backend()) hmac_o.update(iv + encrypted_data) return iv + encrypted_data + hmac_o.finalize()
def encrypt(self, msg, aad, iv, key): """Key Encryption with AES_CBC_HMAC_SHA2. :param msg: text to be encrypt in bytes :param aad: additional authenticated data in bytes :param iv: initialization vector in bytes :param key: encrypted key in bytes :return: (ciphertext, iv, tag) """ self.check_iv(iv) hkey = key[:self.key_bytes_length] ekey = key[self.key_bytes_length:] pad = PKCS7(AES.block_size).padder() padded_data = pad.update(msg) + pad.finalize() cipher = Cipher(AES(ekey), CBC(iv), backend=default_backend()) enc = cipher.encryptor() ciphertext = enc.update(padded_data) + enc.finalize() tag = self._hmac(ciphertext, aad, iv, hkey) return ciphertext, tag