def hkdf_sha256_32(ikm: bytes, salt: bytes, info: bytes) -> bytes: if HAS_CRYPTODOME: return CD_HKDF(ikm, 32, salt, CD_SHA256, context=info) if HAS_CRYPTOGRAPHY: return CG_HKDF(algorithm=CG_SHA256(), length=32, salt=salt, info=info, backend=CG_default_backend()).derive(ikm) raise Exception("no hkdf backend found")
def aes_encrypt_with_iv(key: bytes, iv: bytes, data: bytes) -> bytes: assert_bytes(key, iv, data) data = append_PKCS7_padding(data) if HAS_CRYPTODOME: e = CD_AES.new(key, CD_AES.MODE_CBC, iv).encrypt(data) elif HAS_CRYPTOGRAPHY: cipher = CG_Cipher(CG_algorithms.AES(key), CG_modes.CBC(iv), backend=CG_default_backend()) encryptor = cipher.encryptor() e = encryptor.update(data) + encryptor.finalize() else: aes_cbc = pyaes.AESModeOfOperationCBC(key, iv=iv) aes = pyaes.Encrypter(aes_cbc, padding=pyaes.PADDING_NONE) e = aes.feed(data) + aes.feed() # empty aes.feed() flushes buffer return e
def chacha20_encrypt(*, key: bytes, nonce: bytes, data: bytes) -> bytes: assert isinstance(key, (bytes, bytearray)) assert isinstance(nonce, (bytes, bytearray)) assert isinstance(data, (bytes, bytearray)) assert len(nonce) == 8, f"unexpected nonce size: {len(nonce)} (expected: 8)" if HAS_CRYPTODOME: cipher = CD_ChaCha20.new(key=key, nonce=nonce) return cipher.encrypt(data) if HAS_CRYPTOGRAPHY: nonce = bytes(8) + nonce # cryptography wants 16 byte nonces algo = CG_algorithms.ChaCha20(key=key, nonce=nonce) cipher = CG_Cipher(algo, mode=None, backend=CG_default_backend()) encryptor = cipher.encryptor() return encryptor.update(data) raise Exception("no chacha20 backend found")
def aes_decrypt_with_iv(key: bytes, iv: bytes, data: bytes) -> bytes: assert_bytes(key, iv, data) if HAS_CRYPTODOME: cipher = CD_AES.new(key, CD_AES.MODE_CBC, iv) data = cipher.decrypt(data) elif HAS_CRYPTOGRAPHY: cipher = CG_Cipher(CG_algorithms.AES(key), CG_modes.CBC(iv), backend=CG_default_backend()) decryptor = cipher.decryptor() data = decryptor.update(data) + decryptor.finalize() else: aes_cbc = pyaes.AESModeOfOperationCBC(key, iv=iv) aes = pyaes.Decrypter(aes_cbc, padding=pyaes.PADDING_NONE) data = aes.feed(data) + aes.feed() # empty aes.feed() flushes buffer try: return strip_PKCS7_padding(data) except InvalidPadding: raise InvalidPassword()