我即将努力计算 sha256 签名,其结果与 <openssl dgst -sha256 -hmac> 计算的结果相同。这个主题已经讨论过问题。受此内容的启发,我编写了一个小型 Perl 脚本,以便了解 sha256 HMAC 计算的不同实现。
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 \"$msg\" | openssl dgst -sha256 -hmac \"$key\"";
$p1Sig = hmac_sha256_hex($msg, $key);
$p2Sig = hmac_hex($msg, $key, \&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");
结果不符合预期(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
我在 Linux 系统上运行它(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
所有 Perl 版本都显示相同的结果。 openssl 显示不同的结果。最有趣的是不同的 openssl 版本显示不同的结果。
问题1:openssl版本之间结果不同的原因是什么?问题2:perl中是否有解决方案产生与openssl dgst -sha256 -hmac
.
玩得开心
答案1
my $DgstCmd = "echo \"$msg\" | openssl dgst -sha256 -hmac \"$key\"";
echo
向消息添加换行符。因此,这在 Linux 上进行了摘要"$msg\n"
,而不是$msg
.我不确定它在 Windows 上到底做了什么才能获得这个摘要值,但它绝对不仅仅是输出$msg
.
换句话说:Perl 和 openssl 都没有错。您只需为 openssl 提供与 Perl 代码不同的输入即可。
答案2
你是对的,谢谢你,史蒂芬。
这个问题是由 crpyto api 引起的。有时消息必须使用 hmac-sha256 进行签名。我真正的问题是我的计算机运行的系统时间以及提供商的计算机时间。
如果使用 c 版本完成了测试集 perl 和 openssl。对于任何有兴趣拥有工作测试平台的人:
c-function,在之前的聊天中找到,只是打包为可执行文件:
// 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, "?hvk:m:")) != -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 ("unknown option <%c>\n", c);
usage (argv[0]);
return (-1);
}
}
if ((argc - optind) > 0 ) {
printf ("err: to many parameters, confused\n");
usage (argv[0]);
return (-2);
}
if (!key) {
key = strdup ("security is awesome");
}
keylen = strlen(key);
if (!msg) {
msg = strdup ("this is highly sensitive user data");
}
msglen = strlen(msg);
result = mx_hmac_sha256 ((const void *)key, keylen, (unsigned char *) msg, msglen, result, &resultlen);
if (resultlen) {
c = (2 * resultlen) + 1;
buffer = malloc ((sizeof(char) *c));
memset (buffer, 0, c);
for (i = 0, p = buffer; i < resultlen; i++) {
sprintf (p, "%02x", result[i]);
p += 2;
}
if (flag & VERBOSE) {
printf ("message: <%s>\nkey: <%s>\nsignature <%s>\n", key, msg, buffer);
} else {
printf ("%s",buffer);
}
return (0);
} else {
printf ("no signature\n");
}
}
/*---------------------------------------------------------------------------
* 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;
}
驱动perl脚本:
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 \"$msg\" | openssl dgst -sha256 -hmac \"$key\"";
my $DgstCmd = "echo|set /p=\"$msg\" | openssl dgst -sha256 -hmac \"$key\"";
#documented openssl-mac is not not existent anymore
#my $MacCmd = "echo -n \"$msg\" | openssl-mac -macopt digest:SHA256 \"$key\"";
my $FuncCmd = "HmacSha256Tst -k \"$key\" -m \"$msg\"";
$p1Sig = hmac_sha256_hex($msg, $key);
$p2Sig = hmac_hex($msg, $key, \&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");
显示:
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
玩得开心