如何使用pdfbox签名PDF哈希

时间:2018-10-01 09:52:11

标签: android digital-signature pdfbox spongycastle

是否可以使用pdfbox签名PDF文档哈希? 我需要做下面的事情, 我有一个包含PvtKey和证书链的父项,以及一个具有PDF文档的子应用程序。我不想将整个pdf流发送到父应用程序进行签名,而是只将pdf哈希发送到父应用程序(希望父应用程序将返回Signed哈希值)。然后将签名附加到pdf。

我认为使用IText pdf库可以做到这一点。但是我想使用PDFbox。

public static byte[] getCMSFromHash(byte[] hashVal,String strCertificate, String strPrivatekey){

    byte[] cmsSignedData = null;
    final List<Certificate> certificates;
    final PrivateKey privateKey;
    System.out.println("Get CMS from Hash started");
    Security.addProvider(new BouncyCastleProvider());
    try {
        certificates = getFormatCertificate(strCertificate);
        privateKey = loadPrivateKey(strPrivatekey);

        @SuppressWarnings("rawtypes")
        Store certs = new JcaCertStore(certificates);
      //PAdES
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(certificates.get(certificates.size()-1).getEncoded());

        byte[] certHash = md.digest();
        ESSCertIDv2 essCert1 =
                new ESSCertIDv2(new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256), certHash);
        ESSCertIDv2[] essCert1Arr =
                {
                        essCert1
                };
        SigningCertificateV2 scv2 = new SigningCertificateV2(essCert1Arr);
        Attribute certHAttribute =
                new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificateV2, new DERSet(scv2));
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(certHAttribute);

        AttributeTable at = new AttributeTable(v);


        CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator(at){
            @SuppressWarnings("rawtypes")
            protected Hashtable createStandardAttributeTable(Map parameters)
            {
                Hashtable result = super.createStandardAttributeTable(parameters);
                result.remove(CMSAttributes.signingTime);
                return result;
            }
        };
        //PAdES-end

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

        org.spongycastle.asn1.x509.Certificate certas1 = org.spongycastle.asn1.x509.Certificate.getInstance(ASN1Primitive.fromByteArray(certificates.get(certificates.size()-1).getEncoded()));

        ContentSigner sha1Signer = new JcaContentSignerBuilder(signerAlgorithm).build(privateKey);

        SignerInfoGenerator sifGen = genBuild.build(sha1Signer, new X509CertificateHolder(certas1));

        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();

        gen.addCertificates(certs);
        gen.addSignerInfoGenerator(sifGen);

        CMSTypedData cmsdata = new CMSProcessableByteArray(hashVal);
        CMSSignedData signedData = gen.generate(cmsdata, false);
        cmsSignedData = signedData.getEncoded();
    } catch (GeneralSecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (OperatorCreationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (CMSException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    System.out.println("cmsSignedData 1::"+new String(cmsSignedData));
    return cmsSignedData;

}`

and then
`public static String getSignedPdffromCMS(byte[] cmsSignedData,String signatureName, String signatureLocation, String signatureReason){

    Security.addProvider(new BouncyCastleProvider());
    System.out.println("cmsSignedData 2::"+new String(cmsSignedData));
    final byte[] digitalSign = cmsSignedData;
    Map<String, String> pdfMap = new HashMap<String, String>();
    ByteArrayOutputStream pdfContentOutputStream = new ByteArrayOutputStream();

    try {

        PDSignature signature = new PDSignature();

        signature.setType(COSName.SIG);
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
        signature.setSubFilter(PDSignature.SUBFILTER_ETSI_CADES_DETACHED);
        if(!signatureName.isEmpty()){
            signature.setName(signatureName);
        }
        if(!signatureLocation.isEmpty()){
            signature.setLocation(signatureLocation);
        }
        if(!signatureReason.isEmpty()){
            signature.setReason(signatureReason);
        }
        signature.setSignDate(Calendar.getInstance());

        SignatureInterface signatureInterface = new SignatureInterface() {

            @Override
            public byte[] sign(InputStream content) throws IOException {
                return digitalSign;
            }

        };
        PDDocument pdDocument = PDDocument.load(inputfile);
        System.out.println("PDF InputStream loaded::");
        pdDocument.addSignature(signature, signatureInterface);
        pdDocument.saveIncremental(pdfContentOutputStream);
        pdDocument.close();
        savePdfFile(pdfContentOutputStream);

        String StrPdfBase64 = "";
        try {
            StrPdfBase64 = org.spongycastle.util.encoders.Base64.toBase64String(pdfContentOutputStream.toByteArray());
            pdfMap.put("receiptContent", StrPdfBase64);
            System.out.println("Signed base64:::"+StrPdfBase64);
        } catch (Exception e) {
            StrPdfBase64 = "error";
            System.out.println(" >>>>> pdf error occured in base64 conversion:"+e.toString());
        }
        String receiptHash = getReceiptHash(pdfContentOutputStream);
        pdfMap.put("receiptHash", receiptHash);


    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        inputfile.delete();
        JSONObject jsonObj = new JSONObject(pdfMap);
        System.out.println("pdfMap jsonObj:::"+jsonObj.toString());
        return jsonObj.toString();      
    }

}<code>

enter image description here

Created PDF Attached here

0 个答案:

没有答案