Replace Argon2 with salted SHA-256 password hashes

This commit is contained in:
2026-10-28 13:55:29 +00:00
parent ad168aae63
commit a33549e81a
7 changed files with 157 additions and 250 deletions
+14 -6
View File
@@ -9,7 +9,7 @@ Hermes is a minimal HTTP/1.1 forward proxy written in Rust. It supports streamin
- Streaming request and response bodies
- Upstream connection pooling and configurable timeouts
- Ordered allow/deny ACLs using Basic authentication and/or client IP networks
- Salted Argon2id password hashes; plaintext passwords are never stored in YAML
- Fast salted SHA-256 password hashes; plaintext passwords are never stored in YAML
- Removal of standard and `Connection`-nominated hop-by-hop headers
- W3C Trace Context extraction and injection for plain HTTP traffic
- Structured, trace-correlated logs on stdout and through OTLP
@@ -47,7 +47,7 @@ acl:
users:
alice:
password_hash: "$argon2id$v=19$m=19456,t=2,p=1$..."
password_hash: "$hermes-sha256$v=1$..."
rules:
- name: alice
@@ -65,7 +65,7 @@ acl:
| `connect_timeout_ms` | `10000` | TCP connection timeout for `CONNECT` and the HTTP connector |
| `upstream_timeout_ms` | `30000` | Time limit for receiving upstream HTTP response headers |
| `acl.default_action` | `deny` | Action when no rule matches |
| `acl.users` | empty | Usernames and Argon2id PHC password hashes |
| `acl.users` | empty | Usernames and salted SHA-256 password hashes |
| `acl.rules` | empty | Ordered ACL rules |
Configuration is loaded and validated at startup. Unknown fields, invalid CIDRs, duplicate or empty rules, references to unknown users, and unsupported password hashes prevent startup. Restart Hermes to apply configuration changes.
@@ -98,11 +98,19 @@ curl --proxy http://127.0.0.1:8080 \
cargo run -- hash-password
```
The helper prompts without echoing, confirms the password, and prints a PHC string such as `$argon2id$v=19$...`. Copy the complete string into the user's `password_hash` field. The PHC string includes a cryptographically random salt, the Argon2id parameters, and the hash; no separate salt field is needed. Running the helper twice for the same password produces different salted hashes.
The helper prompts without echoing, confirms the password, and prints a versioned string in this format:
Password verification uses bounded blocking work so Argon2 does not stall Tokio's async runtime. Decoded password buffers are zeroized after use.
```text
$hermes-sha256$v=1$<base64-salt>$<base64-digest>
```
**Basic authentication is not encrypted in transit.** Argon2 protects the stored password hash, but a client sending Basic credentials over cleartext HTTP exposes them to the network. Use Basic authentication only on localhost or a trusted private network unless downstream TLS is added. Do not expose Hermes publicly without appropriate network controls.
Copy the complete string into the user's `password_hash` field. Hermes computes `SHA-256(salt || password)` using a cryptographically random 16-byte salt. No separate salt field is needed, and running the helper twice for the same password produces different salted hashes. Argon2id hashes from earlier configurations are not supported; regenerate them with the helper.
Password verification is synchronous and inexpensive, and digest comparisons are constant-time. Decoded password buffers are zeroized after use.
**Fast password hashes can be brute-forced offline.** Anyone who obtains the YAML can efficiently guess passwords and compare them with the stored salted SHA-256 digest. Use strong, unique passwords and protect the configuration file; this format deliberately trades password-cracking resistance for cheap request verification.
**Basic authentication is not encrypted in transit.** A client sending Basic credentials over cleartext HTTP exposes them to the network. Use Basic authentication only on localhost or a trusted private network unless downstream TLS is added. Do not expose Hermes publicly without appropriate network controls.
## OpenTelemetry