Verify digital signature using certificate chain i

2020-08-01 15:58发布

问题:

i try to sign pdf using digital signature, i send hash value of pdf to REST API it does sign pdf using user's private key and returns CMS formatted data. I got certificate chain from CMS. Now i need to verify original pdf using the certificate chain and add signature to pdf. I use BC and Itextpdf

public static String verifyPdf(byte[] toVerify, byte[] signedByte, String origFile, String signedFile) throws Exception {

//        CMSSignedData cms = new CMSSignedData(signedByte);
//        Store store = cms.getCertificates();
//        System.out.println("Store:" + store);

        String result = "";
        X509Certificate certificate = null;
        SignedData signedData = bytesToPkcs7SignedData(signedByte);
        Certificate[] certs = new Certificate[1];

        X509CertificateChain chain = new X509CertificateChain();
        chain.addAll(readCerts(signedData));
        certificate = chain.get(0);
//        System.out.println("Certificate: " + certificate);
        certs[0] = chain.get(0);
        System.out.println("Signature:" + certificate);
//        for (X509Certificate x5 : chain) {
//            System.out.println(x5);
//        }


        if(certificate != null){
            PublicKey pk = certificate.getPublicKey();
            OcspClient ocspClient = new OcspClientBouncyCastle();
            TSAClient tsaClient = null;
            for (X509Certificate x5 : chain) {
                String tsaUrl = CertificateUtil.getTSAURL(x5);
                if (tsaUrl != null) {
                    tsaClient = new TSAClientBouncyCastle(tsaUrl);
                    break;
                }
            }
            List<CrlClient> crlList = new ArrayList<CrlClient>();
            crlList.add(new CrlClientOnline(certs));
            sign(origFile,signedFile, certs, pk, DigestAlgorithms.SHA256, null,
                    MakeSignature.CryptoStandard.CMS, "User Signature", "", crlList, ocspClient, tsaClient, 0);
        }
        return result;
    }

I think this signature field is user's signature with subject with user's name etc that inside certificate chain

This is sign function(I checked it using Keypairs, signed pdf and added to pdf it works. But this case i dont have private key so dont know how to add signature to pdf):

 public static void sign(String src,
                            String dest,
                            Certificate[] chain,
                            PublicKey pk,
                            String digestAlgorithm,
                            String provider,
                            MakeSignature.CryptoStandard subfilter,
                            String reason,
                            String location,
                            Collection<CrlClient> crlList,
                            OcspClient ocspClient,
                            TSAClient tsaClient,
                            int estimatedSize)
            throws GeneralSecurityException, IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        com.itextpdf.kernel.pdf.PdfReader pdfReader = new com.itextpdf.kernel.pdf.PdfReader(src);

        FileOutputStream os = new FileOutputStream(dest);
        OutputStream out = new FileOutputStream(dest);

        AcroFields acroFields = reader.getAcroFields();
        PdfSigner signer = new PdfSigner(pdfReader, out, new StampingProperties().useAppendMode());

        List<String> names = acroFields.getSignatureNames();
        for (String name : names) {
            System.out.println("Signature name: " + name);
            System.out.println("Signature covers whole document: " + acroFields.signatureCoversWholeDocument(name));
            System.out.println("Document revision: " + acroFields.getRevision(name) + " of " + acroFields.getTotalRevisions());
            PdfPKCS7 pkcs = acroFields.verifySignature(name);
            System.out.println("Subject: " + CertificateInfo.getSubjectFields(pkcs.getSigningCertificate()));
            System.out.println("Document verifies: " + pkcs.verify());
        }

        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setReason(reason);
        appearance.setLocation(location);
        appearance.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, "sig");
        appearance.setCertificate(chain[0]);

//        ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
        ExternalDigest digest = new BouncyCastleDigest();
//        MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);

        ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
        MakeSignature.signExternalContainer(appearance, external, 8192);

    }

i tested the sign function using keypairs and i could add signature. pdf looks like this picture:

In my failed case i got this: