单独的摘要&使用java安全提供程序签名 [英] Separate digest & signing using java security provider

查看:279
本文介绍了单独的摘要&使用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.getInstance(NONEwithRSA);
signer.initSign(pair.getPrivate());
signer.update(digest);
byte [] signed = signer.sign();

签名验证者= Signature.getInstance(SHA256withRSA);
verifier.initVerify(pair.getPublic());
verifier.update(MESSAGE);
verifier.verify(signed);

$ / code>

运行这个函数, verifier.verify()方法抛出Signature异常:

  java.security.SignatureException:签名编码错误
at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:204)$ java.util.Signature中的
$ Delegate.engineVerify(Signature.java:1219)$ java.util.Signature.verify中的$ b $( Signature.java:652)
位于testing.rsaSignatureIntegrityTest(testing.java:38)
...
引起:java.io.IOException:序列标记错误
在太阳.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

验证器对象似乎期望某种DER编码结构,它不是由signer对象产生的。



任何s uggestions如何让这个工作成功?

解决方案

可疑的是,RSA签名是用一个包装摘要值生成的, 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.getInstance(NONEwithRSA);
signer.initSign(pair.getPrivate());
signer.update(wrapForRsaSign(摘要,SHA-256));
byte [] signed = signer.sign();
System.out.println(Base64.getEncoder()。encodeToString(signed));

签名验证者= Signature.getInstance(SHA256withRSA);
verifier.initVerify(pair.getPublic());
verifier.update(MESSAGE);
verifier.verify(signed);

$ b 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)});
尝试{
return seq.getEncoded();
} catch(IOException e){
throw new DigestException(e);
}
}


Due to some implementation detail, I need to split hashing and signature generation. I tried to achieve this using the 'NONEwithRSA' signature algorithm.

This is a basic working example:

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);
}

Running this, the verifier.verify() method throws a Signature exception:

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

The verifier object seems to expect some kind of DER encoded structure, which is not produced by the signer object.

Any suggestions on how to get this to work?

解决方案

As suspected, RSA signatures are generated with a wrapped digest value, containing the hash oid. Using bouncycastle this can be done quite comfortably.

Example:

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);
    }
}

这篇关于单独的摘要&使用java安全提供程序签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