Java Signature.verify导致SignatureException:签名编码错误由IOException引起:序列标记错误

时间:2014-11-21 02:20:17

标签: java cryptography smartcard

首先,这不是一个重复的问题,因为大多数人在从缺少的证书创建公钥时报告此异常" --- BEGIN RSA CERTIFICATE ---"线。

我想要做的就是 1.使用SHA1withRSA算法在JCOP智能卡上签名50Byte消息(RSA密钥为1024位)。 2.将签名从智能卡导出到服务器。 3.验证服务器上的签名。

智能卡上的代码段创建签名。关键点是我在Java Card中使用算法Signature.ALG_RSA_SHA_PKCS1来创建签名。

private void setcustccid(APDU apdu) {

    byte[] buffer = apdu.getBuffer();
    if (buffer[ISO7816.OFFSET_LC] != (byte)24) {
      ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    }
    else {
      short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
      short readCount = apdu.setIncomingAndReceive();
      if (readCount < bytesLeft) {
        ISOException.throwIt(ISO7816.SW_BYTES_REMAINING_00);
      }
      try {
                  Signature signature = Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
        signature.init(privKey, Signature.MODE_SIGN);
        Util.arrayCopy(buffer, (short)buffer[ISO7816.OFFSET_CDATA], tempStorage, (short) 0, (byte)24);
        Util.arrayCopy(transactionHistory, (short)0, tempStorage, (short)24, (byte)30);
      } 
      catch (Exception ex) {
        ISOException.throwIt(ISO7816.SW_BYTES_REMAINING_00);
      }

      signature.sign(tempStorage, (short)0, (short)50, finalEncryptedMsg, (short)0);
    }
    }

服务器端的代码片段,试图验证从抛出异常的Java智能卡导出的签名。这里的关键点是我在服务器端使用Signature.getInstance(&#34; SHA1withRSA&#34;)。我正在对签名消息进行Cipher解密,以确认生成的公钥是否正常工作。

modulusString = new BigInteger(1, rsaModulus);
exponentString = new BigInteger(1, rsaExponent);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(modulusString, exponentString);
KeyFactory factor = KeyFactory.getInstance("RSA"); 
PublicKey publicKey = (RSAPublicKey) factor.generatePublic(keySpec);
rsaCipher = Cipher.getInstance("RSA");
rsaCipher.init(Cipher.DECRYPT_MODE, publicKey);
signature = Signature.getInstance("SHA1withRSA");
signature.initVerify(publicKey);
signature.update(resultBytes);
signature.verify(finalEncryptedMsg);
tempStorage = rsaCipher.doFinal(finalEncryptedMsg);
System.out.println("Decrypted Length = " + tempStorage.length);

signature.verify()上发生异常。另一个线程引用了同样的异常,但解决方案是在Signature.getInstance()中添加Bouncy Castle作为Provider。不知道为什么需要Bouncy Castle来验证签名。

非常感谢任何帮助。如果您需要更多代码来确定问题,请告诉我们。

java.security.SignatureException: Signature encoding error
    at sun.security.rsa.RSASignature.engineVerify(Unknown Source)
    at java.security.Signature$Delegate.engineVerify(Unknown Source)
    at java.security.Signature.verify(Unknown Source)
    at com.mse.reader.SmartCardReader.main(SmartCardReader.java:234)
Caused by: java.io.IOException: Sequence tag error
    at sun.security.util.DerInputStream.getSequence(Unknown Source)
    at sun.security.rsa.RSASignature.decodeSignature(Unknown Source)
    ... 4 more

这是加密消息和解密消息。 (Base4.encodeBase64)

加密长度= 128

JpypH/vKYR4RLjQA4frCab5WljnAoWgNiGUb0k+DCmh8gdWbOtpR/XUec2rW96Nr1k7czNTb2s/2WQDGXe05a3JjNrlErrfijhdWvn9flIzR/5uPrS3VJw+ALESl8NWqR5HF3AgArE6uYIW87EtSjO0iPJTO2N0cITtLghdUSBs=

解密长度= 50

gCUAABgAAAAAO5rJkAAAAAAAvGFOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=

1 个答案:

答案 0 :(得分:0)

您已将智能卡提供程序移到Java SE上的其他提供程序之前,并且出于某种原因,它还尝试验证RSA签名,而不是仅将其用于RSA私钥操作。

有几种方法可以解决这个问题:

  1. 如果您使用相同的签名实例进行验证,则使用另一个用于使用公钥进行验证
  2. 如果这不能解决您的问题,请尝试查看您是否可以在Security课程的提供商列表中移动智能卡提供商(请查看JCA documentation如何执行此操作)
  3. 否则只需使用Signature类提供正确的提供者,我建议指定"SunRsaSign"(您可能希望使此字符串可配置)
  4. com.mse后面的公司解释他们应该正确实施延迟提供商选择而不是吞噬软件公钥以便在其硬件设备中使用
  5. 请注意,由于智能卡充当服务器,因此谈论“服务器端”非常困惑。 “终端方”和“卡方”将更加清晰。