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
---- ----
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](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> #include <string.h>
/* /*
* tweak scrypt hardness params here * tweak default scrypt hardness params here
* *
* https://tools.ietf.org/html/rfc7914#section-2 * https://tools.ietf.org/html/rfc7914#section-2
* https://blog.filippo.io/the-scrypt-parameters/ * https://blog.filippo.io/the-scrypt-parameters/
@ -43,6 +43,27 @@
#define BYTES_PER_READ (1024 * 32) /* 32kb */ #define BYTES_PER_READ (1024 * 32) /* 32kb */
#define INITIAL_BUFFER_SIZE (1024 * 256) /* 256kb, must be at least 2*BYTES_PER_READ */ #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 */ /* don't touch below here unless you know what you are doing */
#define PEGH_VERSION "1.0.0" #define PEGH_VERSION "1.0.0"
@ -323,9 +344,9 @@ int pegh(char *password, int decrypt,
int help(int exit_code) { int help(int exit_code) {
/* this ridiculous split is because C89 only supports strings of 509 characters */ /* this ridiculous split is because C89 only supports strings of 509 characters */
fprintf(stderr, "\ fprintf(stderr, "\
usage: pegh [-demNrphV] password\n\ usage: pegh [-demNrpshV] password\n\
-d decrypt stdin to stdout, default mode\n\ -e encrypt stdin to stdout, default mode\n\
-e encrypt stdin to stdout\n\ -d decrypt stdin to stdout\n\
-m <max_mb> maximum megabytes of ram to use when deriving key from password\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\ with scrypt, applies for encryption AND decryption, must\n\
almost linearly scale with -N, if too low operation will fail,\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\ -r <num> scrypt parameter r, only applies for encryption, default %d\n\
-p <num> scrypt parameter p, 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\ -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\ work scaling, rounded up to the next highest power of 2,\n", SCRYPT_N, SCRYPT_R, SCRYPT_P);
default: 1\n", SCRYPT_N, SCRYPT_R, SCRYPT_P);
fprintf(stderr, "\ 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\ -h print this usage text\n\
-V show version number and format version support then quit\n\ -V show version number and format version support then quit\n\
\nFor additional info on scrypt params refer to:\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 */ /* returns 0 on success, 1 on openssl failure, 2 on other failure */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int optind, decrypt = 1; int optind, decrypt = 0;
char *password = NULL; char *password = NULL;
uint32_t N = SCRYPT_N, scrypt_max_mem_mb = SCRYPT_MAX_MEM_MB, scale = 1; uint32_t N = SCRYPT_N, scrypt_max_mem_mb = SCRYPT_MAX_MEM_MB, scale = 1;
uint8_t r = SCRYPT_R, p = SCRYPT_P; uint8_t r = SCRYPT_R, p = SCRYPT_P;

View File

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