updated README

This commit is contained in:
2026-06-10 01:41:41 +02:00
parent 6febf8ee22
commit 90707cc364
+169 -9
View File
@@ -1,12 +1,172 @@
# fcry - [f]ile[cry]pt
A file en-/decryption tool for easy use.
# fcry - filecrypt
Currently `fcry` uses `ChaCha20Poly1305` ([RFC 8439](https://datatracker.ietf.org/doc/html/rfc8439)) as [AEAD](https://en.wikipedia.org/wiki/Authenticated_encryption) cipher provided by the [chacha20poly1305](https://docs.rs/chacha20poly1305/latest/chacha20poly1305/) crate.
`fcry` encrypts and decrypts files with an authenticated chunked format. New
files use XChaCha20-Poly1305 in a STREAM-style construction: a 19-byte random
nonce prefix, a 32-bit chunk counter, and a last-chunk bit form each 24-byte
XChaCha nonce. Every chunk authenticates the full file header as AEAD
associated data.
## Status
Currently `fcry` is __not thoroughly tested__ and in __early stages of development__.
There is a chance, that something is broken as of now.
Encryption __seems__ to work, but due to a possible lack of understanding of some underlying methods
(or misinterpretation) it could theoretically be not effective at all.
The tool is intended for local file encryption, scripted backups, and
streaming-friendly decrypts. It is not a general archive format, does not hide
file size, and does not protect plaintext after another process has received
it.
See [TODO.md](/ddidderr/fcry/src/branch/main/TODO.md) for further information.
## Usage
Encrypt with an interactive passphrase:
```sh
fcry -i plain.bin -o plain.bin.fcry --passphrase
```
Decrypt with the same passphrase:
```sh
fcry -d -i plain.bin.fcry -o plain.bin --passphrase
```
Use a raw 32-byte key file instead of a passphrase:
```sh
fcry -i plain.bin -o plain.bin.fcry --key-file key.bin
fcry -d -i plain.bin.fcry -o plain.bin --key-file key.bin
```
For non-interactive passphrase use:
```sh
FCRY_PASSWORD='correct horse battery staple' \
fcry -i plain.bin -o plain.bin.fcry --passphrase-env FCRY_PASSWORD
```
`--passphrase-env` is useful for automation, but the environment variable can
remain visible to the current process environment and platform tooling. Prefer
interactive entry or a protected key file when possible.
## Safety Properties
- File outputs are written to private, randomly named temporary files and are
renamed into place only after encryption or decryption succeeds. Existing
outputs require `--force`, except for the self-replacement case that is
handled through the temporary file.
- New passphrase encryptions use Argon2id by default with 1024 MiB of memory,
2 passes, and 4 lanes. Passphrases must be non-empty and at least 12 UTF-8
bytes unless `--allow-weak-kdf` is explicitly supplied for tests or legacy
interop.
- Decryption enforces a memory ceiling for Argon2id headers. The default cap is
the lower of 4096 MiB, the architecture limit, and available Linux memory
when that can be detected. Override it with `--max-argon-memory-mib` only for
files you trust.
- Chunk size is bounded to `1..=64 MiB`. Worker threads are capped at 256, and
the pipeline bounds in-flight chunk memory.
- v3 files carry a key commitment derived from the stretched key and committed
header fields. This gives a fast, clear wrong-key failure before chunk
processing and prevents stripping or downgrading the commitment without
authentication failure.
- On Unix, `fcry` makes a best-effort call to disable core dumps for the process
before handling secrets.
## Format
The current on-disk format version is v3.
```text
magic "fcry" 4 bytes
version u8 1
alg_id u8 1 (1 = XChaCha20-Poly1305)
flags u8 1
reserved u8 1 (must be 0)
chunk_size u32 LE 4
kdf_id u8 1 (0 = raw key, 1 = Argon2id)
kdf_params variable
nonce_prefix [u8; 19]
plaintext_length u64 LE only when flags bit 0 is set
key_commitment [u8; 32] only when flags bit 1 is set
ciphertext chunks each plaintext chunk plus a 16-byte Poly1305 tag
```
The encoded header is AEAD associated data for every chunk. Changing the chunk
size, KDF parameters, nonce prefix, committed plaintext length, key commitment,
or other header bytes causes authentication failure.
Version history:
- v1: no flags and no committed plaintext length.
- v2: adds the length-committed flag and optional `plaintext_length`.
- v3: requires the key-commitment flag and stores the 32-byte key commitment.
Regular file encryption commits `plaintext_length` in the header. Stdin
encryption cannot know the final length up front, so stdin-produced files do
not support random-access decrypt.
## Streaming And Ranges
Normal decrypt-to-stdout emits each plaintext chunk after that chunk has
authenticated. This means a truncated ciphertext can produce an authentic
prefix on stdout before the final truncation error is reported. That is
inherent to chunked streaming AE when bytes are released immediately.
Use `--buffer-verify` when decrypting to stdout if downstream consumers must
not see any plaintext until the whole file has authenticated:
```sh
fcry -d -i plain.bin.fcry --passphrase --buffer-verify > plain.bin
```
`--buffer-verify` writes plaintext to a private temporary file first, verifies
the complete ciphertext, and copies to stdout only after success. File outputs
already get atomic temporary-file behavior, so `--buffer-verify` is only valid
for decrypt-to-stdout.
Random-access decrypt requires `--decrypt`, `--input-file`, `--offset`, and
`--length`, and the input must have a length-committed header:
```sh
fcry -d -i plain.bin.fcry --passphrase --offset 1048576 --length 4096 > slice.bin
```
A successful range decrypt authenticates the requested chunks and header. It
does not prove that the rest of the file is present or untampered. Use a full
decrypt when you need whole-file integrity. `--length 0` is rejected because it
would authenticate no chunks.
## Threat Model
`fcry` aims to provide confidentiality and integrity for file contents against
an attacker who can read, copy, truncate, replace, or modify ciphertext files
after encryption. With passphrase mode, offline guessing is still possible; the
Argon2id parameters make each guess expensive but cannot make a weak passphrase
safe.
The format authenticates all header fields that affect decryption, including
KDF parameters, chunk size, nonce prefix, committed plaintext length, and key
commitment. Unknown header flags and unsupported algorithms are rejected.
The following are explicit non-goals:
- Hiding plaintext length or access patterns. `plaintext_length` is cleartext
for regular-file encryptions, and ciphertext length already reveals an
approximate plaintext size. There is no padding scheme.
- Preventing plaintext exposure after successful decrypt. Plaintext written to
stdout, files, pipes, shell history, terminals, swap, backups, or downstream
tools is outside `fcry`'s control.
- Protecting plaintext chunk buffers from every local memory-forensics route.
Keys and passphrases use protected/zeroizing storage where practical, and
chunk buffers are zeroized on drop, but decrypted plaintext necessarily exists
in ordinary process memory while being processed.
- Disabling Windows Error Reporting or minidumps. Unlike Unix core dumps, those
are controlled by per-machine Windows policy; `fcry` records this as an
operator/deployment responsibility rather than changing host-wide policy.
- Recovering from loss of the passphrase or raw key file. There is no escrow or
backdoor.
## Operational Notes
- Keep backups of important plaintext until you have verified the encrypted
file and your recovery path.
- Store raw key files with restrictive permissions. On Unix, `fcry` warns when
a key file is group/world accessible.
- Use `--allow-weak-kdf` only for tests or compatibility with old intentionally
weak files.
- Use `--temp-dir` when the default temporary-file location is not acceptable
for decrypt-to-stdout buffering or output staging.