使用java安全提供程序单独摘要和签名

由于一些实现细节,我需要拆分散列和签名生成。 我尝试使用’NONEwithRSA’签名算法来实现这一点。

这是一个基本的工作示例:

public void rsaSignatureIntegrityTest() { KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); gen.initialize(2048, new SecureRandom()); KeyPair pair = gen.generateKeyPair(); byte[] digest = MessageDigest.getInstance("SHA-256").digest(MESSAGE); Signature signer = Signature.getInstance("NONEwithRSA"); signer.initSign(pair.getPrivate()); signer.update(digest); byte[] signed = signer.sign(); Signature verifier = Signature.getInstance("SHA256withRSA"); verifier.initVerify(pair.getPublic()); verifier.update(MESSAGE); verifier.verify(signed); } 

运行此命令, verifier.verify()方法将引发Signatureexception:

 java.security.SignatureException: Signature encoding error at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:204) at java.security.Signature$Delegate.engineVerify(Signature.java:1219) at java.security.Signature.verify(Signature.java:652) at testing.rsaSignatureIntegrityTest(testing.java:38) ... Caused by: java.io.IOException: Sequence tag error at sun.security.util.DerInputStream.getSequence(DerInputStream.java:297) at sun.security.rsa.RSASignature.decodeSignature(RSASignature.java:229) at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:195) ... 26 more 

validation者对象似乎期望某种DER编码结构,它不是由签名者对象产生的。

有关如何使其工作的任何建议?

如所怀疑的,RSA签名是使用包含的摘要值生成的,其中包含hash oid。 使用bouncycastle这可以很舒服地完成。

例:

 public void rsaSignatureIntegrityTest() { KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); gen.initialize(2048, new SecureRandom()); KeyPair pair = gen.generateKeyPair(); byte[] digest = MessageDigest.getInstance("SHA-256").digest(MESSAGE); Signature signer = Signature.getInstance("NONEwithRSA"); signer.initSign(pair.getPrivate()); signer.update(wrapForRsaSign(digest, "SHA-256")); byte[] signed = signer.sign(); System.out.println(Base64.getEncoder().encodeToString(signed)); Signature verifier = Signature.getInstance("SHA256withRSA"); verifier.initVerify(pair.getPublic()); verifier.update(MESSAGE); verifier.verify(signed); } private byte[] wrapForRsaSign(byte[] dig, String hashAlgo) { ASN1ObjectIdentifier oid = new DefaultDigestAlgorithmIdentifierFinder().find(hashAlgo).getAlgorithm(); ASN1Sequence oidSeq = new DERSequence(new ASN1Encodable[] { oid, DERNull.INSTANCE }); ASN1Sequence seq = new DERSequence(new ASN1Encodable[] { oidSeq, new DEROctetString(dig) }); try { return seq.getEncoded(); } catch (IOException e) { throw new DigestException(e); } }