签署消息并通过Bouncy Castle的恢复消息进行validation

我编写了以下用于签名消息的代码,然后在Bouncy Castle的java中validation它。
正确签署工作但validation不起作用。 代码打印的结果:
签名被篡改
无法恢复
并返回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;
} }

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

实际上,要validation大型邮件,您必须提供validation输入,这是原始邮件,而不仅仅是完全恢复的签名

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

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

经过一些测试,我认为:

  • 我必须起诉getBytes(“UTF-8”)和String s = new String(消息,“UTF-8”)
  • 我可以在签名中使用最多234个字节,其中235将会中断。 (猜测它将是256字节,但有些用于填充/标记)

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

如果使用更长的有效负载,则必须在validation步骤中包含有效负载:

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

然后validation工作正常,你用eng.getRecoveredMessage()获得有效负载的第一部分。

对我来说这打败了目的,所以我采取了另一种方式。

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

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