0


我编写了以下代码来签署消息,然后在 Bouncy Castle 的 java 中验证它。
签名工作正常但验证不起作用。代码打印结果:
签名被篡改
无法恢复
并返回null。
为什么 eng.hasFullMessage() 函数返回 false 以及为什么下面的代码不起作用?
谢谢大家。

 
public static String sigVer(PublicKey pu, PrivateKey pr, String original) throws Exception{
        //sign
        BigInteger big = ((RSAKey) pu).getModulus();
byte[] text = original.getBytes();
RSAKeyParameters rsaPriv = new RSAKeyParameters(true, big,((RSAPrivateKey) pr).getPrivateExponent()); RSAKeyParameters rsaPublic = new RSAKeyParameters(false, big,((RSAPublicKey) pu).getPublicExponent()); RSAEngine rsa = new RSAEngine(); byte[] data; Digest dig = new SHA1Digest(); ISO9796d2Signer eng = new ISO9796d2Signer(rsa, dig, true); eng.init(true, rsaPriv); eng.update(text[0]); eng.update(text, 1, text.length - 1);
data = eng.generateSignature(); String signature = data.toString(); //verify eng = new ISO9796d2Signer(rsa, dig, true); eng.init(false, rsaPublic); text = signature.getBytes(); if (!eng.verifySignature(text)) { System.out.println("signature tampered"); } try{ if (eng.hasFullMessage()) { eng.updateWithRecoveredMessage(signature.getBytes());
} byte[] message = eng.getRecoveredMessage(); String ss = message.toString(); return ss; } catch (Exception e) { System.out.println("can not recover"); return null;
}

}
4

3 回答 3

0

实际上,要验证大消息,您必须提供验证输入,即原始消息,而不仅仅是仅用于完全恢复的签名

//verify
eng = new ISO9796d2Signer(rsa, dig, true);
eng.init(false, rsaPublic);

// when verifying there has to be also the original plain text
eng.update(text,0,text.length);

signBytes = signature.getBytes(); 
if (!eng.verifySignature(signBytes)) {
     System.out.println("signature tampered");
}
于 2013-03-18T21:47:15.637 回答
0

我玩弄了这种方法,也收到了错误。此外,提到的“更新”方法不起作用,并且“updateWithRecoveredMessage”不存在。

经过一些测试,我发现:

  • 我必须起诉 getBytes("UTF-8") 和 String s = new String(message, "UTF-8")
  • 我最多可以在签名中使用 234 个字节,如果有 235 个字节就会损坏。(猜想它是 256 字节,但有些用于填充/标记)

如果我理解正确,问题是签名者只允许在签名中包含一定数量的字节。

如果您使用更长的有效负载,您还必须在验证步骤中包含有效负载:

    eng.init(false, rsaPublic);
    byte[] message = payload.getBytes("UTF-8");
    eng.update(message, 0, message.length);

然后验证工作正常,您可以使用 eng.getRecoveredMessage() 获得有效负载的第一部分。

对我来说,这违背了目的,所以我走了另一条路。

我使用的解决方法是两个两步法:

1)我生成一个存储在签名中的短密钥 2)使用对称(即AES)加密大有效载荷。我还为有效载荷生成了一个哈希值。3) 有效载荷的密钥和散列是包含在签名中的。

于 2013-12-29T10:25:32.863 回答
0

大多数时候,我们没有要更新和验证签名的原始消息。另一方面,长度限制为 234 个字节。

于 2019-09-25T09:52:48.800 回答