【问题标题】:How to bypass the Certificate Expired validating when verifying the digital signature验证数字签名时如何绕过证书过期验证
【发布时间】:2012-10-16 08:34:26
【问题描述】:

我在使用过期的公共证书验证 Java 中的数字签名 (PKCS#7) 时遇到问题。 更详细的,在.NET中签名数据然后在Java中验证是可以的,但是在Java中签名数据和在Java中验证会出现Certificate Expired错误/强>。在这两种情况下,我都使用了相同的验证方法、相同的私钥和公共证书。

请告诉我为什么?以及在验证数字签名时如果想绕过Certificate Expired验证怎么办?

谢谢,

C#.NET 中的签名方法

private static string SignData(byte[] data, string pkcs12FileUrl, string pkcs12Password)
    {
        X509Certificate2 signerCert = new X509Certificate2(pkcs12FileUrl, pkcs12Password);
        ContentInfo content = new ContentInfo(data);
        SignedCms signed = new SignedCms(content, true);
        CmsSigner signer = new CmsSigner(signerCert);
        signer.IncludeOption = X509IncludeOption.None;
        signed.ComputeSignature(signer);

        return Convert.ToBase64String(signed.Encode());
    }

Java 中的签名方法

public static String SignData(byte[] data, String pkcs12File, String pkcs12Password)
    throws Exception
{
        if(Security.getProvider("BC")==null)
        {
            Security.addProvider(new BouncyCastleProvider());
        }
        KeyStore keyStore = getPkcs12Info(pkcs12File, pkcs12Password);

        Enumeration<String> aliasesList = keyStore.aliases();
        String aliasName = "";
        while (aliasesList.hasMoreElements())
        {
            aliasName = aliasesList.nextElement().toString();
        }

        X509Certificate signerCert = (X509Certificate) keyStore.getCertificate(aliasName);
        PrivateKey privateKey = (PrivateKey) keyStore.getKey(aliasName,pkcs12Password.toCharArray());

        CMSSignedDataGenerator Signer = new CMSSignedDataGenerator();
        Signer.addSigner(privateKey, signerCert, CMSSignedDataGenerator.DIGEST_SHA1);

        CMSProcessableByteArray digestContent = new CMSProcessableByteArray(data);

        CMSSignedData Signed = Signer.generate(digestContent, false, "BC");
        return Base64.encode(Signed.getEncoded());

}

private static  KeyStore getPkcs12Info(String pkcs12File, String pkcs12Password) throws Exception
{
    //KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new FileInputStream(pkcs12File), pkcs12Password.toCharArray());
        return keyStore;
}

Java 中的验证方法

public static boolean VerifySignature(byte[] data, String digitalSignature, InputStream publicCertFile) throws Exception
{
    if(Security.getProvider("BC")==null)
    {
        Security.addProvider(new BouncyCastleProvider());
    }
    CertificateFactory factory = CertificateFactory.getInstance("X509","BC");
    X509Certificate publicCert = (X509Certificate)factory.generateCertificate(publicCertFile);
    CMSProcessableByteArray digestContent = new CMSProcessableByteArray(data);
    CMSSignedData Signed = new CMSSignedData(digestContent,Base64.decode(digitalSignature));
    SignerInformation Signer=(SignerInformation)Signed.getSignerInfos().getSigners().iterator().next();
    return Signer.verify(publicCert, "BC");
}

【问题讨论】:

  • 您能否提供(链接到)有该问题的示例签名以及所涉及的公共证书?
  • 感谢您考虑我的主题。我的答案已经解决了这个问题。

标签: java .net digital-signature pkcs#7


【解决方案1】:

如果您使用已过期的证书签署文件,那已经毫无意义。证书已过期,不应再用于新用途。验证签名证书已过期的文档是有意义的,因为至少您知道在文档签名时证书是有效的。除非它显然是由 .NET 签名的。对我来说,这听起来像是 .NET 中的一个错误。

【讨论】:

  • 我不确定这是否是 .NET 错误,但我发现此链接 comments.gmane.org/gmane.comp.encryption.bouncy-castle.devel/… 与我的问题有关。但是我仍然不知道如何解决它。
  • @anhtuangv 如果“修复它”是指“使用 Java 和过期证书签署文档”,那么您无法修复它,而您不要'不想 修复它。这是一种不安全的做法。解决方法是更新证书。
  • 是的,最好按照你说的更新证书。但是,就我而言,我不想在证书过期时更新证书。因为我只是使用数字签名来验证 Web 服务之间的请求和响应消息。如果我续订它,我必须将新证书发送给我的所有合作伙伴,我的所有合作伙伴也必须向我发送他们的新证书(如果他们的证书已过期)。此外,如果我忘记这样做,系统会出错。
  • @anhtuangv 这些都不是真的。证书随附签名。您不必自己分发它。带有过期签名的数字签名在法律上是没有意义的。如果您不了解要求和含义和/或您不愿意或无法正确实施它们,您最好停止使用它们。
【解决方案2】:

我找到了这个主题Java implementation of C# SignedCms 并尝试在 Java 中更改我的 Sign 方法的代码。最后,它工作得很好。这是我在 Java 中更新的代码

public static String SignData(byte[] data, String pkcs12File, String pkcs12Password)
    throws Exception
{
        ByteArrayOutputStream byteArrOut = new ByteArrayOutputStream();
        DEROutputStream derOut = new DEROutputStream(byteArrOut);
        try
        {
            if(Security.getProvider("BC")==null)
            {
                Security.addProvider(new BouncyCastleProvider());
            }
            KeyStore keyStore = getPkcs12Info(pkcs12File, pkcs12Password);

            Enumeration<String> aliasesList = keyStore.aliases();
            String aliasName = "";
            while (aliasesList.hasMoreElements())
            {
                aliasName = aliasesList.nextElement().toString();
            }

            X509Certificate signerCert = (X509Certificate) keyStore.getCertificate(aliasName);
            PrivateKey privateKey = (PrivateKey) keyStore.getKey(aliasName, pkcs12Password.toCharArray());

            List certList = new ArrayList();
            Store certs = new JcaCertStore(certList);

            JcaSimpleSignerInfoGeneratorBuilder builder = new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").setDirectSignature(true);


            CMSSignedDataGenerator signer = new CMSSignedDataGenerator();
            signer.addSignerInfoGenerator(builder.build("SHA1withRSA", privateKey, signerCert));
            signer.addCertificates(certs);

            CMSTypedData msg = new CMSProcessableByteArray(data);
            CMSSignedData signed = signer.generate(msg, false);

            derOut.writeObject(signed.toASN1Structure().toASN1Primitive());
            return Base64.encode(byteArrOut.toByteArray());
        }
        catch(Exception ex)
        {
            throw ex;
        }
        finally
        {
            derOut.close();
            byteArrOut.close();
        }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 2014-07-07
    • 2014-03-16
    相关资源
    最近更新 更多