2011-03-02 90 views
0

我有一个PKCS7证券文件的大和奇怪的问题。 我创建了一个p7s文件,如http://www.thatsjava.com/java-tech/85019/中建议的那样,它创建该文件并仅使用sun库对其进行验证。它工作正常。
当我想验证这个文件时,问题就开始了。它返回此异常:pkcs7文件验证问题

java.security.SignatureException: Signature encoding error 
     at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:185) 
     at java.security.Signature$Delegate.engineVerify(Signature.java:1140) 
     at java.security.Signature.verify(Signature.java:592) 
     at sun.security.pkcs.SignerInfo.verify(SignerInfo.java:374) 
     at sun.security.pkcs.PKCS7.verify(PKCS7.java:494) 
     at sun.security.pkcs.PKCS7.verify(PKCS7.java:511) 
     at sun.security.pkcs.PKCS7.verify(PKCS7.java:533) 
     at firma.FirmaDigitalImpl.firmarCadenaSun(FirmaDigitalImpl.java:553) 
     at firma.FirmaDigitalImpl.firmarCadena(FirmaDigitalImpl.java:249) 
     at firma.FirmaDigitalImpl.firmarCadena(FirmaDigitalImpl.java:147) 
     at firma.TestFirma.main(TestFirma.java:75) 
Caused by: java.io.IOException: Sequence tag error 
     at sun.security.util.DerInputStream.getSequence(DerInputStream.java:280) 
     at sun.security.rsa.RSASignature.decodeSignature(RSASignature.java:209) 
     at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:174) 
     ... 10 more 

但是这些问题并不总是出现,只是用一种用于签名的证书。我会解释得更好。 我有两个证书(存储到智能卡),第一个正常工作;我创建了p7s,然后验证正确,但第二个证书允许我创建p7s文件,但是当我验证它时,它会返回SignatureException。我认为p7s文件是错误的,但是我用别人的应用程序对它进行了测试,看起来是正确的。此外,这个文件被发送抛出web服务,它返回,它没事!

有关更多信息,如果使用不同工具(.net和capicom)和相同证书创建p7s文件,则可以正确验证。

我已经寻找解决方案,但没有。在类似的情况下,我发现了相同的例外情况,但是提出的解决方案对我来说都不起作用,或者它没有出现。

任何建议找到解决方案将非常感激。

回答

1

它可能是编码问题:文本与二进制。 PKCS7可以采用DER编码的二进制格式,也可以采用PEM格式(base64编码的DER)。在文本编辑器(例如记事本)中打开文件并查看是否工作的是二进制文本或文本。

+0

我试用这两种格式,结果是一样的。如果问题存在,则不会根据已使用的证书进行更改。 Thaks为您的意见 – Marcos 2011-03-03 17:53:13

1

两个多星期后,我已经注意到了什么问题,虽然我没有找到完整的解决方案。

首先,我提取的问题出PKCS7文件,我再现用下面的源代码中的异常:

import diz.firma.keyStore.SmartCard; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.KeyStore; 
import java.security.PrivateKey; 
import java.security.Provider; 
import java.security.PublicKey; 
import java.security.SecureRandom; 
import java.security.Security; 
import java.security.Signature; 

public class TestFirma3 { 
public static void main(String args[]) throws Exception { 
    //Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    SmartCard sm = new SmartCard(); 
    KeyStore ks = sm.loadKeyStore("1234"); 
    //KeyPair keyPair = generateKeyPair(999); 


    byte[] data = "original".getBytes("UTF-8"); 
    //byte[] data = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 }; 
    //byte[] digitalSignature = signData(data, keyPair.getPrivate()); 
    byte[] digitalSignature = signData(data, 
      (PrivateKey)ks.getKey(sm.getAlias(), null),ks.getProvider()); 

    boolean verified; 

    //verified = verifySig(data, keyPair.getPublic(), digitalSignature); 
    verified = verifySig(data, ks.getCertificate(sm.getAlias()). 
      getPublicKey(),ks.getProvider(), digitalSignature); 
    System.out.println("verified:" + verified) ; 

    //keyPair = generateKeyPair(888); 
    //verified = verifySig(data, keyPair.getPublic(), digitalSignature); 
    //System.out.println(verified); 

    } 

    public static byte[] signData(byte[] data, PrivateKey key,Provider p) throws Exception { 
    Signature signer = Signature.getInstance("SHA1withRSA",p); 
    //Signature signer = Signature.getInstance("SHA1withRSA",Security.getProviders()[10]); 

    signer.initSign(key); 
    signer.update(data); 
    return (signer.sign()); 
    } 

    public static boolean verifySig(byte[] data, PublicKey key, Provider p, byte[] sig) throws Exception { 
    Signature signer = Signature.getInstance("SHA1withRSA",p); 
    //Signature signer = Signature.getInstance("SHA1withRSA"); 
    signer.initVerify(key); 
    signer.update(data); 

    boolean valido = false; 
    try{ 
     valido = signer.verify(sig); 
    }catch(Exception e){ 
     e.printStackTrace(); 
     valido = false; 
    } 
    return valido; 

    } 

    public static KeyPair generateKeyPair(long seed) throws Exception { 
    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("DSA"); 
    SecureRandom rng = SecureRandom.getInstance("SHA1PRNG", "SUN"); 
    rng.setSeed(seed); 
    keyGenerator.initialize(1024, rng); 

    return (keyGenerator.generateKeyPair()); 
    } 
} 

在该代码中,(从一个例子在网中提取),我改发电机钥匙,并从我的卡中拿走。我再次遇到异常,而不使用PKCS7文件。看看所有提供者(使用Security.getProviders(),你可以得到所有的提供者;它们在java.security文件中定义,但它可以被添加到运行时或从运行时获取),并且我使用每个人都签名并且验证,我发现:

  1. 如果在实例化签名时没有选择任何一个提供者,则默认使用SunRsaSign。
  2. 我的签名经过两家提供商验证:
    a)SunMSCAPI提供商使用Microsoft Crypt API。
    b)由智能卡读卡器创建的供应商,在我的情况西门子。
  3. 读取另一张不属于西门子的智能卡,它将通过SunRsaSign和SunJSSE进行验证。

在这一刻,我发现问题和使用SunMSCAPI进行验证的工作,但我必须验证到IBM机器。西门子软件提供了一个安装到Unix的选项,但我无法使其运行。并且使用SunMSCAPI,我认为它不适用于IBM。

因此,我必须找到一个在IMB中正确验证SunRsaSign返回SignatureException的签名的提供者。