fix: is_encrypted_record never false-negatives at odd traversal_level; encrypt_data rejects nested non-str keys
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.8
|
||||
envelope_crypto @ git+ssh://git@git.rethinkstudios.io/rethink-public/envelope_crypto.git@v0.1.10
|
||||
```
|
||||
|
||||
Direct:
|
||||
|
||||
```bash
|
||||
pip install "envelope_crypto @ git+ssh://git@git.rethinkstudios.io/rethink-public/envelope_crypto.git@v0.1.8"
|
||||
pip install "envelope_crypto @ git+ssh://git@git.rethinkstudios.io/rethink-public/envelope_crypto.git@v0.1.10"
|
||||
```
|
||||
|
||||
Requires `cryptography` (pulled transitively).
|
||||
|
||||
Drop the `@v0.1.8` suffix from the line above to install the latest unpinned.
|
||||
Drop the `@v0.1.10` suffix from the line above to install the latest unpinned.
|
||||
|
||||
## First-time setup
|
||||
|
||||
@@ -80,10 +80,12 @@ 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.
|
||||
Dict keys must be `str`, at any nesting depth (including a dict nested inside a list
|
||||
or tuple). `encrypt_data` raises `TypeError` on a non-str key anywhere in the payload
|
||||
(e.g. an int-keyed dict of Discord snowflakes, even nested a few levels down) 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
|
||||
@@ -98,11 +100,11 @@ if is_encrypted_record(doc):
|
||||
doc = decrypt_record(crypto, doc)
|
||||
```
|
||||
|
||||
`is_encrypted_record` falls back to an unbounded-depth scan once `traversal_level` is
|
||||
exhausted, so it reliably reports `True` for a blob left behind by a shallower
|
||||
`is_encrypted_record` always falls back to an unbounded-depth scan whenever its bounded
|
||||
pass finds nothing, so it reliably reports `True` for a blob left behind by a shallower
|
||||
`decrypt_record`/`reencrypt` call — safe to use as a leftover-detecting audit after
|
||||
rotation, regardless of how deep the blob is nested, including inside a list or
|
||||
tuple at any depth.
|
||||
rotation, regardless of how deep the blob is nested (including inside a list or tuple
|
||||
at any depth) and regardless of which `traversal_level` you pass; it never false-negatives.
|
||||
|
||||
Naming aliases (same objects): `EnvelopeCrypto` = `DocumentCrypto` = `RecordCrypto`
|
||||
= `PCICrypto` (deprecated legacy alias). `decrypt_record` = `decrypt_document` =
|
||||
|
||||
Reference in New Issue
Block a user