Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

result hmac_sha512 differs from Perl's #14

Open
hadjiprocopis opened this issue Jun 3, 2021 · 1 comment
Open

result hmac_sha512 differs from Perl's #14

hadjiprocopis opened this issue Jun 3, 2021 · 1 comment

Comments

@hadjiprocopis
Copy link

hadjiprocopis commented Jun 3, 2021

Hi there and thank you for this free implementation.

I can not produce the same result using your library's fastpbkdf2_hmac_sha512() with Perl's Digest::SHA::hmac_sha512 and also Python's hashlib.sha512 (Perl's and Python's output do agree).

The problem may well be with me misunderstanding the usage of fastpbkdf2_hmac_sha512(). If this is the case, apologies in advance and please let me know how to use said function with a message and a secret key (no salt - are they the same?) and no repetitions.

Here are 2 programs to reproduce my problem:

test.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fastpbkdf2.h"

// gcc -g test.c libfastpbkdf2.a -lcrypto && a.out
// this is not producing the right result compared to perl

#define SHA512_DIGEST_SIZE (512/8)

// print binary buffer in hex
void printhex(FILE *fh, const char *name, const unsigned char *in, int len){
	fprintf(fh, "begin hex for '%s':\n", name);
	for(int i=0;i<len;i++){ fprintf(fh, "0x%02x ", in[i]); }
	fprintf(fh, "\nend hex of %d bytes.\n", len);
}

int main(void){
	char *message = "hello there";
	char *key = "secret key";
	char result[SHA512_DIGEST_SIZE];
	int key_len = strlen(key);
	int message_len = strlen(message);

        fastpbkdf2_hmac_sha512(
                // this is the input and its size
                (uint8_t *)message, message_len,
                // salt to the hash is our secret key decoded
                (uint8_t *)key, key_len,
                1, // iterations
                // the output goes here
                result, SHA512_DIGEST_SIZE
        );

	printhex(stdout, "result", result, SHA512_DIGEST_SIZE);
}

and here is the Perl script which produces a different result but which agrees with Python and also with another C implementation (by ogay):

mac.pl (run it as perl mac.pl)

#!/usr/bin/env perl
use strict;
use warnings;
use Digest::SHA qw/hmac_sha512/;

my $message = "hello there";
my $secret = "secret key";
my $hmacsha512 = Digest::SHA::hmac_sha512($message, $secret);
print "result hmacsha512:\n".bin2hex($hmacsha512)."\n";

sub bin2hex {
	my @byts = split //, $_[0];
	join(' ', map {sprintf("0x%x", ord)} @byts) . " (size ".@byts.")";
}

I would really love to use your implementation but I need to solve this issue right now.

As I said, the problem may be with me using your function incorrectly. In this case please advise. My usage is that I have a message and a key. Is your salt the same as my key? and I don't need repetitions (what's the default?), so I set them to 1. Even 0 repetitions produce mismatched result.

5minute Edit: here are the 2 outputs:
test.c:

begin hex for 'result':
0x07 0x89 0xd9 0x61 0x75 0xc5 0x12 0x3f 0x05 0x80 0xcc 0xf8 0x2e 0x5b 0x9e 0xa2 0x3e 0x6c 0x84 0xb4 0xb7 0x47 0x84 0x98 0x26 0x6e 0xa1 0x46 0x2e 0x3d 0x6a 0x38 0xcf 0x89 0xda 0x15 0xa8 0x24 0x7e 0xab 0x1f 0xd0 0x49 0xcb 0x04 0xd5 0xd8 0x96 0x6c 0x89 0xfb 0x60 0x54 0x27 0xe8 0xf9 0xf0 0x97 0xd7 0xe1 0x1d 0x5b 0x7d 0x6f 
end hex of 64 bytes.

mac.pl:

result hmacsha512:
0x8c 0x66 0xa0 0x21 0x29 0x38 0xf9 0x80 0xcf 0x49 0x93 0x79 0xfb 0xcd 0xc1 0x8d 0xb7 0x16 0x0 0x55 0x3c 0x4e 0x62 0x57 0xe3 0x8f 0x96 0x41 0x79 0xf8 0xe5 0x67 0xb8 0xa2 0x2b 0x38 0xb0 0xdb 0x54 0xee 0xd8 0x1 0x6 0xdd 0xb0 0x38 0x4b 0xc3 0x3f 0x20 0xba 0xb7 0xdf 0xa2 0x99 0xc2 0x80 0x12 0x43 0x63 0x58 0x2 0x84 0x27
(size 64)

bw,
Andreas Hadjiprocopis

@red0xff
Copy link

red0xff commented Dec 4, 2021

@hadjiprocopis The output of fastpbkdf2_hmac_sha512 is correct.

You are comparing the output of hmac-sha512 of perl with the output of pbkdf2-hmac-sha512 of fastpbkdf2, while the latter calls the first one iteratively, parameters will differ.

The first iteration of PRF uses Password as the PRF key and Salt concatenated with i encoded as a big-endian 32-bit integer as the input. (Note that i is a 1-based index.)

So, to get the output of fastpbkdf2 in Perl, you would need to use the message as a key (or salt), and the key concatenated with 1 in big endian as a message.

#!/usr/bin/env perl
use strict;
use warnings;
use Digest::SHA qw/hmac_sha512/;

my $message = "hello there";
my $secret = "secret key";
my $hmacsha512 = Digest::SHA::hmac_sha512($secret . "\x00\x00\x00\x01", $message);
print "result hmacsha512:\n".bin2hex($hmacsha512)."\n";

sub bin2hex {
        my @byts = split //, $_[0];
        join(' ', map {sprintf("0x%x", ord)} @byts) . " (size ".@byts.")";
}

Result:

result hmacsha512:
0x7 0x89 0xd9 0x61 0x75 0xc5 0x12 0x3f 0x5 0x80 0xcc 0xf8 0x2e 0x5b 0x9e 0xa2 0x3e 0x6c 0x84 0xb4 0xb7 0x47 0x84 0x98 0x26 0x6e 0xa1 0x46 0x2e 0x3d 0x6a 0x38 0xcf 0x89 0xda 0x15 0xa8 0x24 0x7e 0xab 0x1f 0xd0 0x49 0xcb 0x4 0xd5 0xd8 0x96 0x6c 0x89 0xfb 0x60 0x54 0x27 0xe8 0xf9 0xf0 0x97 0xd7 0xe1 0x1d 0x5b 0x7d 0x6f (size 64)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants