在 Java 中验证 hmac sha1 签名
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18687926/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Verifying hmac sha1 signature in Java
提问by agerrr
I'd like to know how I could verify the signature I created. My code to create a signature looks similar to this one: HMAC-SHA1: How to do it properly in Java?
我想知道如何验证我创建的签名。我创建签名的代码与以下代码类似:HMAC-SHA1: How to do it right in Java?
I send the message, the signature and the public key to verify the signature. Public and private key are generated using KeyPairGenerator. How can I use the public key I have to verify my signature? Or maybe can you suggest any good libraries for Java for signing and verifying signature that use HMAC SHA1?
我发送消息、签名和公钥来验证签名。公钥和私钥是使用 KeyPairGenerator 生成的。如何使用我必须验证的公钥来验证我的签名?或者,您能否为 Java 推荐任何用于签名和验证使用 HMAC SHA1 的签名的好库?
回答by gtrig
First to clarify, the HMACcode does not generate a signature. It is a type of Message Authentication Code (MAC).
首先要澄清的是,HMAC代码不会生成签名。它是一种消息验证码 (MAC)。
The latter link explains the difference between a signature and a MAC this way:
后一个链接以这种方式解释了签名和 MAC 之间的区别:
MACs differ from digital signatures as MAC values are both generated and verified using the same secret key. This implies that the sender and receiver of a message must agree on the same key before initiating communications, as is the case with symmetric encryption. For the same reason, MACs do not provide the property of non-repudiation offered by signatures specifically in the case of a network-wide shared secret key: any user who can verify a MAC is also capable of generating MACs for other messages. In contrast, a digital signature is generated using the private key of a key pair, which is asymmetric encryption. Since this private key is only accessible to its holder, a digital signature proves that a document was signed by none other than that holder. Thus, digital signatures do offer non-repudiation. However, non-repudiation can be provided by systems that securely bind key usage information to the MAC key; the same key is in possession of two people, but one has a copy of the key that can be used for MAC generation while the other has a copy of the key in a hardware security module that only permits MAC verification. This is commonly done in the finance industry.
MAC 与数字签名不同,因为 MAC 值是使用相同的密钥生成和验证的。这意味着消息的发送者和接收者必须在启动通信之前就相同的密钥达成一致,对称加密就是这种情况。出于同样的原因,MAC 不提供签名提供的不可否认性,特别是在网络范围共享密钥的情况下:任何可以验证 MAC 的用户也能够为其他消息生成 MAC。相比之下,数字签名是使用密钥对的私钥生成的,这是非对称加密。由于此私钥只能由其持有者访问,因此数字签名证明文档是由该持有者以外的其他人签署的。因此,数字签名确实提供了不可否认性。然而,不可否认性可以由将密钥使用信息安全地绑定到 MAC 密钥的系统提供;同一个密钥由两个人所有,但一个人拥有可用于 MAC 生成的密钥副本,而另一个人拥有仅允许 MAC 验证的硬件安全模块中的密钥副本。这在金融行业很常见。
So in order to verify an HMAC, you need to share the key that was used to generate it. You would send the message, the HMAC, and the receiver would have the same key you used to generate the HMAC. They could then use the same algorithm to generate an HMAC from your message, and it should match the HMAC you sent. Public/private keys (assymetric) are not used for this. You need to generate a symmetric key (like AES) and securely share that with the people that will be generating/verifying the HMAC.
因此,为了验证 HMAC,您需要共享用于生成它的密钥。您将发送消息、HMAC,而接收方将拥有您用于生成 HMAC 的相同密钥。然后他们可以使用相同的算法从您的消息生成 HMAC,它应该与您发送的 HMAC 匹配。公钥/私钥(非对称)不用于此。您需要生成一个对称密钥(如 AES)并安全地与将生成/验证 HMAC 的人共享。
This limits the HMAC to having integrity
and authenticity
properties only, and not non-repudiation
.
这将 HMAC 限制为仅具有integrity
和authenticity
属性,而不是non-repudiation
。
The quote above mentioned that hardware security modules could be used to enforce the key use, and then you could get non-repudiation as long as only one person could use the key for generating the HMAC.
上面的引述提到硬件安全模块可以用来强制使用密钥,然后你就可以获得不可否认性,只要只有一个人可以使用密钥来生成 HMAC。
Alternatively, you could use a hybrid approach. Use a shared symmetric key to generate the HMAC. The HMAC in the end is a hash. You could then sign this hash with your private key (different than the key used in the HMAC). A third party with the symmetric key and your public key could verify you signed the HMAC, and could generate their own HMAC with the message and the shared key to make sure it matched. This would also give you non-repudiation.
或者,您可以使用混合方法。使用共享对称密钥生成 HMAC。最后的 HMAC 是一个哈希值。然后,您可以使用您的私钥(与 HMAC 中使用的密钥不同)对该哈希进行签名。拥有对称密钥和您的公钥的第三方可以验证您对 HMAC 的签名,并且可以使用消息和共享密钥生成他们自己的 HMAC 以确保它匹配。这也将为您提供不可否认性。
If you want to go this route, use the Java Signatureclass. The HMAC algorithm is SHA-1, and assuming your keypair is RSA, you could use the NONEwithRSA
Signature algorithm since the input is already a SHA-1 hash. Or you could hash it again with the SHA1withRSA
algorithm. As long as you generate the signature and verify with the same algorithm, it should be OK.
如果您想走这条路,请使用 Java Signature类。HMAC 算法是 SHA-1,假设您的密钥对是 RSA,您可以使用NONEwithRSA
签名算法,因为输入已经是 SHA-1 哈希。或者你可以用SHA1withRSA
算法再次散列它。只要生成签名,用同样的算法验证就可以了。
byte[] data = hmac.getBytes("UTF-8");
Signature mySig = Signature.getInstance("NONEwithRSA");
mySig.initSign(myPrivateKey);
mySig.update(data);
byte[] sigBytes = mySig.sign();
// And to verify.
Signature mySig2 = Signature.getInstance("NONEwithRSA");
mySig2.initVerify(myPublicKey);
boolean isSigValid = mySig2.verify(sigBytes);