refactor: hoist shared RSA-OAEP padding to a constant; restore encrypt_aes_key_with_rsa docstring
hoists the byte-identical OAEP(MGF1(SHA256), SHA256, label=None) construction out of encrypt_aes_key_with_rsa and decrypt_aes_key_with_rsa into a module-level _OAEP_PADDING constant so a future scheme change lands in one place instead of two in lockstep. also restores encrypt_aes_key_with_rsa's Args/Returns/Raises docstring block, matching its four siblings, after Wave-1 over-stripped it to bare prose. Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "envelope_crypto"
|
name = "envelope_crypto"
|
||||||
version = "0.1.8"
|
version = "0.1.9"
|
||||||
description = "Envelope encryption (RSA-OAEP wrapped AES-256-GCM) for dict records — config-free, storage-agnostic, installable."
|
description = "Envelope encryption (RSA-OAEP wrapped AES-256-GCM) for dict records — config-free, storage-agnostic, installable."
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ from cryptography.hazmat.primitives.serialization import load_ssh_public_key
|
|||||||
|
|
||||||
_log = logging.getLogger(__name__)
|
_log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
_OAEP_PADDING = padding.OAEP(
|
||||||
|
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
||||||
|
algorithm=hashes.SHA256(),
|
||||||
|
label=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _password_mismatch_message(pw: Optional[bytes]) -> str:
|
def _password_mismatch_message(pw: Optional[bytes]) -> str:
|
||||||
"""clear ValueError text for a TypeError raised by a password/encryption mismatch"""
|
"""clear ValueError text for a TypeError raised by a password/encryption mismatch"""
|
||||||
@@ -263,10 +269,22 @@ class EnvelopeCrypto:
|
|||||||
def encrypt_aes_key_with_rsa(
|
def encrypt_aes_key_with_rsa(
|
||||||
self, aes_key: bytes, rsa_key: str, is_file: bool = True
|
self, aes_key: bytes, rsa_key: str, is_file: bool = True
|
||||||
) -> Tuple[str, str]:
|
) -> Tuple[str, str]:
|
||||||
"""wrap an AES key with an RSA public key; returns (fingerprint, wrapped_b64)
|
"""wrap an AES key with an RSA public key
|
||||||
|
|
||||||
raises ValueError if rsa_key is not an RSA key (this lib is RSA-envelope only;
|
Args:
|
||||||
e.g. an Ed25519/EC key loads and fingerprints fine but cannot wrap).
|
aes_key: the AES data key to wrap.
|
||||||
|
rsa_key: path to (or, if is_file=False, raw PEM/OpenSSH data of)
|
||||||
|
the RSA public key to wrap with.
|
||||||
|
is_file: True (default) treats rsa_key as a path.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(fingerprint, wrapped_b64): the wrapping key's fingerprint and the
|
||||||
|
RSA-OAEP wrapped key, base64-encoded.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: rsa_key is not an RSA key (this lib is RSA-envelope
|
||||||
|
only; e.g. an Ed25519/EC key loads and fingerprints fine but
|
||||||
|
cannot wrap), or is malformed.
|
||||||
"""
|
"""
|
||||||
if is_file:
|
if is_file:
|
||||||
with open(rsa_key, "rb") as key_file:
|
with open(rsa_key, "rb") as key_file:
|
||||||
@@ -277,14 +295,7 @@ class EnvelopeCrypto:
|
|||||||
public_key = _load_public_key(key_data)
|
public_key = _load_public_key(key_data)
|
||||||
_require_rsa(public_key)
|
_require_rsa(public_key)
|
||||||
|
|
||||||
wrapped = public_key.encrypt(
|
wrapped = public_key.encrypt(aes_key, _OAEP_PADDING)
|
||||||
aes_key,
|
|
||||||
padding.OAEP(
|
|
||||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
|
||||||
algorithm=hashes.SHA256(),
|
|
||||||
label=None,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
fingerprint = _fingerprint_of(public_key)
|
fingerprint = _fingerprint_of(public_key)
|
||||||
wrapped_b64 = base64.b64encode(wrapped).decode()
|
wrapped_b64 = base64.b64encode(wrapped).decode()
|
||||||
_log.info("wrapped data key for fingerprint %s", fingerprint[:8])
|
_log.info("wrapped data key for fingerprint %s", fingerprint[:8])
|
||||||
@@ -321,14 +332,7 @@ class EnvelopeCrypto:
|
|||||||
_require_rsa(private_key)
|
_require_rsa(private_key)
|
||||||
|
|
||||||
wrapped = base64.b64decode(encrypted_key_base64)
|
wrapped = base64.b64decode(encrypted_key_base64)
|
||||||
aes_key = private_key.decrypt(
|
aes_key = private_key.decrypt(wrapped, _OAEP_PADDING)
|
||||||
wrapped,
|
|
||||||
padding.OAEP(
|
|
||||||
mgf=padding.MGF1(algorithm=hashes.SHA256()),
|
|
||||||
algorithm=hashes.SHA256(),
|
|
||||||
label=None,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
_log.info("unwrapped data key with RSA private key")
|
_log.info("unwrapped data key with RSA private key")
|
||||||
return aes_key
|
return aes_key
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user