Implement cryptographic layer with PSK authentication, age encryption, and SHA-256 integrity
Add the complete cryptographic subsystem to pwr-core, providing three
layers of security for the protocol. The pre-shared key authentication
layer uses HMAC-SHA256 to compute challenge-response proofs. The client
proves knowledge of the PSK by sending HMAC(client_nonce || “pwr-auth-v1”,
PSK). The server responds with HMAC(client_nonce || server_nonce ||
“pwr-auth-v1”, PSK), enabling mutual authentication. Both nonces are
32-byte CSPRNG values generated per-connection using ring’s SystemRandom.
The PSK itself is a 256-bit random key stored as a hex string in both
config files. Helper functions handle hex encoding and decoding.
At-rest encryption uses age with X25519 key pairs. generate_age_identity
creates a fresh keypair, stores the secret identity at
~/.config/pwr/identity with 0o600 permissions, and returns the Bech32
public key for inclusion in .project.toml. The age_encrypt function takes
a public key string and plaintext, producing an age-format encrypted blob
using the one-shot Encryptor API. age_decrypt reverses this with an
identity, returning the original plaintext. Both functions propagate
structured errors for wrong keys, corrupted data, and unsupported formats.
Integrity verification uses SHA-256 via the sha2 crate. sha256_hex
hashes an in-memory buffer. sha256_file streams through a file in 64 KiB
chunks to support large projects without memory pressure. Ten tests
verify PSK randomness and hex round-trips, deterministic proof
computation (same inputs produce same outputs), mutual proof divergence
(client and server proofs differ), age encrypt-decrypt round-trips for
both empty and non-empty payloads, wrong-identity rejection, known-answer
SHA-256 vectors, and file hashing against the same known answer.
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.