pegh is a file encryption tool using passwords with modern, standardized, and authenticated encryption. It is simple, secure, and returns proper exit codes so you can tell whether encryption or decryption failed or not.
This implementation is built in C and can link with OpenSSL, libsodium, *or* libsodium AND OpenSSL in which case it falls back to OpenSSL's software AES implementation if the CPU does not support libsodium's. Every commit is built and tested in every combination and currently on 3 different architectures on Linux and 2 on Windows. The code aims to be fully portable C that should compile on anything with a C89 compiler (depending on crypto backend chosen).
*`pegh-$OS-$ARCH-openssl` - supports AES-256-GCM and Chacha20-Poly1305 on all CPUs
*`pegh-$OS-$ARCH-libsodium` - supports Chacha20-Poly1305 on all CPUs, but AES-256-GCM only on CPUs with hardware support for aes-ni
*`pegh-$OS-$ARCH-libsodium-openssl` - supports AES-256-GCM and Chacha20-Poly1305 on all CPUs, uses libsodium for everything if possible, but OpenSSL's software AES implementation if the CPU does not support aes-ni
Each chunk is fully decrypted and authenticated in memory before being written out as plaintext, so an attacker may be able to truncate a file, but NEVER flip any bytes or corrupt it. Order is enforced by the incrementing the IV, so re-ordered chunks would be decrypted with the wrong IV and would fail authentication. The last chunk is flagged with AAD so we can detect files truncated even on chunk boundaries.
So only fully correct chunks will be output, and only ever in the correct order, but if later chunks are corrupted or the file is truncated, pegh will exit with an error code, and then it's the responsibility of the user/consuming application to do the proper thing with the truncated file it recieved.
pegh implements a simple versioned file format so encryption parameters can change in the future. Numbers here are inclusive 0-based byte array indices, 0th byte is always version number, everything else depends on version number, currently versions 0 and 1 exist.
Version 0, scrypt key derivation, AES-256-GCM encryption, 43 byte header, 16 byte auth tag per chunk. The 12-byte IV for the first chunk is 0, and is incremented by 1 for each successive chunk, if it ever rolls back over to 0 encryption should be aborted (chunk size should be increased). The last chunk has Additional Authenticated Data (AAD) sent in, a single byte value 0, which is used to flag the last chunk and detect file truncation.
Version 1 has the exact same structure as version 0, except Chacha20-Poly1305 encryption instead of AES-256-GCM, key, IV, tag lengths are all the same.