2

期限切れの公開証明書を使用して Java でデジタル署名 (PKCS#7) を検証すると問題が発生します。詳しくは、.NET でデータに署名してから Java で検証する場合は問題ありませんが、Java でデータに署名して Java で検証する場合、Certificate Expired エラーが発生します。どちらの場合も、同じ検証方法、同じ秘密鍵と公開証明書を使用しました。

どうしてか言ってくれない?また、デジタル署名を検証するときに証明書の期限切れの検証をバイパスしたい場合はどうすればよいですか?

ありがとう、

C#.NET の Sign メソッド

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 の Sign メソッド

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");
}
4

2 に答える 2

1

このトピックC# SignedCms の Java 実装を見つけ、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();
        }

}
于 2012-10-17T02:34:31.797 に答える
1

すでに有効期限が切れている証明書を使用して文書に署名した場合、それはすでに無意味です。証明書は既に有効期限が切れているため、新たに使用しないでください。署名証明書の有効期限が切れているドキュメントを検証することは理にかなっています。少なくとも、ドキュメントが署名されたときに証明書が有効であったことがわかっているからです。どうやら.NETによって署名されていない限り。私には.NETのバグのように思えます。

于 2012-10-16T09:51:04.670 に答える