我正在使用 Java 编写一个程序,使用 javax.crypto.Mac 为给定的字符串生成 HMAC。
但为了排除故障和实验,我使用 openssl dgst 生成 HAMC(使用 SHA256)。我观察到即使未传递密钥,该命令也会成功执行。例如,
在 shell 上使用 openssl 生成 HMAC 的标准方法,
echo -n "data" | opnessl dgst -sha256 -hmac "KEY1"
Run Code Online (Sandbox Code Playgroud)
不过我也可以执行以下操作,
echo -n "data" | opnessl dgst -sha256 -hmac
Run Code Online (Sandbox Code Playgroud)
并且两个命令都成功运行并具有不同的输出。
我假设 openssl 可以将不存在的密钥视为“\0”(空)密钥。
实际上我的问题是我无法使用 javax.crypto.Mac 并提供带有 byte[0] = 0 的 SecretKey 来生成类似的结果;(单字节密钥,值为 0)。
编辑:根据 OpenSSSL 邮件列表上的 Rich Salz 的说法,该密钥对于该选项不是-hmac可选的。预计该命令的行为openssl dgst将来会发生变化。
OpenSSL 1.0.2 或 1.1.0 可能会发生此更改。它可能会向后移植到 1.0.1 等较低版本,但不能保证。
实际上我的问题是我无法使用 javax.crypto.Mac 并提供带有 byte[0] = 0 的 SecretKey 来生成类似的结果;
只需使用 SHA-256 哈希值,而不是 HMAC。如果这是 TLDR;然后跳到最后;)
感兴趣的源文件是<openssl src>/apps/dgst.c. 第 225 行是(或应该)设置密钥的地方,但不是因为没有以下参数:
else if (!strcmp(*argv,"-hmac"))
{
if (--argc < 1)
break;
hmac_key=*++argv;
}
Run Code Online (Sandbox Code Playgroud)
如果密钥未作为参数传入,则 openssl(命令)对 HMAC 使用什么密钥
要回答这个问题,我们需要看看源码<openssl src>/apps/dgst.c。
开关-hamc填充了变量hmac_key,但它NULL被跳过了。另一个感兴趣的变量是sigkey,但它也NULL因此也被跳过。
第 513 行左右是事情变得有趣的地方。几乎所有其他内容都被跳过dgst.c(从下面开始lldb):
513 if (argc == 0)
514 {
-> 515 BIO_set_fp(in,stdin,BIO_NOCLOSE);
516 err=do_fp(out, buf,inp,separator, out_bin, sigkey, sigbuf,
517 siglen,NULL,NULL,"stdin",bmd);
518 }
(lldb) p sigkey
(EVP_PKEY *) $25 = 0x0000000000000000
Run Code Online (Sandbox Code Playgroud)
所以我们需要做的就是查看do_fp,如下所示。感兴趣的行是 627,在此执行:
len=BIO_gets(bp,(char *)buf,BUFSIZE);
Run Code Online (Sandbox Code Playgroud)
这BIO bp是一条链,它把你的哈希值链接到它上面。因此,您放入其中的任何内容都会被散列。并且哈希值没有被键入,因为hmac_key和sigkey是NULL。
在第 654 行,遇到了这样的情况:
BIO_printf(out, "(%s)= ", file);
Run Code Online (Sandbox Code Playgroud)
在第655-660行,遇到执行十六进制编码的循环。
结合起来,它们会产生如下内容:
(stdin)= 6667b2d1aab6a00caa5aee5af8ad9f1465e567abf1c209d15727d57b3e8f6e5f
Run Code Online (Sandbox Code Playgroud)
int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
EVP_PKEY *key, unsigned char *sigin, int siglen,
const char *sig_name, const char *md_name,
const char *file,BIO *bmd)
{
size_t len;
int i;
for (;;)
{
i=BIO_read(bp,(char *)buf,BUFSIZE);
if(i < 0)
{
BIO_printf(bio_err, "Read Error in %s\n",file);
ERR_print_errors(bio_err);
return 1;
}
if (i == 0) break;
}
if(sigin)
{
EVP_MD_CTX *ctx;
BIO_get_md_ctx(bp, &ctx);
i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int)siglen);
if(i > 0)
BIO_printf(out, "Verified OK\n");
else if(i == 0)
{
BIO_printf(out, "Verification Failure\n");
return 1;
}
else
{
BIO_printf(bio_err, "Error Verifying Data\n");
ERR_print_errors(bio_err);
return 1;
}
return 0;
}
if(key)
{
EVP_MD_CTX *ctx;
BIO_get_md_ctx(bp, &ctx);
len = BUFSIZE;
if(!EVP_DigestSignFinal(ctx, buf, &len))
{
BIO_printf(bio_err, "Error Signing Data\n");
ERR_print_errors(bio_err);
return 1;
}
}
else
{
len=BIO_gets(bp,(char *)buf,BUFSIZE);
if ((int)len <0)
{
ERR_print_errors(bio_err);
return 1;
}
}
if(binout) BIO_write(out, buf, len);
else if (sep == 2)
{
for (i=0; i<(int)len; i++)
BIO_printf(out, "%02x",buf[i]);
BIO_printf(out, " *%s\n", file);
}
else
{
if (sig_name)
{
BIO_puts(out, sig_name);
if (md_name)
BIO_printf(out, "-%s", md_name);
BIO_printf(out, "(%s)= ", file);
}
else if (md_name)
BIO_printf(out, "%s(%s)= ", md_name, file);
else
BIO_printf(out, "(%s)= ", file);
for (i=0; i<(int)len; i++)
{
if (sep && (i != 0))
BIO_printf(out, ":");
BIO_printf(out, "%02x",buf[i]);
}
BIO_printf(out, "\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果您想自己进行操作,请下载并解压 OpenSSL 源代码。然后,使用调试版本进行配置:
cd openssl-1.0.1h
./Configure debug-darwin64-x86_64-cc no-ssl2 enable-ec_nistp_64_gcc_128
make depend && make
Run Code Online (Sandbox Code Playgroud)
在调试器下打开它:
cd openssl-1.0.1h
lldb apps/openssl
Run Code Online (Sandbox Code Playgroud)
最后运行它:
(lldb) b dgst.c:513
(lldb) r dgst -sha256 -hmac
Run Code Online (Sandbox Code Playgroud)
调试器应该靠近do_fp:
Process 27371 stopped
* thread #1: tid = 0x286a3, 0x000000010000ba99 openssl`dgst_main(argc=0, argv=0x00007fff5fbffa60) + 5961 at dgst.c:513, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x000000010000ba99 openssl`dgst_main(argc=0, argv=0x00007fff5fbffa60) + 5961 at dgst.c:513
512
-> 513 if (argc == 0)
514 {
515 BIO_set_fp(in,stdin,BIO_NOCLOSE);
516 err=do_fp(out, buf,inp,separator, out_bin, sigkey, sigbuf,
(lldb)
Run Code Online (Sandbox Code Playgroud)
诀窍是:当您输入 时do_fp,程序将从 开始读取stdin。输入您的字符串(即data),然后按CTRL+D结束它。
现在,在这一切之后,这是简短的答案:)
$ echo -n "data" | openssl dgst -sha256 -hmac
(stdin)= 3a6eb0790f39ac87c94f3856b2dd2c5d110e6811602261a9a923d3bb23adc8b7
$ echo -n "data" | openssl dgst -sha256
(stdin)= 3a6eb0790f39ac87c94f3856b2dd2c5d110e6811602261a9a923d3bb23adc8b7
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3135 次 |
| 最近记录: |