updated README
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user