Add options and command line parsing
This commit is contained in:
parent
2d1b9a3942
commit
82114dece7
173
pegh.c
173
pegh.c
|
@ -37,7 +37,7 @@
|
||||||
#define SCRYPT_N 32768
|
#define SCRYPT_N 32768
|
||||||
#define SCRYPT_R 8
|
#define SCRYPT_R 8
|
||||||
#define SCRYPT_P 1
|
#define SCRYPT_P 1
|
||||||
#define SCRYPT_MAX_MEM (1024 * 1024 * 64) /* 64mb, must be sufficient for N */
|
#define SCRYPT_MAX_MEM_MB 64
|
||||||
|
|
||||||
/* tweak initial read buffer size/reads here */
|
/* tweak initial read buffer size/reads here */
|
||||||
#define BYTES_PER_READ (1024 * 32) /* 32kb */
|
#define BYTES_PER_READ (1024 * 32) /* 32kb */
|
||||||
|
@ -45,6 +45,8 @@
|
||||||
|
|
||||||
/* 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 KEY_LEN 32 /* 256 bit key required for AES-256 */
|
#define KEY_LEN 32 /* 256 bit key required for AES-256 */
|
||||||
|
|
||||||
/* 1 for file format version, 4 for N, 1 for r, 1 for p */
|
/* 1 for file format version, 4 for N, 1 for r, 1 for p */
|
||||||
|
@ -190,28 +192,18 @@ int gcm_decrypt(unsigned char *ciphertext, size_t ciphertext_len,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 pegh(char *password, int decrypt,
|
||||||
|
uint32_t scrypt_max_mem_mb, uint32_t N,
|
||||||
|
uint8_t r, uint8_t p)
|
||||||
{
|
{
|
||||||
unsigned char key[KEY_LEN] = {0};
|
unsigned char key[KEY_LEN] = {0};
|
||||||
/* these are actually mallocd and freed */
|
/* these are actually mallocd and freed */
|
||||||
unsigned char *in_buffer, *out_buffer = NULL;
|
unsigned char *in_buffer, *out_buffer = NULL;
|
||||||
/* these are simply pointers into the above */
|
/* these are simply pointers into the above */
|
||||||
unsigned char *salt, *iv, *ciphertext, *plaintext, *tag;
|
unsigned char *salt, *iv, *ciphertext, *plaintext, *tag;
|
||||||
int exit_code = 2, decrypt = 1;
|
int exit_code = 2;
|
||||||
size_t read, in_buffer_len = 0, out_buffer_len, in_buffer_allocd_size = INITIAL_BUFFER_SIZE;
|
size_t read, in_buffer_len = 0, out_buffer_len, in_buffer_allocd_size = INITIAL_BUFFER_SIZE;
|
||||||
|
|
||||||
uint32_t N = SCRYPT_N;
|
|
||||||
uint8_t r = SCRYPT_R, p = SCRYPT_P;
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
fprintf(stderr, "Usage: %s <key> [enc]\n", argv[0]);
|
|
||||||
return exit_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this means we want to encrypt, not decrypt */
|
|
||||||
if (argc > 2 && strcmp("enc", argv[2]) == 0)
|
|
||||||
decrypt = 0;
|
|
||||||
|
|
||||||
in_buffer = malloc(in_buffer_allocd_size);
|
in_buffer = malloc(in_buffer_allocd_size);
|
||||||
if(!in_buffer) {
|
if(!in_buffer) {
|
||||||
fprintf(stderr, "in_buffer memory allocation failed\n");
|
fprintf(stderr, "in_buffer memory allocation failed\n");
|
||||||
|
@ -282,10 +274,10 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
/* https://commondatastorage.googleapis.com/chromium-boringssl-docs/evp.h.html#EVP_PBE_scrypt */
|
/* https://commondatastorage.googleapis.com/chromium-boringssl-docs/evp.h.html#EVP_PBE_scrypt */
|
||||||
if (EVP_PBE_scrypt(
|
if (EVP_PBE_scrypt(
|
||||||
argv[1], strlen(argv[1]),
|
password, strlen(password),
|
||||||
salt, SALT_LEN,
|
salt, SALT_LEN,
|
||||||
(uint64_t) N, (uint64_t) r, (uint64_t) p,
|
(uint64_t) N, (uint64_t) r, (uint64_t) p,
|
||||||
SCRYPT_MAX_MEM,
|
(uint64_t) scrypt_max_mem_mb * 1024 * 1024,
|
||||||
key, KEY_LEN
|
key, KEY_LEN
|
||||||
) <= 0) {
|
) <= 0) {
|
||||||
fprintf(stderr, "scrypt key derivation error\n");
|
fprintf(stderr, "scrypt key derivation error\n");
|
||||||
|
@ -327,3 +319,150 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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\
|
||||||
|
-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\
|
||||||
|
default: %d\n", SCRYPT_MAX_MEM_MB);
|
||||||
|
fprintf(stderr, "\
|
||||||
|
-N <num> scrypt parameter N, only applies for encryption, default %d\n\
|
||||||
|
this is rounded up to the next highest power of 2\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);
|
||||||
|
fprintf(stderr, "\
|
||||||
|
-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\
|
||||||
|
https://blog.filippo.io/the-scrypt-parameters/\n\
|
||||||
|
https://tools.ietf.org/html/rfc7914#section-2\n\n");
|
||||||
|
exit(exit_code);
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t parse_int_arg(int optind, int argc, char **argv) {
|
||||||
|
uint32_t tmp = 0;
|
||||||
|
|
||||||
|
if(optind >= argc) {
|
||||||
|
fprintf(stderr, "Error: %s requires an argument\n", argv[optind - 1]);
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
tmp = strtoul(argv[optind], NULL, 10);
|
||||||
|
if(errno != 0 || tmp < 1) {
|
||||||
|
fprintf(stderr, "Error: %s %s failed to parse as a number\n", argv[optind - 1], argv[optind]);
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t parse_byte_arg(int optind, int argc, char **argv) {
|
||||||
|
uint32_t tmp;
|
||||||
|
|
||||||
|
tmp = parse_int_arg(optind, argc, argv);
|
||||||
|
if(tmp > 255) {
|
||||||
|
fprintf(stderr, "Error: %s %s failed to parse as a number 1-255\n", argv[optind - 1], argv[optind]);
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
return (uint8_t) tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t next_highest_power_of_2(uint32_t v) {
|
||||||
|
--v;
|
||||||
|
v |= v >> 1;
|
||||||
|
v |= v >> 2;
|
||||||
|
v |= v >> 4;
|
||||||
|
v |= v >> 8;
|
||||||
|
v |= v >> 16;
|
||||||
|
return ++v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns 0 on success, 1 on openssl failure, 2 on other failure */
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int optind, decrypt = 1;
|
||||||
|
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;
|
||||||
|
|
||||||
|
for (optind = 1; optind < argc; ++optind) {
|
||||||
|
if(strlen(argv[optind]) == 2 && argv[optind][0] == '-') {
|
||||||
|
|
||||||
|
/* -- means stop parsing options */
|
||||||
|
if(argv[optind][1] == '-') {
|
||||||
|
++optind;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (argv[optind][1]) {
|
||||||
|
case 'e':
|
||||||
|
decrypt = 0;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
decrypt = 1;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
scrypt_max_mem_mb = parse_int_arg(++optind, argc, argv);
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
N = next_highest_power_of_2(parse_int_arg(++optind, argc, argv));
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
scale = next_highest_power_of_2(parse_int_arg(++optind, argc, argv));
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
r = parse_byte_arg(++optind, argc, argv);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
p = parse_byte_arg(++optind, argc, argv);
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
fprintf(stderr, "pegh %s\nformat versions supported: 0\n", PEGH_VERSION);
|
||||||
|
return 0;
|
||||||
|
case 'h':
|
||||||
|
return help(0);
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "Error: invalid option %s\n", argv[optind]);
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
} else if (password == NULL) {
|
||||||
|
password = argv[optind];
|
||||||
|
} else {
|
||||||
|
fprintf (stderr, "Error: more than one password provided\n");
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(password == NULL) {
|
||||||
|
if(argc == optind) {
|
||||||
|
fprintf (stderr, "Error: no password provided\n");
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((argc - optind) != 1) {
|
||||||
|
fprintf (stderr, "Error: more than one password provided\n");
|
||||||
|
return help(2);
|
||||||
|
}
|
||||||
|
password = argv[optind];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply scale */
|
||||||
|
N *= scale;
|
||||||
|
scrypt_max_mem_mb *= scale;
|
||||||
|
|
||||||
|
/*
|
||||||
|
fprintf (stderr, "decrypt = %d, key = %s, scrypt_max_mem_mb = %d, N = %d, r = %d, p = %d, scale = %d\n",
|
||||||
|
decrypt, password, scrypt_max_mem_mb, N, r, p, scale);
|
||||||
|
return 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return pegh(password, decrypt, scrypt_max_mem_mb, N, r, p);
|
||||||
|
}
|
||||||
|
|
4
test.sh
4
test.sh
|
@ -13,8 +13,8 @@ echo "key: $key"
|
||||||
|
|
||||||
test () {
|
test () {
|
||||||
bin=$1
|
bin=$1
|
||||||
tee >(md5sum 1>&2) < /dev/shm/randombytes | $bin $key enc | $bin $key | md5sum 1>&2
|
tee >(md5sum 1>&2) < /dev/shm/randombytes | $bin -e $key | $bin $key | md5sum 1>&2
|
||||||
#$bin $key enc < /dev/shm/randombytes | $bin $key &>/dev/null
|
#$bin -e $key < /dev/shm/randombytes | $bin $key &>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
time test ./pegh
|
time test ./pegh
|
||||||
|
|
Loading…
Reference in New Issue