当前位置: 首页 > 知识库问答 >
问题:

带有多个签名的iText7 PDF

蒯嘉赐
2023-03-14

我正在将代码从iText5迁移到iText7,目前我正在努力将一个签名添加到已经包含另一个签名的PDF中。这些签名是用我们的国民身份证(公民卡)进行的。

在iText5中,我使用了PdfStamper,但它在Itext7中丢失了...

这是我目前所掌握的:

package cartaocidadao;

import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import javax.swing.JOptionPane;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.poreid.config.POReIDConfig;
import org.poreid.crypto.POReIDProvider;
import com.itextpdf.signatures.OcspClientBouncyCastle;
import com.itextpdf.signatures.TSAClientBouncyCastle;
import java.io.IOException;
import java.util.Collection;

import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.OCSPVerifier;
import java.security.GeneralSecurityException;
import static javax.swing.JOptionPane.ERROR_MESSAGE;

/**
 *
 * @author i.lourenco
 */
public class Signature {

    /**
     *  Signs the PDF with the Citizen Card Certificate
     * @param src Source file
     * @param dest Destination file
     * @return TRUE if the PDF was signed successfully
     */
    protected static boolean signPDF(String src, String dest) {

        try {

            Security.addProvider(new POReIDProvider());

            BouncyCastleProvider provider = new BouncyCastleProvider();
            Security.addProvider(provider);

            KeyStore ks = KeyStore.getInstance(POReIDConfig.POREID);
            ks.load(null);

            PrivateKey pk = (PrivateKey) ks.getKey(POReIDConfig.ASSINATURA, null);

            Certificate[] chain = ks.getCertificateChain(POReIDConfig.ASSINATURA);

            OCSPVerifier ocspVerifier = new OCSPVerifier(null, null);

            IOcspClient ocspClient = new OcspClientBouncyCastle(ocspVerifier);

            ITSAClient tsaClient = new TSAClientBouncyCastle("http://ts.cartaodecidadao.pt/tsa/server", "", "");

            sign(src, dest, chain, pk, DigestAlgorithms.SHA256, POReIDConfig.POREID, PdfSigner.CryptoStandard.CMS, "", "", null, ocspClient, tsaClient, 0);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), "Erro", ERROR_MESSAGE);
        }

        return true;
    }

    /**
     * Applies the certificate, timestamp and revocation list to a PDF
     * @param src Original PDF document
     * @param dest Signed PDF document
     * @param chain List of certificates
     * @param pk Private key
     * @param digestAlgorithm Encryption algorithm
     * @param provider Citizen Card provider
     * @param subfilter CMS
     * @param reason Reason for signature
     * @param location Location
     * @param crlList Revocation list
     * @param ocspClient Online Certification Status
     * @param tsaClient Timestamp server
     * @param estimatedSize
     * @throws IOException
     * @throws GeneralSecurityException 
     */
    private static void sign(String src, String dest, Certificate[] chain, PrivateKey pk, String digestAlgorithm, 
            String provider, PdfSigner.CryptoStandard subfilter, String reason, String location, Collection<ICrlClient> crlList, 
            IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize) throws IOException, GeneralSecurityException {

        PdfReader reader = new PdfReader(src);

        PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), false);

        PdfSignatureAppearance appearance = signer.getSignatureAppearance()
                .setReason(reason)
                .setLocation(location)
                .setReuseAppearance(false);
        Rectangle rect = new Rectangle(36, 648, 200, 100);
        appearance.setPageRect(rect).setPageNumber(1);

        signer.getNewSigFieldName();

        IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
        IExternalDigest digest = new BouncyCastleDigest();

        signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
    }


}

POReID(https://github.com/POReID/POReID)是用于与智能卡交互的库。

当第一次签署文件时,它工作得很好。再次对文档签名时,它使第一个签名无效,只有最后一个签名有效。

两个签名

共有1个答案

濮阳
2023-03-14
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), false);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), true);

构造函数中的第三个参数确定是否在追加模式下使用签名者。

 类似资料:
  • 我在RestController中对一个实体使用QuerydslPredicate,它有一个date对象,我希望能够查询给定日期之前/之后/之间的日期,希望有类似的东西 null

  • 我对iTextSharp有意见。我有一个带有表单字段的文档,并且我已经为签名生成了字段。当第一个人在文件上签字时,它就会正常工作。Adobe Reader显示有效签名。当我让第二个人在文档上签名时,Adobe Reader显示签名1现在是“未知签名”,签名无效。Adobe reader显示: 此签名中包含的格式或信息有错误(支持信息:SigDict/Contents非法数据)

  • PDF下载示例:https://drive.google.com/file/d/12wv1Pb7gh4vCKOGhX4cZ3aOrLSiOo4If/view?usp=sharing 因此,当PDF在A.Reader(连续版本)中打开时,它表示证书无效,因为对该文档所做的更改导致签名无效。 但我看不出有什么变化。我们自己的应用程序只添加了一个签名(证书),为数千个其他PDF添加了正确的签名。未执行其

  • 问题内容: 我正在尝试使用自签名服务器证书建立TLS连接。 我使用以下示例代码生成了证书:http : //golang.org/src/pkg/crypto/tls/generate_cert.go 我相关的客户端代码如下所示: 以及类似的服务器代码: 因为服务器证书是自签名的,所以对于服务器和客户端CA_Pool使用相同的证书,但这似乎不起作用,因为我总是会收到此错误: 我怎么了 问题答案:

  • 我正在尝试通过签名服务签署一个pdf文件。这个服务需要发送一个十六进制编码的SHA256摘要,作为回报,我会收到一个十六进制编码的SignatureValue。此外,我还收到了签名证书、中间证书、OCSP响应和TimeStampToken。但是,我在尝试使用SignatureValue对pdf进行签名时已经陷入了困境。 我读过布鲁诺的白皮书,过度浏览互联网,尝试了很多不同的方式,但签名不断出现无效

  • 我使用下面的代码在React组件中基于来自props的布尔值动态设置一个class Name: