【问题标题】:How to sign data in PHP with HMAC using a PEM private key如何使用 PEM 私钥使用 HMAC 对 PHP 中的数据进行签名
【发布时间】:2016-02-10 11:58:29
【问题描述】:

我看过很多关于如何在 PHP 中创建 HMAC 的帖子,但使用的秘密始终是一个简单的字符串(例如“秘密”)。我需要做的是创建一个 HMAC,其秘密是私钥,例如从包含 PEM 格式私钥的文件中加载。我一直无法找到任何关于这在 PHP(使用 hash_hmac)中是否可行的信息。

用法

使用私钥的 HmacSHA256 签名是在 Java 中创建的,我想使用从文件加载的相同私钥在 PHP 中重新创建此签名(根据我的理解,使用带有 sha256 散列算法的 hash_hmac)。

澄清: 在这种情况下,私钥用作共享密钥,这意味着双方拥有密钥。消息验证过程包括发送带有消息的 HMAC,使用私钥计算,而接收者使用相同的私钥计算 HMAC,并根据发送的签名验证它。

代码

Java:

byte[] data = getDataForSignature();
PrivateKey key = getPrivateKey(); // loaded from a file
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
byte[] hmac = mac.doFinal(data);
// compare hmac with received signature bytes

PHP:

$key = openssl_pkey_get_private("private.key");
$sig = hash_hmac("sha256", $data, $key??, true);

示例私钥

-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQCSWro05ZKVGxMTCqAyNZRAXp8Gd7wf6vywXRsFckm9MHOAWZL0
SvFAhM6tlCthuPkQb0c+Hx9PWH1+4sW2u3O+VDvjQEB0ZILd79LraBEshK/36Oux
yyw2K+ghk9Yh00nJOzkkonmdZmVxr0AAzw5el2h9yDjlUa1E8BH/1LzBBwIDAQAB
AoGANtwXbHiZh5bMgZi8D9YRqkdNqOj89aHp8loUJOiAR5B/2x64fSYSZLLjniEq
WckyYzyzIdActmtfL07l+ecuLRipsHoHuzjPiiRRnzJQbgBstnB8rHkuN275YSbC
3gE7nyyX0JPEviwqHv++Uig0RCD1ZbrG0SBMKBlGVrFMddECQQDmVguRhRScTJHH
RaXY/zjZtHp0L1dtzzSLM75+ji2UoRy1yK9z+rnE1PM5QC8PQixbwocGwpRIwGQn
hIg1YAM9AkEAoqk+VNbJ9ykoP9r+8o1PrPR1Ff+EIhpTthRyFngHNbNnOFB0D314
+V4wyO+a/gbiIAmvTuOXV/GwOlgnfVDJkwJBAJNHd5QvxPL/3sLNXPN4ljBWP2pl
DwFO2Wkcx/SCEtETh5kQ3mdJbVlXVMJJsQ2PoW923gHLjydJpYDDNJj0cH0CQQCW
8txHOvQ+C9GwQHirenvgExO9EFv8kdXxeNPPCiAWs6AsYGz0Gwpyz/gR4FlDN/wM
ozAu04IVONLDsh8jah9FAkEAsSUvlo7Nh1ITd75kUsStv7Tjxma3SuKViewWCprD
olDNtncfcZC5SrilHAJEabVxGy1fJL3hYvTYfqNkeB1TcA==
-----END RSA PRIVATE KEY-----

【问题讨论】:

  • Java 代码中的key.getClass().getName() 得到了什么? PrivateKey 只是其下特定类的父级。您也可以显示示例密钥文件吗?在这种情况下,getPrivateKey 似乎是一个重要的功能。
  • @MaartenBodewes 这是一个 sun.security.rsa.RSAPrivateCrtKeyImpl,我还添加了一个示例密钥
  • 嗯,Java 只使用 byte[] secret = key.getEncoded(); 作为键(谁会有 thunk :))。因此,您使用内部 PKCS#8 编码作为密钥。这当然不是一个好习惯,但是如果您可以在 PHP 中使用 binary DER 编码对密钥进行编码,那么您将是黄金。
  • 我对你最后的评论只了解一点,我想知道那里到底有什么不好的做法,关于使用二进制 DER 编码的第二部分是什么,但是周五晚上我是累了。
  • 对 MAC 使用 RSA 公钥更糟糕;您会期望 RSA 公钥是公开的。你当然不应该将它用于 MAC,它根本没有意义。

标签: java php hash signature hmac


【解决方案1】:

通常使用私钥来执行签名生成,这是非对称等效于使用对称密钥创建 MAC。

请注意,HMAC 密钥可以由任何二进制字符串组成,因此原则上可以将 HMAC 与二进制编码的私钥一起使用。也就是说,对 HMAC 使用非对称私钥是没有意义的。只有持有私钥的人才能验证生成的身份验证标签。相比之下,可以使用密钥对的公钥来验证数字签名。


现在,如果您有一个在 Java 中使用的 secret 密钥,那么您需要为 PHP hash_hmac 函数创建相同的(二进制)key 参数。

【讨论】:

  • 首先,感谢您的回答。澄清一下,这个场景中的私钥被用作共享密钥,这意味着两方都有密钥。消息验证过程包括发送带有消息的 HMAC,使用私钥计算,而接收者使用相同的私钥计算 HMAC,并根据发送的签名验证它。因此,虽然您的回答没有错,但它并没有回答我的问题,即如何使用存储在文件中的私钥和 PHP hash_hmac 函数来创建与使用 Mac 界面的 Java 制作的签名相同的签名。
  • 如果你不展示 Java 代码和你为 PHP 尝试的内容,将很难回答这个问题。
  • 我会尽快解决的。
猜你喜欢
  • 2014-01-13
  • 1970-01-01
  • 1970-01-01
  • 2019-05-13
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
  • 2019-05-26
相关资源
最近更新 更多