Skip to content

Commit 6e1023d

Browse files
committed
Support prehashing
1 parent ee148f9 commit 6e1023d

File tree

2 files changed

+57
-11
lines changed

2 files changed

+57
-11
lines changed

src/minisign.c

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "minisign.h"
2020

2121
#ifndef VERIFY_ONLY
22-
static const char *getopt_options = "GSVhc:m:oP:p:qQs:t:vx:";
22+
static const char *getopt_options = "GSVHhc:m:oP:p:qQs:t:vx:";
2323
#else
2424
static const char *getopt_options = "Vhm:oP:p:qQvx:";
2525
#endif
@@ -32,7 +32,7 @@ usage(void)
3232
puts("Usage:\n"
3333
#ifndef VERIFY_ONLY
3434
"minisign -G [-p pubkey] [-s seckey]\n"
35-
"minisign -S [-x sigfile] [-s seckey] [-c untrusted_comment] [-t trusted_comment] -m file\n"
35+
"minisign -S [-H] [-x sigfile] [-s seckey] [-c untrusted_comment] [-t trusted_comment] -m file\n"
3636
#endif
3737
"minisign -V [-x sigfile] [-p pubkeyfile | -P pubkey] [-o] [-q] -m file\n"
3838
"\n"
@@ -43,6 +43,7 @@ usage(void)
4343
"-V verify that a signature is valid for a given file\n"
4444
"-m <file> file to sign/verify\n"
4545
"-o combined with -V, output the file content after verification\n"
46+
"-H combined with -S, pre-hash in order to sign large files\n"
4647
"-p <pubkeyfile> public key file (default: ./minisign.pub)\n"
4748
"-P <pubkey> public key, as a base64 string\n"
4849
#ifndef VERIFY_ONLY
@@ -61,12 +62,42 @@ usage(void)
6162
}
6263

