mirror of
https://github.com/BLAKE2/BLAKE2
synced 2024-11-08 14:59:19 +01:00
Implemented keyed-mode for BLAKE2b
Note, that OpenSSL doesn't seem to be using standard HMAC *or* keyed mode. As such, my attempt to bring my implementation to agree with theirs dies with their inibility to follow standards. If I'm incorrect in my assessment I'd appreciate someone sending a pull-request with the fixed version. Perhaps OpenSSL combines HMAC with keyed mode?
This commit is contained in:
parent
750880af71
commit
8bc9e85048
158
b2sum/b2sum.c
158
b2sum/b2sum.c
@ -274,6 +274,57 @@ int blake2b_stream_hmac( unsigned char *key, FILE *stream, void *resstream, size
|
||||
blake2b_update( S, buffer, buffer_length );
|
||||
}
|
||||
|
||||
final_process:;
|
||||
|
||||
if( sum > 0 ) blake2b_update( S, buffer, sum );
|
||||
|
||||
blake2b_final( S, resstream, outbytes );
|
||||
ret = 0;
|
||||
cleanup_buffer:
|
||||
free( buffer );
|
||||
return ret;
|
||||
}
|
||||
int blake2b_stream_keym( unsigned char *key, size_t key_length, FILE *stream, void *resstream, size_t outbytes )
|
||||
{
|
||||
int ret = -1;
|
||||
size_t sum, n;
|
||||
blake2b_state S[1];
|
||||
static const size_t buffer_length = 32768;
|
||||
uint8_t *buffer = ( uint8_t * )malloc( buffer_length );
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
if( !buffer ) return -1;
|
||||
|
||||
blake2b_init_key( S, outbytes, key, key_length );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
sum = 0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
n = fread( buffer + sum, 1, buffer_length - sum, stream );
|
||||
sum += n;
|
||||
|
||||
if( buffer_length == sum )
|
||||
break;
|
||||
|
||||
if( 0 == n )
|
||||
{
|
||||
if( ferror( stream ) )
|
||||
goto cleanup_buffer;
|
||||
|
||||
goto final_process;
|
||||
}
|
||||
|
||||
if( feof( stream ) )
|
||||
goto final_process;
|
||||
}
|
||||
|
||||
blake2b_update( S, buffer, buffer_length );
|
||||
}
|
||||
|
||||
final_process:;
|
||||
|
||||
if( sum > 0 ) blake2b_update( S, buffer, sum );
|
||||
@ -349,12 +400,20 @@ static void usage( char **argv, int errcode )
|
||||
fprintf( out, "\n" );
|
||||
fprintf( out, "With no FILE, or when FILE is -, read standard input.\n" );
|
||||
fprintf( out, "\n" );
|
||||
fprintf( out, " -a <algo> hash algorithm (blake2b is default): \n"
|
||||
" [blake2b|blake2s|blake2bp|blake2sp]\n" );
|
||||
fprintf( out, " -h <key> hash in HMAC mode\n"
|
||||
" if <key> is '-' stdin will be used (only applies to blake2b)\n" );
|
||||
fprintf( out, " -l <length> digest length in bits, must not exceed the maximum for\n"
|
||||
" the selected algorithm and must be a multiple of 8\n" );
|
||||
fprintf( out, " -a <algo> hash algorithm (blake2b is default): \n" );
|
||||
fprintf( out, " [blake2b|blake2s|blake2bp|blake2sp]\n" );
|
||||
fprintf( out, " -h <key> hash in HMAC mode\n" );
|
||||
fprintf( out, " if <key> is '-' stdin will be used (only applies to blake2b)\n" );
|
||||
fprintf( out, " -k <key> uses keyed mode (as opposed to HMAC)\n" );
|
||||
fprintf( out, " I include separated this because I don't like HMAC not being real HMAC\n" );
|
||||
fprintf( out, " in OpenSSL's implementation of BLAKE2b-HMAC : they should change the\n" );
|
||||
fprintf( out, " name of the option if they're not gonna use real HMAC!\n" );
|
||||
fprintf( out, " >> note that keyed mode and HMAC mode are different, since BLAKE\n" );
|
||||
fprintf( out, " >> is made of a construction that is secure with prefixed-key MACs\n" );
|
||||
fprintf( out, " >> I included HMAC mode because I like conforming to specs and I\n" );
|
||||
fprintf( out, " >> refuse to use a non-HMAC keyed mode and call it HMAC\n" );
|
||||
fprintf( out, " -l <length> digest length in bits, must not exceed the maximum for\n" );
|
||||
fprintf( out, " the selected algorithm and must be a multiple of 8\n" );
|
||||
fprintf( out, " --tag create a BSD-style checksum\n" );
|
||||
fprintf( out, " --help display this help and exit\n" );
|
||||
exit( errcode );
|
||||
@ -371,6 +430,7 @@ int main( int argc, char **argv )
|
||||
unsigned char hash2[BLAKE2B_OUTBYTES] = {0};
|
||||
unsigned char hmac_key[HMAC_MAX_KEY_LEN + 1]; /* add an extra byte to make room for a null-terminator */
|
||||
unsigned char use_hmac = 0;
|
||||
unsigned char use_keym = 0;
|
||||
size_t hmac_key_len = 0;
|
||||
bool bsdstyle = false;
|
||||
int c, i;
|
||||
@ -387,7 +447,7 @@ int main( int argc, char **argv )
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long( argc, argv, "a:l:h:", long_options, &option_index );
|
||||
c = getopt_long( argc, argv, "a:l:h:k:", long_options, &option_index );
|
||||
if( c == -1 ) break;
|
||||
switch( c )
|
||||
{
|
||||
@ -461,6 +521,34 @@ int main( int argc, char **argv )
|
||||
}
|
||||
} /* Now you have a zero-padded key, per spec */
|
||||
break;
|
||||
case 'k':
|
||||
use_keym = 0xFF;
|
||||
hmac_key_len = 0;
|
||||
if ( 0 == strcmp( optarg, "-" ) ){
|
||||
hmac_key_len = 0;
|
||||
while(hmac_key_len < HMAC_MAX_KEY_LEN){
|
||||
hmac_key[hmac_key_len++] = 0;
|
||||
}
|
||||
hmac_key[HMAC_MAX_KEY_LEN] = 0;
|
||||
hmac_key_len = 0;
|
||||
while(hmac_key_len < HMAC_MAX_KEY_LEN){
|
||||
unsigned char c = getc(stdin);
|
||||
if(c == '\n' || c == '\r') break;
|
||||
hmac_key[hmac_key_len++] = c;
|
||||
}
|
||||
} else {
|
||||
hmac_key_len = 0;
|
||||
while(hmac_key_len < HMAC_MAX_KEY_LEN + 1){
|
||||
hmac_key[hmac_key_len++] = 0;
|
||||
}
|
||||
hmac_key_len = 0;
|
||||
while(hmac_key_len < HMAC_MAX_KEY_LEN){
|
||||
unsigned char c = optarg[hmac_key_len];
|
||||
if(c == 0) break;
|
||||
hmac_key[hmac_key_len++] = c;
|
||||
}
|
||||
} /* Now you have a zero-padded key, per spec */
|
||||
break;
|
||||
case 0:
|
||||
if( 0 == strcmp( "help", long_options[option_index].name ) )
|
||||
usage( argv, 0 );
|
||||
@ -502,7 +590,6 @@ int main( int argc, char **argv )
|
||||
if(use_hmac){
|
||||
if(hmac_key_len > outbytes){
|
||||
size_t j;
|
||||
printf("Building key...");
|
||||
blake2b_stream_build_key( hmac_key, hmac_key_len, hash, outbytes );
|
||||
for(j=0; j<outbytes; ++j){
|
||||
hmac_key[j] = hash[j];
|
||||
@ -568,6 +655,61 @@ int main( int argc, char **argv )
|
||||
printf(hmac_key);
|
||||
}
|
||||
}
|
||||
} else if(use_keym){
|
||||
/*
|
||||
Apparently OpenSSL doesn't use standard HMAC, *or* keyed mode with BLAKE2...
|
||||
I'm using the keyed-mode provided by BLAKE's own library, so I'm just gonna
|
||||
call it a day.
|
||||
|
||||
https://blake2.net/blake2.pdf
|
||||
*/
|
||||
if(hmac_key_len > outbytes){
|
||||
size_t j;
|
||||
blake2b_stream_build_key( hmac_key, hmac_key_len, hash, outbytes );
|
||||
for(j=0; j<outbytes; ++j){
|
||||
hmac_key[j] = hash[j];
|
||||
hash[j] = 0;
|
||||
}
|
||||
hmac_key_len = outbytes;
|
||||
}
|
||||
/* The indentation is weird because I got lazy and used tab */
|
||||
/* printf("%s\n", hmac_key); /* Used for debugging or seeing what the key looks like */
|
||||
size_t j;
|
||||
/* printf("%s\n", hmac_key); /* Used for debugging or seeing what the key looks like */
|
||||
if( blake2b_stream_keym( hmac_key, hmac_key_len, f, hash, outbytes ) < 0 )
|
||||
{
|
||||
fprintf( stderr, "Failed to hash `%s'\n", argv[i] );
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t j;
|
||||
if( bsdstyle )
|
||||
{
|
||||
if( outbytes < maxbytes )
|
||||
printf( "%s-%lu (%s) = ", algorithm, outbytes * 8, argv[i] );
|
||||
else
|
||||
printf( "%s (%s) = ", algorithm, argv[i] );
|
||||
}
|
||||
|
||||
for( j = 0; j < outbytes; ++j )
|
||||
printf( "%02x", hash[j] );
|
||||
|
||||
if( bsdstyle )
|
||||
printf( "\n" );
|
||||
else
|
||||
printf( " %s\n", argv[i] );
|
||||
/* clean up */
|
||||
|
||||
memset(hmac_key, 0, HMAC_MAX_KEY_LEN);
|
||||
memset(hash2, 0, outbytes);
|
||||
memset(hash, 0, outbytes);
|
||||
/*
|
||||
Make sure the compiler doesn't optimize away our memory reset; it's a security measure
|
||||
*/
|
||||
printf(hash);
|
||||
printf(hash2);
|
||||
printf(hmac_key);
|
||||
}
|
||||
} else{
|
||||
if( blake2_stream( f, hash, outbytes ) < 0 )
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user