0

i'm about to struggle with calculating a sha256 signature with the same result as <openssl dgst -sha256 -hmac> does calculate. this subject already was discussed in question. inspired by this content i wrote the small perl script in order to understand different implementations of sha256 hmac calculations.

use strict;
use warnings;
use Digest::SHA qw(sha256 hmac_sha256_hex hmac_sha256_base64);
use Digest::HMAC qw(hmac_hex);

my $msg = 'Value-corresponding_to_openssls_EVP_MD structure'; my $key = 'fq6if8aaxLTw0EHRAEkyvCbfa5O9BclbCCB6mtVsWO14KtyIdzIakzzlFGttMaw0'; my ($p1Sig, $p2Sig, $p3Sig, $odSig, $omSig); my $DgstCmd = "echo &quot;$msg&quot; | openssl dgst -sha256 -hmac &quot;$key&quot;";

$p1Sig = hmac_sha256_hex($msg, $key); $p2Sig = hmac_hex($msg, $key, &amp;sha256); $p3Sig = hmac_sha256_base64($msg, $key);

$odSig = $DgstCmd; $odSig =~ /= (\w*)/;

print "message\t<$msg>\nkey\t<$key>\nsignatures:\n openssl = <$1>\n perlSHA = <$p1Sig>\n perlHMAC = <$p2Sig>\n perlSHAbase = <$p3Sig>\n";

system ("openssl version");

the result is not as expected (run on win10):

message <Value-corresponding_to_openssls_EVP_MD structure>
key     <fq6if8aaxLTw0EHRAEkyvCbfa5O9BclbCCB6mtVsWO14KtyIdzIakzzlFGttMaw0>
signatures:
  openssl  = <a1a262e3d0393b076b53620d7924b04ae8c6d9c66a1a1aadd6c1b6e2fd27b8d8>
  perlSHA  = <2782c620c8c799d2c6b77d306cfca9be7dd2820effe66483d6b97dab7ada31f5>
  perlHMAC = <2782c620c8c799d2c6b77d306cfca9be7dd2820effe66483d6b97dab7ada31f5>
  perlSHAbase = <J4LGIMjHmdLGt30wbPypvn3Sgg7/5mSD1rl9q3raMfU>
OpenSSL 1.1.1g  21 Apr 2020

i so run it on a linux system (SMP PREEMPT Wed Nov 8 11:54:06 CET 2017 x86_64 GNU/Linux):

message <Value-corresponding_to_openssls_EVP_MD structure>
key     <fq6if8aaxLTw0EHRAEkyvCbfa5O9BclbCCB6mtVsWO14KtyIdzIakzzlFGttMaw0>
signatures:
  openssl  = <fadbde9a78101454d987d58ee00f6442f75a9f740202acbf9f1cb6933eeb27bf>
  perlSHA  = <2782c620c8c799d2c6b77d306cfca9be7dd2820effe66483d6b97dab7ada31f5>
  perlSHAbase = <J4LGIMjHmdLGt30wbPypvn3Sgg7/5mSD1rl9q3raMfU>
OpenSSL 1.1.0g  2 Nov 2017

all perl versions show the same result. openssl show different results. most interesting is the fact that different openssl versions show different results.

question 1: what is the reason for different results between openssl versions? question 2: is there a solution in perl producing same result as openssl dgst -sha256 -hmac.

have fun

2 Answers2

1
my $DgstCmd = "echo \"$msg\" | openssl dgst -sha256 -hmac \"$key\"";

echo adds a new-line to the message. Thus this does a digest of "$msg\n" on Linux, not a digest of $msg. I'm not sure what exactly it does on Windows though to get to this digest value, but it is definitely not just outputting $msg.

In other words: neither Perl nor openssl is wrong. You simply feed openssl a different input than you feed the Perl code.

0

you are right, thank you steffen.

this problem arised with crpyto api. sometimes messages have to be signed with a hmac-sha256. my real probleam was the system time of my computer running ahaed of providers computer time.

if finished the testset perl and openssl with the c-version. for anyone interested in having the working testbed:

c-function, found in a previous chat, just packed as excecutable:

// using openssl; compile with [-Wall -g -O2] -lcrypto
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>

#define VERBOSE 1 void usage (char); /-----------------------------------------------------------------------------

  • mx_hmac_sha256 - wrapper to HMAC and EVP_sha256

-------------------------------------------------------------------------- / unsigned char mx_hmac_sha256 (const void key, int keylen, const unsigned char data, int datalen, unsigned char result, unsigned int *resultlen) { return HMAC (EVP_sha256(), key, keylen, data, datalen, result, resultlen); }

