Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Changelog

.. note:: This version is not yet released and is under active development.

* :meth:`~cryptography.hazmat.primitives.hpke.Suite.encrypt` and
:meth:`~cryptography.hazmat.primitives.hpke.Suite.decrypt` accept ``aad``,
additional authenticated data for the AEAD. It is separate from ``info``,
which is mixed into the key schedule.
* :func:`~cryptography.hazmat.primitives.serialization.load_der_private_key`
and :func:`~cryptography.hazmat.primitives.serialization.load_pem_private_key`
now accept :rfc:`5958` ``OneAsymmetricKey`` (PKCS8 version 2).
Expand Down
9 changes: 7 additions & 2 deletions docs/hazmat/primitives/hpke.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ specifying auxiliary authenticated information.
:param aead: The authenticated encryption algorithm.
:type aead: :class:`AEAD`

.. method:: encrypt(plaintext, public_key, info=b"")
.. method:: encrypt(plaintext, public_key, info=b"", aad=b"")

Encrypt a message using HPKE.

Expand All @@ -70,10 +70,13 @@ specifying auxiliary authenticated information.
and :class:`MLKEM1024P384PublicKey` for :attr:`KEM.MLKEM1024_P384`.
:param bytes info: Application-specific context string for binding the
encryption to a specific application or protocol.
:param bytes aad: Additional authenticated data passed to the AEAD.
It is authenticated with the ciphertext and is not mixed into the
key schedule. This is a different input from ``info``.
:returns: The encapsulated key concatenated with ciphertext (enc || ct).
:rtype: bytes

.. method:: decrypt(ciphertext, private_key, info=b"")
.. method:: decrypt(ciphertext, private_key, info=b"", aad=b"")

Decrypt a message using HPKE.

Expand All @@ -93,6 +96,8 @@ specifying auxiliary authenticated information.
and :class:`MLKEM1024P384PrivateKey` for :attr:`KEM.MLKEM1024_P384`.
:param bytes info: Application-specific context string (must match the
value used during encryption).
:param bytes aad: Additional authenticated data (must match the value
used during encryption).
:returns: The decrypted plaintext.
:rtype: bytes
:raises cryptography.exceptions.InvalidTag: If decryption fails.
Expand Down
2 changes: 2 additions & 0 deletions src/cryptography/hazmat/bindings/_rust/openssl/hpke.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class Suite:
| MLKEM768X25519PublicKey
| MLKEM1024P384PublicKey,
info: Buffer | None = None,
aad: Buffer | None = None,
) -> bytes: ...
def decrypt(
self,
Expand All @@ -81,6 +82,7 @@ class Suite:
| MLKEM768X25519PrivateKey
| MLKEM1024P384PrivateKey,
info: Buffer | None = None,
aad: Buffer | None = None,
) -> bytes: ...

def _encrypt_with_aad(
Expand Down
10 changes: 6 additions & 4 deletions src/rust/src/backend/hpke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,26 +1031,28 @@ impl Suite {
})
}

#[pyo3(signature = (plaintext, public_key, info=None))]
#[pyo3(signature = (plaintext, public_key, info=None, aad=None))]
fn encrypt<'p>(
&self,
py: pyo3::Python<'p>,
plaintext: CffiBuf<'_>,
public_key: &pyo3::Bound<'p, pyo3::PyAny>,
info: Option<CffiBuf<'_>>,
aad: Option<CffiBuf<'_>>,
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyBytes>> {
self.encrypt_inner(py, plaintext, public_key, info, None)
self.encrypt_inner(py, plaintext, public_key, info, aad)
}

#[pyo3(signature = (ciphertext, private_key, info=None))]
#[pyo3(signature = (ciphertext, private_key, info=None, aad=None))]
fn decrypt<'p>(
&self,
py: pyo3::Python<'p>,
ciphertext: CffiBuf<'_>,
private_key: &pyo3::Bound<'p, pyo3::PyAny>,
info: Option<CffiBuf<'_>>,
aad: Option<CffiBuf<'_>>,
) -> CryptographyResult<pyo3::Bound<'p, pyo3::types::PyBytes>> {
self.decrypt_inner(py, ciphertext, private_key, info, None)
self.decrypt_inner(py, ciphertext, private_key, info, aad)
}
}

Expand Down
10 changes: 5 additions & 5 deletions tests/hazmat/primitives/test_hpke.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,14 +400,14 @@ def test_wrong_aad_fails(self):
sk_r = x25519.X25519PrivateKey.generate()
pk_r = sk_r.public_key()

ciphertext = rust_openssl.hpke._encrypt_with_aad(
suite, b"Secret message", pk_r, aad=b"correct aad"
ciphertext = suite.encrypt(b"Secret message", pk_r, aad=b"correct aad")
assert (
suite.decrypt(ciphertext, sk_r, aad=b"correct aad")
== b"Secret message"
)

with pytest.raises(InvalidTag):
rust_openssl.hpke._decrypt_with_aad(
suite, ciphertext, sk_r, aad=b"wrong aad"
)
suite.decrypt(ciphertext, sk_r, aad=b"wrong aad")

def test_info_mismatch_fails(self):
suite = Suite(KEM.X25519, KDF.HKDF_SHA256, AEAD.AES_128_GCM)
Expand Down
Loading