Java Signature.verify结果SignatureException:签名编码错误导致IOException:序列标记错误 [英] Java Signature.verify results in SignatureException: Signature encoding error Caused by IOException: Sequence tag error

查看:19507
本文介绍了Java Signature.verify结果SignatureException:签名编码错误导致IOException:序列标记错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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

  private void setcustccid ){

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.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(SHA1withRSA)。我正在对签名的消息进行密码解密,以确认生成的公钥是否正在工作。

  modulusString = new BigInteger(1,rsaModulus); 
exponentString = new BigInteger(1,rsaExponent);
RSAPublicKeySpec keySpec = new RSPublicKeySpec(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()上发生异常。另一个线程引用这个相同的异常,但解决方案是添加Bouncy Castle作为Provider在Signature.getInstance()。不知道为什么Bouncy城​​堡将需要验证签名。



任何帮助将非常感谢。如果您需要更多的代码来识别问题,请告诉我。

  java.security.SignatureException:签名编码错误
at sun.security.rsa.RSASignature.engineVerify(未知源)
at java.security.Signature $ Delegate.engineVerify(未知源)
at java.security.Signature.verify(未知源) )
at com.mse.reader.SmartCardReader.main(SmartCardReader.java:234)
引发者:java.io.IOException:序列标记错误
at sun.security.util.DerInputStream .getSequence(未知源)
at sun.security.rsa.RSASignature.decodeSignature(unknown Source)
... 4 more

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



加密长度= 128

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

解密长度= 50

  gCUAABgAAAAAO5rJkAAAAAAAvGFOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA = 


解决方案

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



有几种解决方法:


  1. 使用相同的签名实例进行验证,然后使用不同的身份验证公钥

  2. ,如果这不能解决您的问题,请尝试看看是否可以移动智能卡提供程序在安全类中的提供程序列表中(检查 JCA文档,了解如何执行此操作)

  3. 否则只需提供正确的提供商, code> Signature 类,我建议指定SunRsaSign(您可能希望使此字符串可配置)

  4. com.mse 后面的公司解释,他们应该正确实施延迟提供程序选择 ,而不是冻结软件公钥


  5. 请注意,由于智能卡作为服务器,所以说服务器端是非常混乱的。 终端侧和卡侧将更清楚。


    first of all this is not a duplicate question as most people report this exception when creating a Public Key from a Certificate which is missing "---BEGIN RSA CERTIFICATE---" line.

    gist of what I am trying to do is 1. Sign a 50Byte message on JCOP Smart card using SHA1withRSA algorithm (RSA Key is 1024 bits). 2. Export the signature from smart card to server. 3. Verify the signature on the server.

    Code snippet on the smart card to create the signature. The key point is I am using algorithm Signature.ALG_RSA_SHA_PKCS1 in the Java Card to create the signature.

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

    Code snippet on the Server side trying to verify the signature exported from the Java Smart card which is throwing the exception. The key point here is I am using Signature.getInstance("SHA1withRSA") on the server side. I am doing Cipher decrypt of the signed message just to confirm that the public key generated is working and it is.

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

    The exception happens on signature.verify(). Another thread referred to this same exception but the solution was to add Bouncy Castle as the Provider in Signature.getInstance(). Not sure why Bouncy Castle would be required for verification of signature.

    Any help would be greatly appreciated. If you need more of the code to identify the issue please let me know.

    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
    

    Here is the Encrypted Msg and Decrypted Msg. (Base4.encodeBase64)

    Encrypted Length = 128

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

    Decrypted Length = 50

    gCUAABgAAAAAO5rJkAAAAAAAvGFOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
    

    解决方案

    You've moved your smart card provider in front of the other providers on Java SE, and for some reason it is also trying to verify RSA signatures instead of just using it for RSA private key operations.

    There are a few methods of solving this:

    1. if you are using the same signature instance for verification, then use a different one for the verification with the public key
    2. if that doesn't solve your problem, try and see if you can move the smart card provider down in the list of providers in the Security class (check the JCA documentation on how to do this)
    3. otherwise simply provide the correct provider using the Signature class, I would recommend specifying "SunRsaSign" (you may want to make this string configurable)
    4. explain to the company behind com.mse that they should implement delayed provider selection correctly and not gobble up software public keys for use in their hardware device

    Note that talking about "server side" is very confusing as the smart card acts as a server. "Terminal side" and "card side" would be a much more clear.

    这篇关于Java Signature.verify结果SignatureException:签名编码错误导致IOException:序列标记错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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