使用HSM服务的PDFBox数字签名

时间:2017-10-03 21:39:35

标签: java digital-signature pdfbox

我想使用pdfbox使用hsm服务插入数字签名。

我在这里使用示例作为起点https://github.com/apache/pdfbox/tree/2.0.7/examples/src/main/java/org/apache/pdfbox/examples/signature。这些例子假设我拥有私钥和密码。

在我的情况下,我将生成pdf的相应位的散列并将它们传递给服务以进行签名。在这个帖子的作者的一些指导下:PDF Signing, generated PDF Document certification is invalid? (using external signing, web-eid, HSM)我拼凑了以下对CreateSignatureBase.sign的更改,以便附上证书:

    @Override
public byte[] sign(InputStream content) throws IOException
{
    try
    {
        List<Certificate> certList = new ArrayList<Certificate>();
        certList.addAll(Arrays.asList(certificateChain));
        certList.add(certificate);
        Store certs = new JcaCertStore(certList);
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();

        byte[] sh = MessageDigest.getInstance("SHA-256").digest(IOUtils.toByteArray(content));

        String hexencodedDigest = new BigInteger(1, sh).toString(16);
        hexencodedDigest = hexencodedDigest.toUpperCase();
        // Send digest to signing service
        final String signedHash = certProvider.signPdfDigest(hexencodedDigest);

        ContentSigner nonSigner = new ContentSigner() {

            @Override
            public byte[] getSignature() {
                try {
                    return Hex.decodeHex(signedHash.toCharArray());
                } catch (DecoderException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            public OutputStream getOutputStream() {
                return new ByteArrayOutputStream();
            }

            @Override
            public AlgorithmIdentifier getAlgorithmIdentifier() {
                return new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSAEncryption");
            }
        };

        org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate.getInstance(certificateChain[0].getEncoded());
        JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build());

        //ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA256WithRSA").build(privateKey);
        gen.addSignerInfoGenerator(sigb.build(nonSigner, new X509CertificateHolder(cert)));
        gen.addCertificates(certs);
        CMSTypedDataInputStream msg = new CMSTypedDataInputStream(new ByteArrayInputStream("useless_data".getBytes())); // this is never used.

        //CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
        CMSSignedData signedData = gen.generate(msg, false);
        if (tsaClient != null)
        {
            signedData = signTimeStamps(signedData);
        }

        byte[] pkcs7 = signedData.getEncoded();

        content.close();

        return pkcs7;
    }
    catch (GeneralSecurityException | CMSException | TSPException | OperatorCreationException e)
    {
        throw new IOException(e);
    } catch (SessionExpiredException | TokenExpiredException | CertProviderException e) {
        throw new IOException(e);
    }
}

文档出现更改或损坏,Show签名返回以下错误:

  

org.bouncycastle.cms.CMSSignerDigestMismatchException:message-digest   属性值与计算值不匹配。

0 个答案:

没有答案