fix: is_file drift on decrypt_aes_key_with_rsa and non-str dict key coercion
self_test(is_file=False) only forwarded is_file to the public-key wrap; decrypt_aes_key_with_rsa had no is_file parameter and always open()'d its argument, so a PEM string was opened as a filename, misdiagnosing a good keypair as non-pairing and leaking the private key PEM into the FileNotFoundError traceback. decrypt_aes_key_with_rsa now takes is_file (default True, preserving current callers), and self_test threads it through to both key loads. encrypt_data json.dumps a dict without checking key types, silently stringifying int/float/bool/None keys (e.g. snowflake-int-keyed dicts), so a decrypt round-trip silently lost the original key. encrypt_data now raises TypeError on a non-str key instead of coercing it. Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
@@ -11,18 +11,18 @@ and storage-agnostic.
|
||||
`requirements.txt`:
|
||||
|
||||
```
|
||||
envelope_crypto @ git+ssh://git@git.rethinkstudios.io/rethink-public/envelope_crypto.git@v0.1.4
|
||||
envelope_crypto @ git+ssh://git@git.rethinkstudios.io/rethink-public/envelope_crypto.git@v0.1.5
|
||||
```
|
||||
|
||||
Direct:
|
||||
|
||||
```bash
|
||||
pip install "envelope_crypto @ git+ssh://git@git.rethinkstudios.io/rethink-public/envelope_crypto.git@v0.1.4"
|
||||
pip install "envelope_crypto @ git+ssh://git@git.rethinkstudios.io/rethink-public/envelope_crypto.git@v0.1.5"
|
||||
```
|
||||
|
||||
Requires `cryptography` (pulled transitively).
|
||||
|
||||
Drop the `@v0.1.4` suffix from the line above to install the latest unpinned.
|
||||
Drop the `@v0.1.5` suffix from the line above to install the latest unpinned.
|
||||
|
||||
## First-time setup
|
||||
|
||||
@@ -66,6 +66,13 @@ bot.crypto = crypto
|
||||
The `keys` schema (`_id` = fingerprint, `key` = wrapped) is the **caller's** choice;
|
||||
this lib only produces `(fingerprint, wrapped_key)`.
|
||||
|
||||
`decrypt_aes_key_with_rsa` (like `encrypt_aes_key_with_rsa` and
|
||||
`get_rsa_key_fingerprint`) takes `is_file` (default `True`). Pass `is_file=False` to
|
||||
hand it PEM/OpenSSH key data directly — e.g. a private key sourced from a vault —
|
||||
instead of a file path. `self_test` threads the same `is_file` through to both the
|
||||
public and private key it loads, so `self_test(pub_pem, priv_pem, is_file=False)`
|
||||
round-trips two in-memory PEM strings rather than treating them as paths.
|
||||
|
||||
## Encrypt / decrypt
|
||||
|
||||
```python
|
||||
@@ -73,6 +80,11 @@ enc = crypto.encrypt_data({"ssn": "..."}) # -> {"secure": True, "iv": ...,
|
||||
plain = crypto.decrypt_data(enc) # -> {"ssn": "..."}
|
||||
```
|
||||
|
||||
Dict keys must be `str`. `encrypt_data` raises `TypeError` on a non-str key (e.g. an
|
||||
int-keyed dict of Discord snowflakes) instead of silently stringifying it — the
|
||||
underlying JSON encoding has no other key type, so a coerced key would come back out
|
||||
of `decrypt_data` as a `str` and no longer match the original lookup key.
|
||||
|
||||
For whole records: `decrypt_record(crypto, doc)` decrypts every `{secure, iv, data}`
|
||||
field (nested up to `traversal_level`, default 2); `is_encrypted_record(doc)` reports
|
||||
whether any encrypted field exists. Both also detect `doc` itself being a bare
|
||||
|
||||
Reference in New Issue
Block a user