【问题标题】:Problems with pkcs7 file validationpkcs7文件验证问题
【发布时间】:2011-03-02 12:02:11
【问题描述】:

我对 PKCS7 证券文件有一个大而奇怪的问题。 我创建了一个 p7s 文件,就像http://www.thatsjava.com/java-tech/85019/ 中建议的那样,它创建了文件并仅使用 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文件有问题,但我用别人的应用程序测试过,它看起来是正确的。此外,这个文件发送 throws webservice 并返回它是好的!

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

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

我们将不胜感激任何找到解决方案的建议。

【问题讨论】:

    标签: java security validation x509certificate pkcs#7


    【解决方案1】:

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

    【讨论】:

    • 两种格式都试了,结果是一样的。如果是问题所在,则不会根据已使用的证书而改变。谢谢你的意见
    【解决方案2】:

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

    首先,我将问题从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. 如果在实例化 Signature 时未选择任何提供者,则默认使用 SunRsaSign。
    2. 我的签名已通过 2 个提供商验证:
      a) 使用 SunMSCAPI 提供程序,它使用 Microsoft Crypt API。
      b) 使用智能卡读卡器创建的提供商,在我的例子中是西门子。
    3. 读取另一张不属于 Siemens 的智能卡,并通过 SunRsaSign 和 SunJSSE 进行验证。

    此时,我发现了问题并使用 SunMSCAPI 进行验证,但我必须在 IBM 机器上进行验证。西门子软件提供了一个安装到 Unix 中的选项,但我无法让它工作。并且使用 SunMSCAPI,我想它不适用于 IBM。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-16
      • 1970-01-01
      • 2015-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多