CAdES数字签名 [英] CAdES Digital Signature

查看:133
本文介绍了CAdES数字签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试使用葡萄牙语公民卡实现PDF文件的数字签名(CAdES),但是我一直在努力寻找完美的解决方案.目前,我有两套代码.

I've been trying to implement digital signing (CAdES) for PDF files using Portuguese Citizen Card, however I'm having a hard time figuring out the perfectly working solution. Currently I have two sets of code.

第一个:

public void signCAdES(...)
{
        String pkcs11Config = "name=GemPC" + "\n" + "library=C:\\WINDOWS\\SysWOW64\\pteidpkcs11.dll";
        ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11Config.getBytes());
        Provider pkcs11Provider = new sun.security.pkcs11.SunPKCS11(configStream);

                    //provider_name: SunPKCS11-GemPC
        Security.addProvider(pkcs11Provider);

        javax.security.auth.callback.CallbackHandler cmdLineHdlr = new DialogCallbackHandler();

        KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11Provider,
                new KeyStore.CallbackHandlerProtection(cmdLineHdlr));
        KeyStore ks= builder.getKeyStore();

        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);

        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', new File(tempPath), true);
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();

        appearance.setReason(reason);
        appearance.setLocation(location);
        appearance.setCertificationLevel(level);

        String alias = "CITIZEN SIGNATURE CERTIFICATE";

                    //certificates from electronic card and resources folder
        Certificate[] certs = getSignatureCertificatesChain(ks);

        PrivateKey pk = (PrivateKey) ks.getKey(alias, null);

        ExternalSignature es = new PrivateKeySignature(pk, "SHA-1", pkcs11Provider.getName());
        ExternalDigest digest = new BouncyCastleDigest();

        MakeSignature.signDetached(appearance, digest, es, certs, null, null, null, 0, MakeSignature.CryptoStandard.CADES);
}

第一个有效,但是我提供了一个验证器,可以验证PDF的签名是否满足标准,并且似乎缺少其中一个属性(以证书发行者的序列号开头).

The first one works, however I have a validator given to me that verifies if the signatures of a PDF satisfies the standards, and it seems that one of the attributes is missing (sigining certificate issuer's serial number).

第二个是不同的,我必须手动添加属性,但是生成的PDF已损坏(然后,我可能还需要添加颁发者序列属性):

The second one is different, and I have to add the attributes manually, however the generated PDF is corrupted (and then I might need to add the issuer serial attribute too):

private static void signCAdES(byte[] aDocument, PrivateKey aPrivateKey, Certificate[] certChain, String outputPath) {
    try {

        Security.addProvider(new BouncyCastleProvider());
        ArrayList<X509Certificate> certsin = new ArrayList<X509Certificate>();
        for (Certificate certChain1 : certChain) {
            certsin.add((X509Certificate) certChain1);
        }

        X509Certificate signingCertificate= certsin.get(0);

        MessageDigest dig = MessageDigest.getInstance("SHA-1");
        byte[] certHash = dig.digest(signingCertificate.getEncoded());

        ESSCertID essCertid = new ESSCertID(certHash);
        DERSet set = new DERSet(new SigningCertificate(essCertid));

        Attribute certHAttribute = new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificate, set);
        AttributeTable at = getAttributeTableWithSigningCertificateAttribute(certHAttribute);
        CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator(at);

        SignerInfoGeneratorBuilder genBuild = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
        genBuild.setSignedAttributeGenerator(attrGen);

        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        ContentSigner shaSigner = new JcaContentSignerBuilder("SHA1withRSA").build(aPrivateKey);
        SignerInfoGenerator sifGen = genBuild.build(shaSigner, new X509CertificateHolder(signingCertificate.getEncoded()));
        gen.addSignerInfoGenerator(sifGen);
        JcaCertStore jcaCertStore = new JcaCertStore(certsin);
        gen.addCertificates(jcaCertStore);

        CMSTypedData msg = new CMSProcessableByteArray(aDocument);
        CMSSignedData sigData = gen.generate(msg, false); // false=detached

        byte[] encoded = sigData.getEncoded();

        ASN1InputStream in = new ASN1InputStream(encoded);
        CMSSignedData sigData2 = new CMSSignedData(new CMSProcessableByteArray(aDocument), in);
        byte[] encoded2 = sigData2.getEncoded();

        FileOutputStream fos = new FileOutputStream(outputPath);
        fos.write(encoded2);
//      fos.write(encoded);
        fos.flush();
        fos.close();
    } catch (CMSException | IOException | OperatorCreationException | CertificateEncodingException ex) {
        log("signCAdES", "Error: " + ex.toString());
    }
}

有没有人了解使用Java的CAdES数字签名?任何帮助将不胜感激!

Is there anyone who understands CAdES digital signature using Java? Any help would be appreciated!

推荐答案

'issuer-serial'属性不存在或不匹配!

The 'issuer-serial' attribute is absent or does not match!

这意味着您的cades签名未签名属性:签名证书的签名参考或该参考已被篡改.

It means that your cades signature has not signed attribute: the signed reference to the signing certificate or that this reference is tampered.

请检查:ETSI TS 101 733 V2.2.1(2013-04)了解更多信息:

Please check: ETSI TS 101 733 V2.2.1 (2013-04) for more information:

5.7.3签名证书参考属性

5.7.3 Signing Certificate Reference Attributes

使用以下任一命令均可支持签名证书参考属性 ESS签名证书属性或ESS签名证书v2属性...

The Signing certificate reference attributes are supported by using either the ESS signing-certificate attribute or the ESS-signing-certificate-v2 attribute...

这篇关于CAdES数字签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