Java pkcs7文件验证的问题

Java pkcs7文件验证的问题,java,security,validation,x509certificate,pkcs#7,Java,Security,Validation,X509certificate,Pkcs#7,我对PKCS7证券文件有一个大而奇怪的问题。 我创建了一个p7s文件,就像在创建文件的地方建议的那样,并仅使用sun库对其进行验证。它很好用。 当我想要验证此文件时,问题开始出现。它返回此异常: java.security.SignatureException:签名编码错误 位于sun.security.rsa.RSASignature.engineVerify(RSASignature.java:185) 位于java.security.Signature$Delegate.engineVer

我对PKCS7证券文件有一个大而奇怪的问题。 我创建了一个p7s文件,就像在创建文件的地方建议的那样,并仅使用sun库对其进行验证。它很好用。
当我想要验证此文件时,问题开始出现。它返回此异常:

java.security.SignatureException:签名编码错误
位于sun.security.rsa.RSASignature.engineVerify(RSASignature.java:185)
位于java.security.Signature$Delegate.engineVerify(Signature.java:1140)
位于java.security.Signature.verify(Signature.java:592)
位于sun.security.pkcs.SignerInfo.verify(SignerInfo.java:374)
位于sun.security.pkcs.PKCS7.verify(PKCS7.java:494)
位于sun.security.pkcs.PKCS7.verify(PKCS7.java:511)
位于sun.security.pkcs.PKCS7.verify(PKCS7.java:533)
位于firma.firmadigitalipl.firmacadenasun(firmadigitalipl.java:553)
在firma.firmadigitalipl.firmaCardena(firmadigitalipl.java:249)
在firma.firmadigitalipl.firmaCardena(firmadigitalipl.java:147)
位于firma.TestFirma.main(TestFirma.java:75)
原因:java.io.IOException:序列标记错误
位于sun.security.util.DerInputStream.getSequence(DerInputStream.java:280)
位于sun.security.rsa.RSASignature.decodeSignature(RSASignature.java:209)
位于sun.security.rsa.RSASignature.engineVerify(RSASignature.java:174)
... 10多
但问题并不总是出现,只是在使用某种类型的证书进行签名时才会出现。我会解释得更好。 我有两个证书(存储在智能卡中),第一个可以正常工作;我创建了p7s,然后正确验证,但是第二个证书允许我创建p7s文件,但是当我验证它时,它返回SignatureException。我认为p7s文件是错误的,但我用其他人的应用程序测试了它,它看起来是正确的。此外,此文件通过webservice发送,并返回ok

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

我一直在寻找解决办法,但一无所获。我在类似的情况下也发现了同样的异常,但要么建议的解决方案对我不起作用,要么就不出现


如果您能提供任何解决方案,我们将不胜感激。

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

两周多后,我注意到了问题所在,尽管我没有找到完整的解决方案

首先,我从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());
  }
}
在这段代码中(摘自网络中的一个示例),我更改了generators密钥并从我的卡中取出它。我再次遇到异常,没有使用PKCS7文件

查看所有提供程序(使用Security.getProviders()可以获取所有提供程序;它们在java.Security文件中定义,但可以在运行时添加或从中获取),我使用每个人进行签名和验证,我发现:

  • 如果在实例化签名时未选择任何一个提供程序,则默认情况下使用SunRsaSign
  • 我的签名由两个提供商验证:
    a) 使用SunMSCAPI提供程序,该提供程序使用Microsoft Crypt API。
    b) 由智能卡读卡器创建的供应商,在我的案例中是西门子
  • 读取另一个不属于西门子的智能卡时,会使用SunRsaSign和SunJSSE进行验证
  • 此时,我发现了问题,并找到了使用SunMSCAPI进行验证的解决方法,但我必须在IBM机器上进行验证。西门子软件提供了安装到Unix的选项,但我无法让它工作。使用SunMSCAPI,我想它不适用于IBM


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

    我尝试了这两种格式,结果是相同的。如果是问题所在,则不会根据已使用的证书而更改。谢谢你的意见