我对将具有RSA签名的SHA-1哈希应用于某些数据感兴趣,但是我需要分两个步骤进行操作-首先应用哈希,然后对数据进行签名。 Signature.sign()函数似乎会创建一个更复杂的(ASN.1?)数据结构,该数据结构最终会被签名(请参阅this question)。如何在不使用BouncyCaSTLe之类的任何外部库的情况下使两者等效?

应用哈希并使用签名单步登录:

PrivateKey privatekey = (PrivateKey) keyStore.getKey(alias, null);
...
sig = Signature.getInstance("SHA1withRSA", "SunMSCAPI");
sig.initSign(privatekey);
sig.update(data_to_sign);
byte[] bSignedData_CAPISHA1_CAPIRSA = sig.sign();

通过MessageDigest应用哈希,然后使用签名签名:
PrivateKey privatekey = (PrivateKey) keyStore.getKey(alias, null);
...
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
byte[] data_to_sign = sha1.digest(bdataToSign);
Signature sig = Signature.getInstance("NONEwithRSA", "SunMSCAPI");
sig.initSign(privatekey);
sig.update(data_to_sign);
byte[] bSignedData_JAVASHA1_CAPIRSA = sig.sign();
...

我正在寻找以下等效项:
bSignedData_JAVASHA1_CAPIRSA == bSignedData_CAPISHA1_CAPIRSA

我的最终目标是创建哈希,然后使用PKCS11 token 签名,但出于验证目的,我要求签名的数据必须与旧数据的格式相同。

最佳答案

我可以通过执行以下操作解决此问题:

  • 要签名的数据需要正确格式化为
    DigestInfo DER编码的字节数组。带有SHA1withRSA的签名
    为您解决这个问题,但是如果您要分两步完成
    流程中,您需要创建自己的DigestInfo。我最终复制了
    从BouncyCaSTLe到我的ASN.1类的数量非常少
    尽管我希望不使用第三个
    党库
  • 如果您尝试使用Cipher API加密DigestInfo,则
    PKCS1填充将是随机的,不适用于数字
    签名。我需要静态填充。
  • Signature.getInstance(“NONEwithRSA”,“SunMSCAPI”)拒绝
    DER编码的DigestInfo格式,如果尝试则将返回错误
    对数据进行签名。但是,由于我最终想使用PKCS11
    API生成签名,我最终签署了DER编码的签名
    具有PKCS11 C_SignInit和C_Sign函数的DigestInfo。

  • 总而言之,对我有用的是:
  • 使用Java MessageDigest API
  • 生成数据的SHA-1哈希以进行签名
  • 生成了一个DigestInfo DER编码的ASN.1对象,其中嵌入了SHA-1哈希和SHA-1 OID。
  • 使用第三方库中的PKCS11 C_Sign函数对DigestInfo进行了签名。

  • 以下链接对解决我的问题最有帮助:

    Oracle Forums: SHA1withRSA - how to do that in 2 steps?

    StackOverflow: Using SHA1 and RSA with java.security.Signature vs. MessageDigest and Cipher

    10-08 00:51