/*-----------------------------------------------------------------------------

  • main - begin coding

-------------------------------------------------------------------------- / int main (int argc, char *argv) { register char p; char flag = 0, key = 0, msg = 0, buffer; extern char optarg; extern int optind; unsigned char *result = NULL; unsigned int i, keylen, msglen, resultlen = (-1); int c;

while ((c = getopt(argc, argv, &quot;?hvk:m:&quot;)) != -1) {
    switch (c) {
        case 'h':
        case '?':   usage (argv[0]);
                    return (0);
        case 'v':   flag |= VERBOSE;
                    break;
        case 'k':   key = optarg;
                    break;
        case 'm':   msg = optarg;
                    break;
        default:    printf (&quot;unknown option &lt;%c&gt;\n&quot;, c);
                    usage (argv[0]);
                    return (-1);
    }
}
if ((argc - optind) &gt; 0 ) {
    printf (&quot;err: to many parameters, confused\n&quot;);
    usage (argv[0]);
    return (-2);
}

if (!key) {
    key = strdup (&quot;security is awesome&quot;);
}
keylen = strlen(key);
if (!msg) {
    msg = strdup (&quot;this is highly sensitive user data&quot;);
}
msglen = strlen(msg);

result = mx_hmac_sha256 ((const void *)key, keylen, (unsigned char *) msg, msglen, result, &amp;resultlen);
if (resultlen) {
    c = (2 * resultlen) + 1;
    buffer = malloc ((sizeof(char) *c));
    memset (buffer, 0, c);
    for (i = 0, p = buffer; i &lt; resultlen; i++) {
      sprintf (p, &quot;%02x&quot;, result[i]);
      p += 2;
    }
    if (flag &amp; VERBOSE) {
        printf (&quot;message: &lt;%s&gt;\nkey: &lt;%s&gt;\nsignature &lt;%s&gt;\n&quot;, key, msg, buffer);
    } else {
        printf (&quot;%s&quot;,buffer);
    }
    return (0);
} else {
    printf (&quot;no signature\n&quot;);
}

}

/*---------------------------------------------------------------------------

  • usage

-------------------------------------------------------------------------/ void usage (char *pgm) { printf ("usage: %s [-h?v] [-k key] [-m message]\n
h|? = this helptext\n
k = key\n
m = message\n
v = verbose\n\n",pgm); return; }

driving perl script:

use strict;
use warnings;
use Digest::SHA qw(sha256 hmac_sha256_hex hmac_sha256_base64);
use Digest::HMAC qw(hmac_hex);

my $msg = 'Value-corresponding_to_openssls_EVP_MD structure'; my $key = 'fq6if8aaxLTw0EHRAEkyvCbfa5O9BclbCCB6mtVsWO14KtyIdzIakzzlFGttMaw0'; my ($p1Sig, $p2Sig, $p3Sig, $odSig, $funcSig, $omSig); #unix my $DgstCmd = "echo -n &quot;$msg&quot; | openssl dgst -sha256 -hmac &quot;$key&quot;"; my $DgstCmd = "echo|set /p=&quot;$msg&quot; | openssl dgst -sha256 -hmac &quot;$key&quot;"; #documented openssl-mac is not not existent anymore #my $MacCmd = "echo -n &quot;$msg&quot; | openssl-mac -macopt digest:SHA256 &quot;$key&quot;"; my $FuncCmd = "HmacSha256Tst -k &quot;$key&quot; -m &quot;$msg&quot;";

$p1Sig = hmac_sha256_hex($msg, $key); $p2Sig = hmac_hex($msg, $key, &amp;sha256); $p3Sig = hmac_sha256_base64($msg, $key);

$odSig = $DgstCmd; $odSig =~ /= (\w*)/;

$funcSig = $FuncCmd; print "message\t<$msg>\nkey\t<$key>\nsignatures:\n openssl = <$1>\n c-func = <$funcSig>\n perlSHA = <$p1Sig>\n perlHMAC = <$p2Sig>\n perlSHAbase = <$p3Sig>\n";

system ("openssl version");

shows:

message <Value-corresponding_to_openssls_EVP_MD structure>
key     <fq6if8aaxLTw0EHRAEkyvCbfa5O9BclbCCB6mtVsWO14KtyIdzIakzzlFGttMaw0>
signatures:
  openssl  = <2782c620c8c799d2c6b77d306cfca9be7dd2820effe66483d6b97dab7ada31f5>
  c-func   = <2782c620c8c799d2c6b77d306cfca9be7dd2820effe66483d6b97dab7ada31f5>
  perlSHA  = <2782c620c8c799d2c6b77d306cfca9be7dd2820effe66483d6b97dab7ada31f5>
  perlHMAC = <2782c620c8c799d2c6b77d306cfca9be7dd2820effe66483d6b97dab7ada31f5>
  perlSHAbase = <J4LGIMjHmdLGt30wbPypvn3Sgg7/5mSD1rl9q3raMfU>
OpenSSL 1.1.1g  21 Apr 2020

have fun