如何分两步生成与直接调用SHA256withRSA结果一致的RSA数字签名
问题解答
签名结果不一致的原因及修复
你手动签名和自动签名结果不同的核心原因是:SHA256withRSA 底层并不是直接对原始哈希值做RSA运算,而是会先将哈希值封装为符合PKCS#1 v1.5规范的DigestInfo DER编码结构,再对这个结构做签名,你之前的手动步骤缺失了封装DigestInfo的环节。
DigestInfo结构包含了哈希算法的OID标识和哈希值本身,针对SHA256算法,这个结构的前缀是固定的,你只需要手动拼接前缀和原始哈希值,再做NONEwithRSA签名即可得到和自动签名完全一致的结果。
修复代码示例
首先定义SHA256对应的固定前缀:
// SHA256对应的DigestInfo DER编码固定前缀 private static final byte[] SHA256_DIGEST_INFO_PREFIX = new byte[] { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, (byte)0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
修改主类中手动签名的逻辑,拼接前缀和哈希值后再签名:
//MANUALLY SIGN & VERIFY System.out.println("\nMANUALLY SIGN & VERIFY"); byte[] manualHashBytes = ManualHash.hash("SHA-256", dataBytes); // 拼接DigestInfo前缀和原始哈希值 byte[] digestInfoBytes = ByteBuffer.allocate(SHA256_DIGEST_INFO_PREFIX.length + manualHashBytes.length) .put(SHA256_DIGEST_INFO_PREFIX) .put(manualHashBytes) .array(); // 对DigestInfo结构做签名 byte[] manualSignatureBytes = ManualHash.sign("NONEwithRSA", privateKey, digestInfoBytes);
额外问题解答
数字签名是基于原始二进制哈希值计算的,Base64只是将二进制哈希值转换为可读文本的编码方式,不会参与实际的签名运算,如果你传入Base64编码后的字节做签名,得到的结果会是错误的。
内容的提问来源于stack exchange,提问作者ivoronline
相关产品推荐
相关产品推荐

