Threat model, stated plainly.
SECURITY.md
is the source of truth; this is the readable summary. A cryptographic library that will not say
what it does not protect is not worth trusting.
In scope
-
Timing attacks on reveal
Commitment comparison uses hmac.compare_digest — constant-time, no early exit on the first differing byte.
-
Weak randomness
Salts and the ZKP nonce k come from secrets (the OS CSPRNG). The random module is never imported in the runtime path.
-
Insecure hash selection
md5 and sha1 raise SecurityError at construction. Anything off the eight-algorithm allowlist raises ValidationError.
-
Injection via input
Inputs are validated before use; validation.py centralizes the checks.
-
Directory traversal in the CLI
Commitment names are sanitized before being used as filenames.
-
Plaintext at rest
The secure CLI never writes the committed value to disk; entry is via getpass, and files are created mode 0600.
Out of scope
-
Physical / hardware attacks
An adversary with physical access to the device holding the salt is out of scope. Use a hardware-isolated keystore.
-
Kernel compromise
A compromised OS can read process memory; no userspace library can defend against that.
-
Long-term key management
The library manages commitments, not keys. Reusing a ZKP public key across commitments is your protocol’s responsibility (and discouraged).
-
Secure network transport
The library produces bytes. How you move them between parties — TLS, gossip, a transaction — is your problem.
Table 1 — hash allowlist
| Identifier | Output | Status |
|---|---|---|
| sha256 | 32 bytes | Default · allowed |
| sha384 · sha512 | 48 · 64 bytes | Allowed |
| sha3_256 · sha3_384 · sha3_512 | 32 · 48 · 64 bytes | Allowed |
| blake2b · blake2s | 64 · 32 bytes | Allowed |
| md5 · sha1 | — | Rejected — SecurityError |
Security FAQ
Has commit-reveal had a formal external audit?
No, and we do not claim one. It ships with mypy strict, Hypothesis property tests, a clean Bandit scan, and an explicit SECURITY.md threat model — that is the floor, not a substitute for an audit.
Is the secp256k1 implementation constant-time?
No. It is an affine, textbook implementation intended for protocol prototyping and low-throughput use. It is not competitive with a native binding for sustained signing, and it is not constant-time at the scalar-multiply level.
Why reject MD5 and SHA-1 instead of just warning?
Because a warning is easy to ignore. Selecting md5 or sha1 raises SecurityError at construction time, so a broken commitment can never be created by accident.
Disclosure
Found something? Tell us first.
See SECURITY.md for the coordinated-disclosure address, or
contact the maintainers.