Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Using uacrypt

uacrypt encrypt/decrypt/hash (docs/TASKS.md T-16, docs/DECISIONS.md D-52) are the real, misuse-resistant top-level commands — mode, nonce, and algorithm are all hardcoded, nothing to misconfigure:

cargo build -p uacrypt --release
uacrypt keygen --out key.bin
uacrypt encrypt --key key.bin --in message.bin --out sealed.bin
uacrypt decrypt --key key.bin --in sealed.bin --out message.bin
uacrypt hash --in file.bin --out digest.bin

encrypt/decrypt have no message-length cap and stream --in/--out in fixed-size chunks — as of 2026-07-25 they’re built over dstu_core::crypto_secretstream (docs/TASKS.md T-40/T-70, docs/DECISIONS.md D-68), a genuinely chunked construction over hazmat::kalyna_gcm, not the earlier whole-buffer crypto_secretbox (docs/TASKS.md T-37, docs/DECISIONS.md D-51/D-63) - a large input file no longer means a correspondingly large in-memory buffer. Breaking wire-format change: a file the prior crypto_secretbox-backed encrypt produced cannot be read by this decrypt, and vice versa

  • acceptable pre-1.0. crypto_secretbox itself is unchanged and still available as a library primitive for whole-message use, just no longer what this CLI command uses. --key is a raw 32-byte file (crypto_secretstream::Key’s size) — uacrypt keygen --out key.bin generates one from the OS CSPRNG (docs/TASKS.md T-115). encrypt draws a fresh random header internally on every call and embeds it in --out; there is no --nonce/--header flag to supply or reuse by mistake. hash has no such limit either — it streams --in from disk in fixed-size chunks regardless of size, fixed to Kupyna-256 (32-byte digest, no --variant choice).

uacrypt sign-keygen/sign-pubkey/sign/verify (docs/TASKS.md T-124, docs/DECISIONS.md D-73) are the digital-signature equivalent, built over dstu_core::crypto_sign (DSTU 4145): a signature proves a file came from whoever holds the signing key and hasn’t been changed since — unlike encrypt, it does not hide the file’s contents, only attests to who signed it and that it’s unmodified. Every command below was run for real against the release binary before being written here:

uacrypt sign-keygen --out signing.key
uacrypt sign-pubkey --key signing.key --out verifying.key
uacrypt sign --key signing.key --in message.bin --out message.bin.sig
uacrypt verify --key verifying.key --in message.bin --sig message.bin.sig

sign-keygen’s output (signing.key, 21 raw bytes) is secret — keep it like any other private key. sign-pubkey derives the matching verifying.key (42 raw bytes) from it, safe to share or publish. verify prints nothing and exits 0 on a valid signature; on a tampered file, a tampered signature, or the wrong verifying key, it exits 1 with an error and writes nothing — it does not, and cannot, silently accept a mismatch:

$ uacrypt verify --key verifying.key --in message.bin --sig message.bin.sig
$ echo $?
0

$ echo "tampered" > message.bin
$ uacrypt verify --key verifying.key --in message.bin --sig message.bin.sig
uacrypt: verify: signature does not verify - message, signature, or key do not match
$ echo $?
1

uacrypt box-keygen/box-pubkey/box-seal/box-open (docs/TASKS.md T-178, docs/DECISIONS.md D-169) are public-key encryption, built over dstu_core::crypto_box (DSTU 9041, hybrid via KDF): unlike encrypt (which needs a shared symmetric key both sides already have), box-seal only needs the recipient’s public key — anyone can seal a message only the matching secret key can open:

uacrypt box-keygen --out box.key
uacrypt box-pubkey --key box.key --out box.pub
uacrypt box-seal --key box.pub --in message.bin --out message.bin.box
uacrypt box-open --key box.key --in message.bin.box --out message.bin

box-keygen’s output (box.key, 32 raw bytes) is secret. box-pubkey derives the matching box.pub (32 raw bytes, the curve point’s x-coordinate only) from it, safe to share or publish. box-seal/box-open are not memory-bounded yet — --in is read whole into memory, unlike encrypt/decrypt’s bounded-chunk streaming (see crypto_box’s own module doc for why).

What exists below this level: kalyna-block, a single-block (no mode, no padding), hazmat-scoped command added for a binary-level performance comparison (docs/PERFORMANCE.md, docs/DECISIONS.md D-31):

uacrypt kalyna-block encrypt --variant 128-128 --key key.bin --in block.bin --out ct.bin
uacrypt kalyna-block decrypt --variant 128-128 --key key.bin --in ct.bin --out pt.bin

--key/--in/--out are raw binary files of the variant’s exact byte length (16/32/64 bytes depending on variant — see --variant’s five values).

kalyna-ccm (docs/DECISIONS.md D-41) additionally encrypts/authenticates arbitrary-length short messages (plaintext and --aad each capped at 255 bytes — a sourced property of the construction, not a CLI restriction, see hazmat::kalyna_ccm’s doc comment) using a provisional, dual-oracle- verified Kalyna-alone CCM mode, not yet confirmed against the primary DSTU 7624:2014 text:

uacrypt kalyna-ccm encrypt --variant 128-128 --key key.bin --nonce nonce.bin --aad aad.bin --in msg.bin --out ct.bin --tag tag.bin
uacrypt kalyna-ccm decrypt --variant 128-128 --key key.bin --nonce nonce.bin --aad aad.bin --in ct.bin --out pt.bin --tag tag.bin

--nonce is a raw file of exactly the variant’s block length (16/32/64 bytes) — but it’s an output on encrypt, not an input: encrypt generates a fresh random nonce itself (via the OS CSPRNG) and writes it there, so there is nothing for you to supply or accidentally reuse. decrypt reads --nonce back (the value encrypt produced) as an input, same as --tag. --aad is optional (an empty AAD is used if omitted); decrypt verifies the tag before writing --out and fails without writing anything on a mismatch. See docs/DECISIONS.md D-40 for why a random nonce is safe here (128 bits minimum across all five variants) and its per-key message-count guideline.

Neither kalyna-block nor kalyna-ccm is the encrypt/decrypt surface above - both stay as lower-level, hazmat-scoped tools (kalyna-block for exactly one block, kalyna-ccm for full control over variant/nonce/AAD/tag as separate files) for anyone who explicitly wants that.