pkcs7文件验证问题

时间:2011-03-02 12:02:12

标签: java security validation x509certificate pkcs#7

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

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文件是错误的,但我测试了其他人的应用程序,它看起来是正确的。此外,这个文件被发送抛出webservice,它返回它是好的!

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

我已经找到了解决方案,但没有。我在类似情况下发现了相同的异常,但是建议的解决方案对我不起作用,或者没有出现。

非常感谢任何寻找解决方案的建议。

2 个答案:

答案 0 :(得分:1)

可能是编码问题:文本与二进制。 PKCS7可以是DER编码的二进制格式或PEM格式(base64编码的DER)。在文本编辑器(例如记事本)中打开文件,看看有效的文件是二进制还是文本。

答案 1 :(得分: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. My Signature已通过2家提供商验证:
    a)使用Microsoft Crypt API的SunMSCAPI提供程序 b)由智能卡读卡器创建的提供商,在我看来是西门子。
  3. 阅读另一款不属于西门子的智能卡,通过SunRsaSign和SunJSSE进行验证。
  4. 此时,我发现问题和使用SunMSCAPI进行验证的工作日,但我必须验证IBM机器。西门子软件提供了一个安装到Unix的选项,但我无法让它工作。使用SunMSCAPI,我认为它不适用于IBM。

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