def set_shared_secret(self, data): """ When used in the NTOR handshake, the first HASH_LEN bytes form the forward digest Df; the next HASH_LEN form the backward digest Db; the next KEY_LEN form Kf, the next KEY_LEN form Kb, and the final DIGEST_LEN bytes are taken as a nonce to use in the place of KH in the hidden service protocol. Excess bytes from K are discarded. :type data: bytes """ forward_digest, backward_digest, encryption_key, decryption_key = struct.unpack( "!20s20s16s16s", data) self._forward_digest = self.set_digest(forward_digest) self._backward_digest = self.set_digest(backward_digest) self.encryption_key = encryption_key self.decryption_key = decryption_key self._forward_cipher = Cipher(AES(self.encryption_key), CTR(b'\0' * 16), backend=default_backend()).encryptor() self._backward_cipher = Cipher(AES(self.decryption_key), CTR(b'\0' * 16), backend=default_backend()).decryptor()
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 compute_tag(cls, key: 'SK', data: bytes): encryptor = Cipher(AES(key.k), modes.CBC(unhexlify(b''.join([b'00'] * 16))), default_backend()).encryptor() while len(data) % 16 != 0: data += unhexlify(b"00") ciphertext = encryptor.update(data) + encryptor.finalize() if cls.get_digest_length() == 16: digest = ciphertext[-1 * cls.get_digest_length():] else: ciphertext = ciphertext[:-8] digest = ciphertext[-8:] return digest
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 decrypt(self, key: bytes, iv: bytes) -> bytes: """ Decrypt a BlobFile to plaintext bytes """ with open(self.file_path, "rb") as f: buff = f.read() if len(buff) != self.length: raise ValueError("unexpected length") cipher = Cipher(AES(key), modes.CBC(iv), backend=backend) unpadder = PKCS7(AES.block_size).unpadder() decryptor = cipher.decryptor() return unpadder.update(decryptor.update(buff) + decryptor.finalize()) + unpadder.finalize()
def generate_symmetric_key(private_key, peer_public_key): """ Generate symmetric AES key using ECDH :param private_key: host private key :param peer_public_key: public key of the peer """ shared_key = private_key.exchange(ec.ECDH(), peer_public_key) derived_key = HKDF(algorithm=hashes.SHA256(), length=32, salt=None, info=b'handshake data', backend=default_backend()).derive(shared_key) aes_key = AES(derived_key) return aes_key
def decrypt(ciphertext, key): """ Decrypt the AES encrypted string. Parameters: ciphertext -- Encrypted string with AES method. key -- key to decrypt the encrypted string. """ ciphertext = base64.b64decode(ciphertext) iv = ciphertext[:iv_size] cipher = Cipher(AES(pad(key)), CFB8(iv), default_backend()) decryptor = cipher.decryptor() return decryptor.update(ciphertext[iv_size:]) + decryptor.finalize()
def _prf(self, key, data): """Set up secure round function F """ # The AES cipher - doesn't seem to care about key length cipher = Cipher(AES(key), modes.CBC('\0' * 16), backend=self._backend) # Pad with x\00 to a multiple 128 bits padding = (16 - len(data) % 16) * '\0' encryptor = cipher.encryptor() data = encryptor.update(padding + data) + encryptor.finalize() return data
def test_challenge7(play_that_funky_music_padded): key = b'YELLOW SUBMARINE' cipher = challenge7.AESECB(key) reference = Cipher(AES(key), ECB(), default_backend()) check_cipher_interoperability( cipher, reference, b'welcome to the wonderful world of cryptography\x02\x02', ) with open('data/7.txt') as f: ciphertext = b64decode(f.read()) plaintext = cipher.decrypt(ciphertext) assert plaintext == play_that_funky_music_padded
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 parse_frame(self, frame): # type: (bytes) -> bytes """Parse one encrypted frame (without size header) and get cleartext data.""" if len(frame) < IV_SIZE + 16: raise AuthenticationError("Frame too short") try: iv = frame[:IV_SIZE] gcm_tag = frame[-16:] cipher_text = frame[IV_SIZE:-16] cipher = Cipher(AES(self._key), GCM(iv), default_backend()) decryptor = cipher.decryptor() clear_text = decryptor.update( cipher_text) + decryptor.finalize_with_tag(gcm_tag) return clear_text except InvalidTag: raise AuthenticationError("Invalid GCM authentication tag")
def decrypt(self, ciphertext, aad, iv, tag, key): """Key Decryption with AES GCM :param ciphertext: ciphertext in bytes :param aad: additional authenticated data in bytes :param iv: initialization vector in bytes :param tag: authentication tag in bytes :param key: encrypted key in bytes :return: message """ self.check_iv(iv) cipher = Cipher(AES(key), GCM(iv, tag), backend=default_backend()) d = cipher.decryptor() d.authenticate_additional_data(aad) return d.update(ciphertext) + d.finalize()
def encrypt(self, msg): IV = os.urandom(16) padder = padding.PKCS7(256).padder() padded = padder.update(msg.encode()) + padder.finalize() cipher = Cipher(AES(key=self.key), modes.CBC(initialization_vector=IV), backend=default_backend()) encryptor = cipher.encryptor() result = encryptor.update(padded) + encryptor.finalize() file_name = input('Save to file: ') self.toFile(file_name, result, IV)
def encrypt(self, msg, aad, iv, key): """Key Encryption with AES GCM :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) cipher = Cipher(AES(key), GCM(iv), backend=default_backend()) enc = cipher.encryptor() enc.authenticate_additional_data(aad) ciphertext = enc.update(msg) + enc.finalize() return ciphertext, enc.tag
def better_aes_decrypt(secret: str, value: bytes) -> bytes: try: data = base64.b64decode(value) _, scryp_n, scrypt_r, scrypt_p, data = data.split(b':', maxsplit=4) init_vector, data = data[:16], data[16:] key = scrypt(secret.encode(), init_vector, int(scryp_n), int(scrypt_r), int(scrypt_p)) decryptor = Cipher(AES(key), modes.CBC(init_vector), default_backend()).decryptor() unpadder = PKCS7(AES.block_size).unpadder() return unpadder.update(decryptor.update(data)) + unpadder.finalize() except ValueError as e: if e.args[0] == 'Invalid padding bytes.': raise InvalidPasswordError() raise
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 get_decrypted_envelope_data(self, certificate: x509.Certificate, key: rsa.RSAPrivateKey) -> bytes: """Decrypt the encrypted envelope data: Decrypt encrypted_key using public key of CA encrypted_key is available at content.recipient_infos[x].encrypted_key algo is content.recipient_infos[x].key_encryption_algorithm at the moment this is RSA """ encap = self.encap_content_info ct = encap['content_type'].native print(ct) recipient_info = encap['content']['recipient_infos'][0] encryption_algo = recipient_info.chosen['key_encryption_algorithm'].native encrypted_key = recipient_info.chosen['encrypted_key'].native assert encryption_algo['algorithm'] == 'rsa' plain_key = key.decrypt( encrypted_key, padding=asympad.PKCS1v15(), ) # Now we have the plain key, we can decrypt the encrypted data encrypted_contentinfo = encap['content']['encrypted_content_info'] print('encrypted content type: {}'.format(encrypted_contentinfo['content_type'].native)) algorithm = encrypted_contentinfo['content_encryption_algorithm'] #: EncryptionAlgorithm encrypted_content_bytes = encrypted_contentinfo['encrypted_content'].native symkey = None if algorithm.encryption_cipher == 'aes': symkey = AES(plain_key) print('cipher AES') elif algorithm.encryption_cipher == 'tripledes': symkey = TripleDES(plain_key) print('cipher 3DES') else: print('Dont understand encryption cipher: ', algorithm.encryption_cipher) print('key length: ', algorithm.key_length) print('enc mode: ', algorithm.encryption_mode) cipher = Cipher(symkey, modes.CBC(algorithm.encryption_iv), backend=default_backend()) decryptor = cipher.decryptor() return decryptor.update(encrypted_content_bytes) + decryptor.finalize()
def aes_decrypt(secret: str, value: str) -> typing.Tuple[str, bytes]: try: data = base64.b64decode(value.encode()) key = double_sha256(secret.encode()) init_vector, data = data[:16], data[16:] decryptor = Cipher(AES(key), modes.CBC(init_vector), default_backend()).decryptor() unpadder = PKCS7(AES.block_size).unpadder() result = unpadder.update(decryptor.update(data)) + unpadder.finalize() return result.decode(), init_vector except UnicodeDecodeError: raise InvalidPasswordError() except ValueError as e: if e.args[0] == 'Invalid padding bytes.': raise InvalidPasswordError() raise
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 mdp_crypt(main_password: str, password_to_crypt: str): """ @param main_password: str -> the userpassword @param password_to_crypt: str -> to crypt @return: byte string """ nonce = os.urandom(32) key = bcrypt.kdf(password=bytes(main_password, "utf8"), salt=nonce, desired_key_bytes=32, rounds=100) ciph = Cipher(AES(key), CTR(nonce), default_backend()) encryptor = ciph.encryptor() return encryptor.update(bytes(password_to_crypt, "utf8")).hex(), nonce.hex()
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_update_into_auto_chunking(self, backend, monkeypatch): key = b"\x00" * 16 c = ciphers.Cipher(AES(key), modes.ECB(), backend) encryptor = c.encryptor() # Lower max chunk size so we can test chunking monkeypatch.setattr(encryptor._ctx, "_MAX_CHUNK_SIZE", 40) buf = bytearray(527) pt = b"abcdefghijklmnopqrstuvwxyz012345" * 16 # 512 bytes processed = encryptor.update_into(pt, buf) assert processed == 512 decryptor = c.decryptor() # Change max chunk size to verify alternate boundaries don't matter monkeypatch.setattr(decryptor._ctx, "_MAX_CHUNK_SIZE", 73) decbuf = bytearray(527) decprocessed = decryptor.update_into(buf[:processed], decbuf) assert decbuf[:decprocessed] == pt
def test_raises_after_finalize(self, backend): key = b"2b7e151628aed2a6abf7158809cf4f3c" cmac = CMAC(AES(key), backend) cmac.finalize() with pytest.raises(AlreadyFinalized): cmac.update(b"foo") with pytest.raises(AlreadyFinalized): cmac.copy() with pytest.raises(AlreadyFinalized): cmac.finalize() with pytest.raises(AlreadyFinalized): cmac.verify(b"")
def decrypt_smime_content(payload: bytes, key: rsa.RSAPrivateKey) -> bytes: content_info = ContentInfo.load(payload) assert content_info['content_type'].native == 'enveloped_data' content: EnvelopedData = content_info['content'] matching_recipient = content['recipient_infos'][0] # Need to see if we hold the key for any valid recipient. # for recipient_info in content['recipient_infos']: # assert recipient_info.name == 'ktri' # Only support KeyTransRecipientInfo # ktri: KeyTransRecipientInfo = recipient_info.chosen # recipient_id: RecipientIdentifier = ktri['rid'] # assert recipient_id.name == 'issuer_and_serial_number' # Only support IssuerAndSerialNumber # matching_recipient = recipient_info encryption_algo = matching_recipient.chosen['key_encryption_algorithm'].native encrypted_key = matching_recipient.chosen['encrypted_key'].native assert encryption_algo['algorithm'] == 'rsa' # Get the content key plain_key = key.decrypt( encrypted_key, padding=padding.PKCS1v15(), ) # Now we have the plain key, we can decrypt the encrypted data encrypted_contentinfo = content['encrypted_content_info'] algorithm: EncryptionAlgorithm = encrypted_contentinfo['content_encryption_algorithm'] #: EncryptionAlgorithm encrypted_content_bytes = encrypted_contentinfo['encrypted_content'].native symkey = None if algorithm.encryption_cipher == 'aes': symkey = AES(plain_key) elif algorithm.encryption_cipher == 'tripledes': symkey = TripleDES(plain_key) else: print('Dont understand encryption cipher: ', algorithm.encryption_cipher) cipher = Cipher(symkey, modes.CBC(algorithm.encryption_iv), backend=default_backend()) decryptor = cipher.decryptor() decrypted_data = decryptor.update(encrypted_content_bytes) + decryptor.finalize() return decrypted_data
def decrypt_value(encryption_key, value): raw_data = value[len('$encrypted$'):] # If the encrypted string contains a UTF8 marker, discard it utf8 = raw_data.startswith('UTF8$') if utf8: raw_data = raw_data[len('UTF8$'):] algo, b64data = raw_data.split('$', 1) if algo != 'AES': raise ValueError('unsupported algorithm: %s' % algo) encrypted = base64.b64decode(b64data) decryptor = Cipher(AES(encryption_key), ECB(), default_backend()).decryptor() value = decryptor.update(encrypted) + decryptor.finalize() value = value.rstrip('\x00') # If the encrypted string contained a UTF8 marker, decode the data if utf8: value = value.decode('utf-8') return value
def aesctr_decrypt_stream(key: AES128Key, iv: bytes, cipher_text: bytes) -> Iterator[int]: aes_key = AES(key) ctr = CTR(iv) try: cipher = Cipher(aes_key, ctr, backend=default_backend()) except ValueError as err: raise DecryptionError(str(err)) from err decryptor = cipher.decryptor() num_blocks = int(math.ceil(len(cipher_text) / 16)) for i in range(num_blocks): cipher_text_block = cipher_text[i * 16:(i + 1) * 16] plain_text_block = decryptor.update(cipher_text_block) yield from plain_text_block yield from decryptor.finalize()
def test_decrypt_and_unpack_bad_signature(caplog, mock_open_streams): orig, new, _ = mock_open_streams orig_contents = orig._fd.getvalue() cipher = Cipher(AES(TMP_KEY), CTR(TMP_NONCE), backend=default_backend()).encryptor() ct = cipher.update(zlib.compress(orig_contents)) hmac = HMAC(TMP_KEY, SHA256(), default_backend()) hmac.update(ct) signature = hmac.finalize() orig._fd.write(ct) with pytest.raises(BackupCorruptedError): decrypt_and_unpack( orig, new, TMP_KEYPAIR + signature[:-2] + b'f', dict(use_compression=True, use_encryption=True), )
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 aes_key_wrap_with_padding(wrapping_key, key_to_wrap, backend): if len(wrapping_key) not in [16, 24, 32]: raise ValueError("The wrapping key must be a valid AES key length") aiv = b"\xA6\x59\x59\xA6" + struct.pack(">i", len(key_to_wrap)) # pad the key to wrap if necessary pad = (8 - (len(key_to_wrap) % 8)) % 8 key_to_wrap = key_to_wrap + b"\x00" * pad if len(key_to_wrap) == 8: # RFC 5649 - 4.1 - exactly 8 octets after padding encryptor = Cipher(AES(wrapping_key), ECB(), backend).encryptor() b = encryptor.update(aiv + key_to_wrap) assert encryptor.finalize() == b"" return b else: r = [key_to_wrap[i:i + 8] for i in range(0, len(key_to_wrap), 8)] return _wrap_core(wrapping_key, aiv, r, backend)
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 _aes256cbc_encrypt(key, iv, plaintext): cipher = _AES.new(key, _AES.MODE_CBC, iv) ciphertext = cipher.encrypt(plaintext) return ciphertext