document usage and pegh file format

This commit is contained in:
Travis Burtrum 2019-12-26 01:19:05 -05:00
parent 82114dece7
commit 6fc9e1d871
3 changed files with 90 additions and 12 deletions

View File

@ -1,10 +1,66 @@
pegh
----
pegh is a file encryption tool using passwords and authenticated encryption. It is simple, secure, and returns proper exit codes so you can tell whether encryption or decryption failed or not.
[pegh](http://klingonska.org/dict/?q=tlh%3Apegh) is Klingon for secret
pegh is a file encryption tool using passwords and authenticated encryption. It returns proper exit codes so you can tell whether encryption/decryption failed or not.
Usage
-----
pegh implements a simple versioned file format so encryption parameters can change in the future, but currently version 0 derives a 256-bit key from your password with scrypt, and uses that to encrypt/decrypt your file with aes-256-gcm.
```sh
# encrypt file.txt to file.txt.pegh with password SUPER_SECRET_1942
pegh -e SUPER_SECRET_1942 <file.txt >file.txt.pegh
todo: document usage and file format
# decrypt file.txt.pegh to file.txt with password SUPER_SECRET_1942
pegh -d SUPER_SECRET_1942 <file.txt.pegh >file.txt
```
The easiest way to scale cost/time it takes for bruteforcing is simply to continue doubling -s, on both encryption and decryption commands.
full help:
```
$ pegh -h
usage: pegh [-demNrpshV] password
-e encrypt stdin to stdout, default mode
-d decrypt stdin to stdout
-m <max_mb> maximum megabytes of ram to use when deriving key from password
with scrypt, applies for encryption AND decryption, must
almost linearly scale with -N, if too low operation will fail,
default: 64
-N <num> scrypt parameter N, only applies for encryption, default 32768
this is rounded up to the next highest power of 2
-r <num> scrypt parameter r, only applies for encryption, default 8
-p <num> scrypt parameter p, only applies for encryption, default 1
-s <num> multiplication factor to apply to both -N and -m for easy
work scaling, rounded up to the next highest power of 2,
default: 1
-h print this usage text
-V show version number and format version support then quit
For additional info on scrypt params refer to:
https://blog.filippo.io/the-scrypt-parameters/
https://tools.ietf.org/html/rfc7914#section-2
```
pegh file format
----------------
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 only version 0 exists.
Version 0, scrypt key derivation, aes-256-gcm encryption, 51 byte header, 16 byte footer:
| indices | format | value interpretation |
|--------------|---------------------------------------------|--------------------------------|
| 0 | 8 bit unsigned byte | pegh file format version |
| 1-4 | 32 bit unsigned integer in big endian order | scrypt N parameter |
| 5 | 8 bit unsigned byte | scrypt r parameter |
| 6 | 8 bit unsigned byte | scrypt p parameter |
| 7-38 | 32 randomly generated bytes | scrypt key derivation seed |
| 39-50 | 12 randomly generated bytes | AES-256-GCM IV |
| 51-X | any number of bytes | AES-256-GCM encrypted data |
| (X+1)-(X+16) | 16 bytes, always last 16 bytes in file | AES-256-GCM authentication tag |
License
-------
AGPLv3 for now, message me if you have a problem with this

36
pegh.c
View File

@ -29,7 +29,7 @@
#include <string.h>
/*
* tweak scrypt hardness params here
* tweak default scrypt hardness params here
*
* https://tools.ietf.org/html/rfc7914#section-2
* https://blog.filippo.io/the-scrypt-parameters/
@ -43,6 +43,27 @@
#define BYTES_PER_READ (1024 * 32) /* 32kb */
#define INITIAL_BUFFER_SIZE (1024 * 256) /* 256kb, must be at least 2*BYTES_PER_READ */
/*
* pegh file format, numbers are inclusive 0-based byte array indices
*
* 0th byte is always version number, everything else depends on version number
*
* |---------------------------------------------------------------------------------------------|
* | Version 0, scrypt key derivation, aes-256-gcm encryption, 51 byte header, 16 byte footer |
* |--------------|---------------------------------------------|--------------------------------|
* | indices | format | value interpretation |
* |--------------|---------------------------------------------|--------------------------------|
* | 0 | 8 bit unsigned byte | pegh file format version |
* | 1-4 | 32 bit unsigned integer in big endian order | scrypt N parameter |
* | 5 | 8 bit unsigned byte | scrypt r parameter |
* | 6 | 8 bit unsigned byte | scrypt p parameter |
* | 7-38 | 32 randomly generated bytes | scrypt key derivation seed |
* | 39-50 | 12 randomly generated bytes | AES-256-GCM IV |
* | 51-X | any number of bytes | AES-256-GCM encrypted data |
* | (X+1)-(X+16) | 16 bytes, always last 16 bytes in file | AES-256-GCM authentication tag |
* |---------------------------------------------------------------------------------------------|
*/
/* don't touch below here unless you know what you are doing */
#define PEGH_VERSION "1.0.0"
@ -323,9 +344,9 @@ int pegh(char *password, int decrypt,
int help(int exit_code) {
/* this ridiculous split is because C89 only supports strings of 509 characters */
fprintf(stderr, "\
usage: pegh [-demNrphV] password\n\
-d decrypt stdin to stdout, default mode\n\
-e encrypt stdin to stdout\n\
usage: pegh [-demNrpshV] password\n\
-e encrypt stdin to stdout, default mode\n\
-d decrypt stdin to stdout\n\
-m <max_mb> maximum megabytes of ram to use when deriving key from password\n\
with scrypt, applies for encryption AND decryption, must\n\
almost linearly scale with -N, if too low operation will fail,\n\
@ -336,9 +357,10 @@ usage: pegh [-demNrphV] password\n\
-r <num> scrypt parameter r, only applies for encryption, default %d\n\
-p <num> scrypt parameter p, only applies for encryption, default %d\n\
-s <num> multiplication factor to apply to both -N and -m for easy\n\
work scaling, rounded up to the next highest power of 2,\n\
default: 1\n", SCRYPT_N, SCRYPT_R, SCRYPT_P);
work scaling, rounded up to the next highest power of 2,\n", SCRYPT_N, SCRYPT_R, SCRYPT_P);
fprintf(stderr, "\
BEWARE: -s 32 requires 2G ram, -s 64 requires 4G and so on,\n\
default: 1\n\
-h print this usage text\n\
-V show version number and format version support then quit\n\
\nFor additional info on scrypt params refer to:\n\
@ -388,7 +410,7 @@ uint32_t next_highest_power_of_2(uint32_t v) {
/* returns 0 on success, 1 on openssl failure, 2 on other failure */
int main(int argc, char **argv)
{
int optind, decrypt = 1;
int optind, decrypt = 0;
char *password = NULL;
uint32_t N = SCRYPT_N, scrypt_max_mem_mb = SCRYPT_MAX_MEM_MB, scale = 1;
uint8_t r = SCRYPT_R, p = SCRYPT_P;

View File

@ -13,8 +13,8 @@ echo "key: $key"
test () {
bin=$1
tee >(md5sum 1>&2) < /dev/shm/randombytes | $bin -e $key | $bin $key | md5sum 1>&2
#$bin -e $key < /dev/shm/randombytes | $bin $key &>/dev/null
tee >(md5sum 1>&2) < /dev/shm/randombytes | $bin -e $key | $bin -d $key | md5sum 1>&2
#$bin -e $key < /dev/shm/randombytes | $bin -d $key &>/dev/null
}
time test ./pegh