How pSIONIUM works
What happens when you encrypt a file, what psion checks before it trusts one, what the design protects against, and how the scanner sorts your cryptography.
Encrypting a file
Six steps, each built from a standardized primitive. The default suite is shown; the CNSA suite replaces the hybrid exchange with ML-KEM-1024 and signs with ML-DSA-87.
- 1
A fresh key for every file
psion draws a random 256-bit file key and a random salt. Nothing is reused between files.
- 2
Post-quantum key exchange per recipient
For each recipient, an ephemeral X25519 exchange and an ML-KEM-768 encapsulation produce two shared secrets. HKDF-SHA-384 combines them with the whole exchange transcript into a key-encryption key, so the file stays safe while either algorithm holds.
- 3
The file key is wrapped
AES-256-GCM wraps the file key under each key-encryption key, bound to the header. Only listed recipients can unwrap it.
- 4
The header is sealed
An HMAC-SHA-384 over the header, keyed from the file key, protects the suite, chunk size, flags, salt and every recipient entry.
- 5
Data is encrypted in chunks
The payload is split into 64 KiB chunks, each sealed with AES-256-GCM under a nonce that carries the chunk number and a final-chunk flag. Reordering, dropping or appending chunks is detected, and files of any size stream in a few MB of memory.
- 6
Optionally, the sender signs
With --sign-with, an ML-DSA signature covers a SHA-384 hash of the complete header and payload, so recipients can prove who produced exactly this file.
Before psion trusts a file
It checks the header MAC before reading any data, opens every chunk in order, and fails if the file ends before its final chunk. With a signature, it verifies ML-DSA over everything it read.
When writing to disk, plaintext lands in a temporary file that only gets its real name once every check passes, so a damaged or forged file never leaves a half-written result behind. With --signed-by, unsigned files and other senders are refused.
Keys you can read
Every key is one line of text with a prefix that says what it is, so a public key can never be mistaken for a secret one.
| psionpk: | Public key | Share it so people can encrypt to you |
| psionvk: | Verifying key | Share it so people can check your signatures |
| psionsk: | Decryption key | Secret, kept in your identity file |
| psionss: | Signing key | Secret, kept in your identity file |
| psionpe: | Protected secrets | Argon2id (64 MiB) + AES-256-GCM; the default |
What it protects, and what it doesn’t
A summary of the threat model.
Protected
- File contents, against anyone who is not a listed recipient, including attackers who record files today and use a quantum computer later
- Integrity of every byte: changed, reordered, truncated or extended files are rejected
- Who sent a file, when signed: --signed-by refuses unsigned files and other signers
- Stolen identity files, which need the passphrase before they reveal anything
- Malformed or hostile input, which is rejected without crashing
Not protected
- A compromised computer while the identity is unlocked, or plaintext before encryption and after decryption
- Metadata: file sizes, timing, and recipient key identifiers are visible
- Deniability: a signature proves who signed to anyone with the verifying key
- Forward secrecy for stored files: rotate identities if a key may have leaked
How pSIONIUM Scan sorts what it finds
Every finding names the file and line, or the server, so you can judge it. Export a CycloneDX 1.6 cryptography bill of materials for your inventory, or fail a CI build when quantum-vulnerable code appears.
RSA, ECDSA, ECDH, Ed25519, X25519 alone, Diffie-Hellman, DSA
Plan migration to ML-KEM or hybrid X25519MLKEM768 for key exchange and ML-DSA for signatures. Start with data that must stay secret for years.
MD5, SHA-1, DES and 3DES, RC4, TLS 1.0 and 1.1
Replace now. These fail even without a quantum computer.
General crypto libraries, 128-bit keys
Check how they are used.
ML-KEM, ML-DSA, SLH-DSA, FN-DSA, XMSS/LMS, hybrid groups
Keep them.
Go deeper
Format specification
The .psen v2 layout, byte by byte.
Threat model
What is protected, against whom, and what is not.
Scanner guide
What pSIONIUM Scan finds and how to read it.
Security policy
How to report a vulnerability privately.
Changelog
What changed in each release.
Source code
Rust, Apache-2.0, with a second implementation in Go.