如何使“ MessageDigest SHA-1和Signature NONEwithRSA”等效于“ Signature SHA1withRSA”

ems*_*rth 5 java hash rsa keystore sha

我对将具有RSA签名的SHA-1哈希应用于某些数据感兴趣,但是我需要分两个步骤进行-先应用哈希,然后对数据签名。Signature.sign()函数似乎会创建一个更复杂的(ASN.1?)数据结构,该数据结构最终会被签名(请参阅此问题)。如何在不使用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();
Run Code Online (Sandbox Code Playgroud)

通过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();
...
Run Code Online (Sandbox Code Playgroud)

我正在寻找以下等效项:

bSignedData_JAVASHA1_CAPIRSA == bSignedData_CAPISHA1_CAPIRSA
Run Code Online (Sandbox Code Playgroud)

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

ems*_*rth 4

我能够通过执行以下操作来解决此问题:

  1. 要签名的数据需要在 DigestInfo DER 编码的字节数组中正确格式化。Signature SHA1withRSA 会为您处理这个问题,但如果您想通过两步过程完成它,您需要创建自己的 DigestInfo。尽管我不想使用第三方库,但我最终还是从 BouncyCastle 中复制了极少量的 ASN.1 类到我的项目中来完成此任务。

  2. 如果您尝试使用 Cipher API 加密 DigestInfo,则 PKCS1 填充将是随机的,不适合数字签名。我需要静态填充。

  3. Signature.getInstance("NONEwithRSA", "SunMSCAPI") 拒绝 DER 编码的 DigestInfo 格式,如果您尝试对该数据进行签名,则会返回错误。但是,由于我最终想使用 PKCS11 API 来生成签名,因此我最终使用 PKCS11 C_SignInit 和 C_Sign 函数对 DER 编码的 DigestInfo 进行签名。

总而言之,对我有用的是:

  1. 使用 Java MessageDigest API 生成要签名的数据的 SHA-1 哈希值
  2. 生成了 DigestInfo DER 编码的 ASN.1 对象,其中嵌入了 SHA-1 哈希和 SHA-1 OID。
  3. 使用第三方库中的 PKCS11 C_Sign 函数对 DigestInfo 进行签名。

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

Oracle 论坛:SHA1withRSA - 如何通过 2 个步骤完成此操作?

StackOverflow:使用 SHA1 和 RSA 与 java.security.Signature 对比 MessageDigest 和 Cipher