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
2424static 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
6364static 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
115146static SigStruct *
116147sig_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
403440static int
404441sign (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 ) {
0 commit comments