iText7使用IExternalSignatureContainer进行签名和验签

写在前面

一般情况下我们都是使用iText7自带的

pdfsigner.detach()
复制代码

方法对pdf文件进行签名,iText7已经自己封装好了PKC7,所以这里还是挺方便的。但如果因为某种需求需要我们自己来进行P7签名,那么我们就可以使用

pdfsigner.signExternalContainer()
复制代码

来自己实现对pdf的签名,即itext7只要提供要签名的数据给我们就行了。

签名和验签大致流程

我们可以看下这幅图,来自《Acrobat_DigitalSignatures_in_PDF》

大致的意思就是说

  1. 要签名的时候会把文档转换成字节流叫ByteRange
  2. ByteRange有四个数字,分成三部分(以图为例),我们要用来签名的数据就在0- 840和960-1200这部分,然后签名就存放在840~960里面。
  3. 因此我们验签的时候获取签名值就来自于840~960也就是Contents里。
  4. 要验签的原文就是ByteRange里除去签名值的部分。

IExternalSignatureContainer介绍

我们先看下IExternalSignatureContainer这个接口:

/**
 * Interface to sign a document. The signing is fully done externally, including the container composition.
 * 这是一个用来签署文件的接口,它让所有的签名都完全来自于外部扩展实现。
 * @author Paulo Soares
 */
public interface IExternalSignatureContainer {

    /**
     * Produces the container with the signature.
     * @param data the data to sign
     * @return a container with the signature and other objects, like CRL and OCSP. The container will generally be a PKCS7 one.
     * @throws GeneralSecurityException
     */
    byte[] sign(InputStream data) throws GeneralSecurityException;

    /**
     * Modifies the signature dictionary to suit the container. At least the keys {
    @link PdfName#Filter} and
     * {
    @link PdfName#SubFilter} will have to be set.
     * @param signDic the signature dictionary
     */
    void modifySigningDictionary(PdfDictionary signDic);
}
复制代码

signExternalContainer()方法介绍

接下来我们看下需要用到IExternalSignatureContainer 的方法 signExternalContainer() 的介绍:

    /**
     * Sign the document using an external container, usually a PKCS7. The signature is fully composed
     * externally, iText will just put the container inside the document.
     * <br><br>
     * NOTE: This method closes the underlying pdf document. This means, that current instance
     * of PdfSigner cannot be used after this method call.
     *
     * @param externalSignatureContainer the interface providing the actual signing
     * @param estimatedSize              the reserved size for the signature
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public void signExternalContainer(IExternalSignatureContainer externalSignatureContainer, int estimatedSize) throws GeneralSecurityException, IOException {
        //省略部分源码
        
        //关注这里,调用getRangeStream()方法获取到要签名的数据
        //传入到externalSignatureContainer.sign()方法里给我们签
        InputStream data = getRangeStream();
        byte[] encodedSig = externalSignatureContainer.sign(data);
        
        //省略部分源码


    /**
     * Gets the document bytes that are hashable when using external signatures. 在使用外部签名的时候会返回可用于哈希的文件字节。
     * The general sequence is:
     * {
    @link #preClose(Map)}, {
    @link #getRangeStream()} and {
    @link #close(PdfDictionary)}.
     *
     * @return The {
    @link InputStream} of bytes to be signed.
     * 返回用于签名的字节
     */
    protected InputStream getRangeStream() throws IOException {
        RandomAccessSourceFactory fac = new RandomAccessSourceFactory();
        return new RASInputStream(fac.createRanged(getUnderlyingSource(), range));
    }
复制代码

可以看到这个方法需要两个参数IExternalSignatureContainer(扩展签名容器) 和 estimatedSize(预估值)。

开始重写IExternalSignatureContainer

那么我们先重写IExternalSignatureContainer:

注:以下使用到的哈希方法,签名方法是做一个说明,

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值