6364
static unsigned char *
64-
message_load(size_t *message_len, const char *message_file)
65+
message_load_hashed(size_t *message_len, const char *message_file)
66+
{
67+
crypto_generichash_state hs;
68+
unsigned char buf[4096U];
69+
unsigned char *message;
70+
FILE *fp;
71+
size_t n;
72+
73+
if ((fp = fopen(message_file, "rb")) == NULL) {
74+
exit_err(message_file);
75+
}
76+
crypto_generichash_init(&hs, NULL, 0U, crypto_generichash_BYTES_MAX);
77+
while ((n = fread(buf, 1U, sizeof buf, fp)) > 0U) {
78+
crypto_generichash_update(&hs, buf, n);
79+
}
80+
if (!feof(fp)) {
81+
exit_err(message_file);
82+
}
83+
xfclose(fp);
84+
message = xmalloc(crypto_generichash_BYTES_MAX);
85+
crypto_generichash_final(&hs, message, crypto_generichash_BYTES_MAX);
86+
*message_len = crypto_generichash_BYTES_MAX;
87+
88+
return message;
89+
}
90+
91+
static unsigned char *
92+
message_load(size_t *message_len, const char *message_file, int hashed)
6593
{
6694
FILE *fp;
6795
unsigned char *message;
6896
off_t message_len_;
6997

98+
if (hashed != 0) {
99+
return message_load_hashed(message_len, message_file);
100+
}
70101
if ((fp = fopen(message_file, "rb")) == NULL ||
71102
fseeko(fp, 0, SEEK_END) != 0 ||
72103
(message_len_ = ftello(fp)) == (off_t) -1) {
@@ -114,7 +145,7 @@ output_file(const char *message_file)
114145

115146
static SigStruct *
116147
sig_load(const char *sig_file, unsigned char global_sig[crypto_sign_BYTES],
117-
char trusted_comment[TRUSTEDCOMMENTMAXBYTES],
148+
int *hashed, char trusted_comment[TRUSTEDCOMMENTMAXBYTES],
118149
size_t trusted_comment_maxlen)
119150
{
120151
char comment[COMMENTMAXBYTES];
@@ -171,7 +202,12 @@ sig_load(const char *sig_file, unsigned char global_sig[crypto_sign_BYTES],
171202
exit_msg("base64 conversion failed");
172203
}
173204
free(sig_s);
174-
if (memcmp(sig_struct->sig_alg, SIGALG, sizeof sig_struct->sig_alg) != 0) {
205+
if (memcmp(sig_struct->sig_alg, SIGALG, sizeof sig_struct->sig_alg) == 0) {
206+
*hashed = 0;
207+
} else if (memcmp(sig_struct->sig_alg, SIGALG_HASHED,
208+
sizeof sig_struct->sig_alg) == 0) {
209+
*hashed = 1;
210+
} else {
175211
exit_msg("Unsupported signature algorithm");
176212
}
177213
if (b64_to_bin(global_sig, global_sig_s, crypto_sign_BYTES,
@@ -346,13 +382,14 @@ verify(PubkeyStruct *pubkey_struct, const char *message_file,
346382
unsigned char *message;
347383
size_t message_len;
348384
size_t trusted_comment_len;
385+
int hashed;
349386

350387
if (output != 0) {
351388
info_fp = stderr;
352389
}
353-
message = message_load(&message_len, message_file);
354-
sig_struct = sig_load(sig_file, global_sig,
390+
sig_struct = sig_load(sig_file, global_sig, &hashed,
355391
trusted_comment, sizeof trusted_comment);
392+
message = message_load(&message_len, message_file, hashed);
356393
if (memcmp(sig_struct->keynum, pubkey_struct->keynum_pk.keynum,
357394
sizeof sig_struct->keynum) != 0) {
358395
fprintf(stderr, "Signature key id in %s is %" PRIX64 "\n"
@@ -402,7 +439,7 @@ verify(PubkeyStruct *pubkey_struct, const char *message_file,
402439
#ifndef VERIFY_ONLY
403440
static int
404441
sign(const char *sk_file, const char *message_file, const char *sig_file,
405-
const char *comment, const char *trusted_comment)
442+
const char *comment, const char *trusted_comment, int hashed)
406443
{
407444
unsigned char global_sig[crypto_sign_BYTES];
408445
SigStruct sig_struct;
@@ -415,8 +452,12 @@ sign(const char *sk_file, const char *message_file, const char *sig_file,
415452
size_t message_len;
416453

417454
seckey_struct = seckey_load(sk_file);
418-
message = message_load(&message_len, message_file);
419-
memcpy(sig_struct.sig_alg, SIGALG, sizeof sig_struct.sig_alg);
455+
message = message_load(&message_len, message_file, hashed);
456+
if (hashed != 0) {
457+
memcpy(sig_struct.sig_alg, SIGALG_HASHED, sizeof sig_struct.sig_alg);
458+
} else {
459+
memcpy(sig_struct.sig_alg, SIGALG, sizeof sig_struct.sig_alg);
460+
}
420461
memcpy(sig_struct.keynum, seckey_struct->keynum_sk.keynum,
421462
sizeof sig_struct.keynum);
422463
crypto_sign_detached(sig_struct.sig, NULL, message, message_len,
@@ -582,6 +623,7 @@ main(int argc, char **argv)
582623
const char *pubkey_s = NULL;
583624
const char *trusted_comment = NULL;
584625
int opt_flag;
626+
int hashed = 0;
585627
int quiet = 0;
586628
int output = 0;
587629
Action action = ACTION_NONE;
@@ -611,6 +653,9 @@ main(int argc, char **argv)
611653
break;
612654
case 'h':
613655
usage();
656+
case 'H':
657+
hashed = 1;
658+
break;
614659
case 'm':
615660
message_file = optarg;
616661
break;
@@ -671,7 +716,7 @@ main(int argc, char **argv)
671716
trusted_comment = default_trusted_comment(message_file);
672717
}
673718
return sign(sk_file, message_file, sig_file, comment,
674-
trusted_comment) != 0;
719+
trusted_comment, hashed) != 0;
675720
#endif
676721
case ACTION_VERIFY:
677722
if (message_file == NULL) {

src/minisign.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define PASSWORDMAXBYTES 1024
88
#define TRUSTEDCOMMENTMAXBYTES 8192
99
#define SIGALG "Ed"
10+
#define SIGALG_HASHED "ED"
1011
#define KDFALG "Sc"
1112
#define CHKALG "B2"
1213
#define COMMENT_PREFIX "untrusted comment: "

0 commit comments

Comments
 (0)