def test_finalize_with_tag_already_finalized(self, backend): key = binascii.unhexlify(b"e98b72a9881a84ca6b76e0f43e68647a") iv = binascii.unhexlify(b"8b23299fde174053f3d652ba") encryptor = ciphers.Cipher(AES(key), modes.GCM(iv), backend).encryptor() ciphertext = encryptor.update(b"abc") + encryptor.finalize() decryptor = ciphers.Cipher(AES(key), modes.GCM(iv, tag=encryptor.tag), backend).decryptor() decryptor.update(ciphertext) decryptor.finalize() with pytest.raises(AlreadyFinalized): decryptor.finalize_with_tag(encryptor.tag)
def crypt_create(key_bytes, is_encrypt_flag=None, iv_bytes=None, algorithm=ciphers_algorithms.AES, mode=ciphers_modes.CTR): ''' Create and return a crypto context for symmetric key encryption using the key key_bytes. Uses algorithm in mode with an IV of iv_bytes. If iv_bytes is None, an all-zero IV is used. AES CTR mode uses the same operations for encryption and decyption. ''' #print "Key: " + binascii.hexlify(bytes(key_bytes)) algo = algorithm(bytes(key_bytes)) # The block_size is in bits if iv_bytes is None: iv_bytes = get_zero_pad(algo.block_size/BITS_IN_BYTE) cipher = ciphers.Cipher(algo, mode(bytes(iv_bytes)), backend=backends.default_backend()) if is_encrypt_flag: return cipher.encryptor() else: return cipher.decryptor()
def _decrypt_block(self, block, mac_needs_iv=False): """Decrypt a block of data, with its MAC at the end.""" # the last ten bytes of the block is the message authentication code payload, their_mac = block[:-10], block[-10:] # update the iv with the counter self._iv_drip[:4] = ByteHelper.write_bytes_int(self._iv_counter) self._iv_counter += 1 # compute mac from the block body and compare mac = hmac.HMAC(self._mac_key, hashes.SHA256()) if mac_needs_iv: mac.update(self._iv_drip) mac.update(payload) our_mac = mac.finalize()[:10] if their_mac != our_mac: self.logger.debug('MAC fail, their_mac %s our_mac %s', their_mac, our_mac) raise Exception('Message Authentication Code fail') # decrypt contents decryptor = ciphers.Cipher(ciphers.algorithms.AES(self._cipher_key), ciphers.modes.CTR( self._iv_drip)).decryptor() return decryptor.update(payload) + decryptor.finalize()
def decrypt_unpad_check(input, string): """Combine the prior routines to convert the string into a key, extract out the IV, decrypt the remainder, unpad whatever decrypted, and check the SHA2 224 tag appended to the end. PARAMETERS ========== input: A bytes object to be decrypted according to the above. string: A string to be used as a key. RETURNS ======= If the input could be decoded and the tag matches, the return value is a bytes object containing the plaintext. In all other cases, the return is None. """ key = derive_key(string) iv = input[:16] ctext = input[16:] aes_cipher = ciphers.Cipher(ciphers.algorithms.AES(key), ciphers.modes.CBC(iv)) aes_decryptor = aes_cipher.decryptor() plain = aes_decryptor.update(ctext) + aes_decryptor.finalize() try: unpadder = padding.PKCS7(128).unpadder() data = unpadder.update(plain) data += unpadder.finalize() except: return None res = check_tag(data) return res
def _build_vectors(): count = 0 output = [] key = None plaintext = binascii.unhexlify(32 * '0') for size in _SIZES_TO_GENERATE: for keyinfo in _RFC6229_KEY_MATERIALS: key = _key_for_size(size, keyinfo) cipher = ciphers.Cipher(algorithms.ARC4(binascii.unhexlify(key)), None, default_backend()) encryptor = cipher.encryptor() current_offset = 0 for offset in _RFC6229_OFFSETS: if offset % 16 != 0: raise ValueError( "Offset {} is not evenly divisible by 16".format( offset)) while current_offset < offset: encryptor.update(plaintext) current_offset += len(plaintext) output.append("\nCOUNT = {}".format(count)) count += 1 output.append("KEY = {}".format(key)) output.append("OFFSET = {}".format(offset)) output.append("PLAINTEXT = {}".format( binascii.hexlify(plaintext))) output.append("CIPHERTEXT = {}".format( binascii.hexlify(encryptor.update(plaintext)))) current_offset += len(plaintext) assert not encryptor.finalize() return "\n".join(output)
def _encrypt(self, data, iv=None): if iv is None: iv = os.urandom(_iv_len) cipher = cryptography.Cipher(self.cipher, mode=_mode[self.mode](iv), backend=self.backend).encryptor() return b''.join([iv, cipher.update(data)])
def encrypt(self, password, data): """Encrypt given data using md5 + salt + aes-128-cbc.""" # IrssiNotifier requires null at the end databytes = data.encode() + bytes(1) padder = padding.PKCS7(128).padder() padded_data = padder.update(databytes) + padder.finalize() salt = os.urandom(8) key = None iv = None for n in range(2): # this following logic is similar to EVP_BytesToKey() from openssl md5hash = hashes.Hash(hashes.MD5()) if key is not None: md5hash.update(key) md5hash.update(password.encode()) md5hash.update(salt) md5 = md5hash.finalize() if key is None: key = md5 continue if iv is None: iv = md5 aes256cbc = ciphers.Cipher(ciphers.algorithms.AES(key), ciphers.modes.CBC(iv)) encryptor = aes256cbc.encryptor() edata = encryptor.update(padded_data) + encryptor.finalize() edata = 'Salted__'.encode() + salt + edata edata = base64.b64encode(edata, b'-_') edata = edata.replace(b'=', b'') return edata
def aes_ecb(text, key, encrypt=False): """Decrypts the ciphertext in the file with known key.""" cipher = ciphers.Cipher(algorithms.AES(key), modes.ECB(), backends.default_backend()) cryptor = cipher.encryptor() if encrypt else cipher.decryptor() crypt = cryptor.update(text) + cryptor.finalize() return crypt
def decrypt(value: bytes) -> bytes: """Decrypt a string. :return: A decrypted string.""" try: decrypted = base64.b64decode(value) except binascii.Error: raise CryptoError("Invalid encrypted token: invalid base64") if len(decrypted) < IV_BYTES_NEEDED + TAG_SIZE_BYTES: raise CryptoError("Invalid encrypted token: size check failure") iv = decrypted[:IV_BYTES_NEEDED] tag = decrypted[IV_BYTES_NEEDED:IV_BYTES_NEEDED + TAG_SIZE_BYTES] decrypted = decrypted[IV_BYTES_NEEDED + TAG_SIZE_BYTES:] cipher = ciphers.Cipher( ciphers.algorithms.AES(SECRET_KEY), ciphers.modes.GCM(iv, tag), backend=default_backend(), ) decryptor = cipher.decryptor() try: return decryptor.update( decrypted) + decryptor.finalize() # type: ignore[no-any-return] except cryptography.exceptions.InvalidTag: raise CryptoError("Invalid encrypted token: decryptor() failure")
def _decrypt_message(self, message): try: encrypted_message = base64.b64decode(message['body']) except (ValueError, TypeError): return iv = encrypted_message[:16] cipher = ciphers.Cipher(algorithms.AES(self._encryption_key), modes.CBC(iv), backend=crypto_backends.default_backend()) try: decryptor = cipher.decryptor() data = (decryptor.update(encrypted_message[16:]) + decryptor.finalize()) except Exception: raise DecryptError(_('Encrypted data appears to be corrupted.')) # Strip the last n padding bytes where n is the last value in # the plaintext unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder() data = unpadder.update(data) + unpadder.finalize() try: message['body'] = pickle.loads(data) except pickle.UnpicklingError: # If the data is a string which didn't be serialized, there will # raise an exception. We just try to return the string itself. message['body'] = str(data, encoding="utf-8")
def build_cipher(self, alg='aes_128_cbc'): """ :param alg: cipher algorithm :return: A Cipher instance """ self.__class__._deprecation_notice() typ, bits, cmode = alg.lower().split('_') bits = int(bits) iv = _os.urandom(self.AES_BLOCK_SIZE) if len(iv) != self.AES_BLOCK_SIZE: raise Exception('Wrong iv size: {}'.format(len(iv))) if bits not in _ciphers.algorithms.AES.key_sizes: raise Exception('Unsupported key length: {}'.format(bits)) if len(self.key) != bits / 8: raise Exception('Wrong Key length: {}'.format(len(self.key))) try: mode = self.POSTFIX_MODE[cmode] except KeyError: raise Exception('Unsupported chaining mode: {}'.format(cmode)) cipher = _ciphers.Cipher(_ciphers.algorithms.AES(self.key), mode(iv), backend=_backends.default_backend()) return cipher, iv
def __init__(self, algorithm=None, cipher_mode=None, initialization_vector=None, **kwargs): """Initializes a decrypter. Args: algorithm (Optional[Cryptography.CipherAlgorithm]): cipher algorithm. cipher_mode (Optional[str]): cipher mode. initialization_vector (Optional[bytes]): initialization vector. kwargs (dict): keyword arguments depending on the decrypter. Raises: ValueError: if the initialization_vector is required and not set. """ if (cipher_mode != definitions.ENCRYPTION_MODE_ECB and not initialization_vector): raise ValueError('Missing initialization vector.') if cipher_mode == definitions.ENCRYPTION_MODE_CBC: mode = modes.CBC(initialization_vector) elif cipher_mode == definitions.ENCRYPTION_MODE_CFB: mode = modes.CFB(initialization_vector) elif cipher_mode == definitions.ENCRYPTION_MODE_ECB: mode = modes.ECB() elif cipher_mode == definitions.ENCRYPTION_MODE_OFB: mode = modes.OFB(initialization_vector) backend = backends.default_backend() cipher = ciphers.Cipher(algorithm, mode=mode, backend=backend) super(CryptographyBlockCipherDecrypter, self).__init__() self._algorithm = algorithm self._cipher_context = cipher.decryptor()
def encryptKeyAES(options, manifestInput, encryptionInfo, payload): # Store the PSK ID pskId = manifestGet(manifestInput, 'resource.resource.manifest.payload.encryptionInfo.id.key', 'encryptionKeyId') if not pskId: LOG.critical('The aes-psk encryption mode requires a "encryptionKeyId" entry in the input JSON file') sys.exit(1) encryptionInfo["id"] = { "key" : codecs.decode(pskId, 'hex')} secret = options.payload_secret # Read the secret secret_data = utils.read_file(secret) if os.path.isfile(secret) else base64.b64decode(secret) if not secret_data: LOG.critical('The aes-psk encryption mode requires either a base64-encoded secret or a valid file to be passed via the "-s" option.') sys.exit(1) # generate an IV IV = os.urandom(nonceSize) # generate a new key key = os.urandom(nonceSize) cipherpayload = encryptClearText(payload, key, IV) # NOTE: In general, ECB is a poor choice, since it fails quickly to known-plaintext attacks. In this case, however, # ECB should be appropriate, since the plaintext is precisely one AES block, and it is comprised of high entropy # random data; therefore, the plaintext is never known. # Create the cipher object cipher = cryptoCiphers.Cipher(cryptoCiphers.algorithms.AES(bytes(secret_data)), cryptoCiphers.modes.ECB(), backend=backend) # nosec ignore bandit B404 keyEncryptor = cipher.encryptor() # Encrypt the plain text cipherKey = keyEncryptor.update(bytes(key)) + encryptor.finalize() return ciphertext return IV, cipherKey, cipherpayload
def test_DecryptionCorrectness(self): encryption_key = self.fernet._encryption_key signing_key = self.fernet._signing_key iv = os.urandom(16) ptx = "this is a super secret message" timestamp = struct.pack(">Q", int(time.time())) cipher = ciphers.Cipher(ciphers.algorithms.AES(encryption_key), ciphers.modes.CTR(iv), self._backend) encryptor = cipher.encryptor() ctx = encryptor.update(ptx) + encryptor.finalize() auth = cmac.CMAC(ciphers.algorithms.AES(signing_key), backend=default_backend()) auth.update(b"\x91" + timestamp + iv + ctx) mac = auth.finalize() # Assemble a ciphertext using token created by `cryptography`. Ensure Fermet # 0x91 can decrypt the ciphertext correctly. mocked_result = base64.urlsafe_b64encode(b"\x91" + timestamp + iv + ctx + mac) fernet_result = self.fernet.encrypt(ptx, iv) assert mocked_result == fernet_result assert self.fernet.decrypt(mocked_result) == ptx
def AES_from_key(key, iv=None, iv_block=16, encoding=fc.DEFAULT_ENC): """ Create an AES cipher from a key Args: key <bytes> - session key of size 8 or 16 Kwargs: iv <bytes> - initialization vector iv_block <int> - size of the random initialization vector for CBC mode encoding <str> - string coding Return: cipher <cryptography..Cipher object> - AES cipher """ if isinstance(key, str): key = key.encode(encoding) if len(key) == 8: key2 = key + key[::-1] elif len(key) == 16: key2 = key elif len(key) > 16: key2 = key[:16] else: fab_log('AES requires a cipher key of length of N16!', verbose_mode=5) return iv = iv if iv is not None else key2 AES_cipher = ciphers.Cipher(algorithm=ciphers.algorithms.AES(key2), mode=ciphers.modes.CBC(iv)) return AES_cipher
def _too_old(self, mode, backend): key = b"\x00" * 16 c = ciphers.Cipher(AES(key), mode, backend) encryptor = c.encryptor() buf = bytearray(32) with pytest.raises(NotImplementedError): encryptor.update_into(b"\x00" * 16, buf)
def _decrypt(value): try: decrypted = base64.b64decode(value) except binascii.Error: LOG.error("Invalid encrypted token: invalid base64") return if len(decrypted) < IV_BYTES_NEEDED + TAG_SIZE_BYTES: LOG.error("Invalid encrypted token: size check failure") return iv = decrypted[:IV_BYTES_NEEDED] tag = decrypted[IV_BYTES_NEEDED:IV_BYTES_NEEDED + TAG_SIZE_BYTES] decrypted = decrypted[IV_BYTES_NEEDED + TAG_SIZE_BYTES:] cipher = ciphers.Cipher(ciphers.algorithms.AES(SECRET_KEY), ciphers.modes.GCM(iv, tag), backend=default_backend()) decryptor = cipher.decryptor() try: decrypted = decryptor.update(decrypted) + decryptor.finalize() except cryptography.exceptions.InvalidTag: LOG.error("Invalid encrypted token: decryptor() failure") return try: decrypted = decrypted.decode() except UnicodeDecodeError: LOG.error("Invalid encrypted token: decode() failure") return try: return json.loads(decrypted) except json.JSONDecodeError: LOG.error("Invalid encrypted token: json.load() failure") return
def test_update_into_buffer_too_small_gcm(self, backend): key = b"\x00" * 16 c = ciphers.Cipher(AES(key), modes.GCM(b"\x00" * 12), backend) encryptor = c.encryptor() buf = bytearray(5) with pytest.raises(ValueError): encryptor.update_into(b"testing", buf)
def decrypt(self, data_enc, password, salt): """Decrypt data. :param data: `bytes` object with encrypted data. :param password: The password (will be fed to the KDF in use). :param salt: The salt (will be fed to the KDF in use). :return: `bytes` object with cleartext data. """ kdf = self.get_kdf(salt, self.key_size) key = kdf.derive(password) iv_bytes = self.block_size // 8 iv = data_enc[0:iv_bytes] data_enc = data_enc[iv_bytes:] unpadder = padding.PKCS7(self.block_size).unpadder() decryptor = (ciphers.Cipher(self.algorithm(key), modes.CBC(iv), backend=default_backend())).decryptor() try: data = decryptor.update(data_enc) + decryptor.finalize() return unpadder.update(data) + unpadder.finalize() except (ValueError, TypeError): # No padding oracle scenario in our usecase, but probably a good habit not to raise with root cause. raise_from(AgentCryptException("Decryption failed."), AgentCryptException("*redacted*"))
def _decrypt(self, data, iv=None): if iv is None: iv = data[:_iv_len] data = data[_iv_len:] cipher = cryptography.Cipher(self.cipher, mode=_mode[self.mode](iv), backend=self.backend).decryptor() return cipher.update(data)
def _decrypt(iv: bytes, tag: bytes, value: bytes, secret: bytes) -> bytes: cipher = ciphers.Cipher( ciphers.algorithms.AES(secret), ciphers.modes.GCM(iv, tag), backend=default_backend(), ) decryptor = cipher.decryptor() return decryptor.update(value) + decryptor.finalize()
def test_max_chunk_size_fits_in_int32(self, backend): # max chunk must fit in signed int32 or else a call large enough to # cause chunking will result in the very OverflowError we want to # avoid with chunking. key = b"\x00" * 16 c = ciphers.Cipher(AES(key), modes.ECB(), backend) encryptor = c.encryptor() backend._ffi.new("int *", encryptor._ctx._MAX_CHUNK_SIZE)
def aes_decryptor(key): '''Return AES cipher in CTR mode for *key*''' cipher = crypto_ciphers.Cipher( crypto_ciphers.algorithms.AES(key), crypto_ciphers.modes.CTR(nonce=bytes(16)), backend=crypto_backend) return cipher.decryptor()
def decipher(self, encrypted_data, symmetric_key): encrypted_data = base64.b64decode(encrypted_data) iv_size = 16 mode = ciphers.modes.GCM(b'\0' * iv_size, encrypted_data[-iv_size:], iv_size) decipher = ciphers.Cipher(ciphers.algorithms.AES(symmetric_key), mode, backend=self.backend).decryptor() decrypted = decipher.update(encrypted_data[:-16]) + decipher.finalize() decrypted = Token(decrypted) return decrypted
def encryptClearText(cleartext, key, iv): backend = cryptoBackends.default_backend() iv_counter = int.from_bytes(bytes(iv), byteorder='big') # Create the cipher object cipher = cryptoCiphers.Cipher(cryptoCiphers.algorithms.AES(key), cryptoCiphers.modes.CTR(iv), backend=backend) encryptor = cipher.encryptor() # Encrypt the plain text ciphertext = encryptor.update(bytes(cleartext)) + encryptor.finalize() return ciphertext
def test_invalid_mode_algorithm(): with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): ciphers.Cipher( ARC4(b"\x00" * 16), modes.GCM(b"\x00" * 12), ) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): ciphers.Cipher( ARC4(b"\x00" * 16), modes.CBC(b"\x00" * 12), ) with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): ciphers.Cipher( ARC4(b"\x00" * 16), modes.CTR(b"\x00" * 12), )
def encrypt(self, msg): padder = padding.PKCS7(ciphers.algorithms.AES.block_size).padder() padded_msg = padder.update(msg) + padder.finalize() iv = os.urandom(self._block_size_bytes) encryptor = ciphers.Cipher(ciphers.algorithms.AES(self._key), ciphers.modes.CBC(iv), self._backend).encryptor() _ciphertext = iv + encryptor.update(padded_msg) + encryptor.finalize() return _ciphertext
def test_invalid_backend(): pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): ciphers.Cipher( AES(b"AAAAAAAAAAAAAAAA"), modes.ECB(), pretend_backend, # type: ignore[arg-type] )
def test_update_into_gcm(self, backend): key = binascii.unhexlify(b"e98b72a9881a84ca6b76e0f43e68647a") iv = binascii.unhexlify(b"8b23299fde174053f3d652ba") ct = binascii.unhexlify(b"5a3c1cf1985dbb8bed818036fdd5ab42") pt = binascii.unhexlify(b"28286a321293253c3e0aa2704a278032") c = ciphers.Cipher(AES(key), modes.GCM(iv), backend) encryptor = c.encryptor() buf = bytearray(len(pt) + 15) res = encryptor.update_into(pt, buf) assert res == len(pt) assert bytes(buf)[:res] == ct encryptor.finalize() c = ciphers.Cipher(AES(key), modes.GCM(iv, encryptor.tag), backend) decryptor = c.decryptor() res = decryptor.update_into(ct, buf) decryptor.finalize() assert res == len(pt) assert bytes(buf)[:res] == pt
def test_update_into(self, params, backend): key = binascii.unhexlify(params["key"]) pt = binascii.unhexlify(params["plaintext"]) ct = binascii.unhexlify(params["ciphertext"]) c = ciphers.Cipher(AES(key), modes.ECB(), backend) encryptor = c.encryptor() buf = bytearray(len(pt) + 15) res = encryptor.update_into(pt, buf) assert res == len(pt) assert bytes(buf)[:res] == ct