在 Java 中使用带有 iText 的 X.509 智能卡证书对 PDF 进行签名



我有一个智能卡(政府 eID),我可以在插入引脚后从中提取签名(不可否认性)证书,使用智能卡特定的 API 和驱动程序,它可以为卡持有的每个证书返回一个字节 []。经过研究,我发现这是一个 X.509 证书,在 Java 中,您可以使用以下代码从中获取对象:

InputStream in = new ByteArrayInputStream(certByteArray);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);

我的问题:

  • 是否可以使用 X.509 证书对文档进行签名?我已经阅读并实验了很多关于这个主题的内容(我有一个程序,使用 PKCS#12 使用 iText 操作和签名 PDF),但我看到的关于 X.509 的唯一参考资料是关于加密的,即使在 Bruno Lowagie 的白皮书中也是如此。
  • 如果是这样,如何使用BouncyCastle加密提供商来完成?

我认为如果您尝试使用位于 www.poreid.org 上的名为poreid并在带有工件poreid的maven中央存储库上可用的java组件,您可能会在使用葡萄牙语eID(Cartão de Cidadão)进行身份验证/签名的问题上不那么挣扎

基于 itext 网站上提供的示例的示例

public void createPdf(String filename) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter.getInstance(document, new FileOutputStream(filename));
    document.open();
    document.add(new Paragraph("Assinado com o Cartão de Cidadão!"));
    document.close();
}
public void signPdf(String src, String dest)
    throws IOException, DocumentException, GeneralSecurityException {
    KeyStore ks = KeyStore.getInstance(POReIDConfig.POREID);
    ks.load(null);
    PrivateKey pk = (PrivateKey) ks.getKey(POReIDConfig.AUTENTICACAO, null);
    Certificate[] chain = ks.getCertificateChain(POReIDConfig.AUTENTICACAO);
    // reader and stamper
    PdfReader reader = new PdfReader(src);
    FileOutputStream os = new FileOutputStream(dest);
    PdfStamper stamper = PdfStamper.createSignature(reader, os, '');
    // appearance
    PdfSignatureAppearance appearance = stamper .getSignatureAppearance();
    appearance.setReason("qualquer motivo");
    appearance.setLocation("qualquer localização");
    appearance.setVisibleSignature(new Rectangle(72, 732, 144, 780), 1, "primeira assinatura");
    // digital signature
    ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", POReIDConfig.POREID);
    ExternalDigest digest = new ProviderDigest(null); // find provider
    MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
}

public static void main(String[] args) throws DocumentException, IOException, GeneralSecurityException {
    Security.addProvider(new POReIDProvider());
    App exemplo = new App();
    exemplo.createPdf("/home/quim/exemplo.pdf");
    exemplo.signPdf("/home/quim/exemplo.pdf","/home/quim/exemplo.assinado.pdf");
}

对于任何努力使用葡萄牙语 eID(名为 Cartão Cidadão)进行身份验证/签名的人来说,提供的带有中间件的 java lib 仅实现公共方法来获取用于验证的证书,这让我感到困惑,因为我期望可以访问所有内容。

要解决此问题,您可以使用 pteidpkcs11.dll本机方法,该方法与中间件(Windows 系统中的 System32 文件夹)一起安装。我仍在尝试创建一个可以完成此操作的代码示例,但这是我目前的线索:

  • 使用 pteid4j 库。请记住,有关 pdf 签名的 iText 代码示例是旧的,在最新版本中不存在
  • 实现主题"使用 PKCS#11 对文档进行签名"中的代码,itextpdf.com/book/digitalsignatures

最新更新