使用 eid-commons 和 itext - 以编程方式签署具有有效签名的 pdf
Using eid-commons and itext - programmatically sign a pdf with a valid signature
我在 Whosebug 上看到了一些类似的问题,但遗憾的是我一直无法找到解决方案。我相信我已经很接近了,但只是缺少正确的步骤。
我正在使用我的比利时 EID 卡,上面有我可以用来签署 PDF 的签名证书。
使用的 Maven 库:
be.fedict.commons-eid - 0.6.5
com.itextpdf - 5.5.10
org.bouncycastle - 1.55
代码如下:
BeIDCardManager manager = new BeIDCardManager();
manager.addBeIDCardEventListener(new BeIDCardEventsListener() {
public void eIDCardInserted(CardTerminal arg0, BeIDCard arg1) {
log.info("Inserted");
try {
dostuffwithmycard(arg1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
...
protected static void dostuffwithmycard(BeIDCard card) throws IOException, DocumentException, GeneralSecurityException {
Security.addProvider(new BeIDProvider());
KeyStore keyStore = KeyStore.getInstance("BeID");
keyStore.load(null, null);
PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Authentication", null);
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(authnPrivateKey);
PdfReader reader = new PdfReader("C:\Untitled.pdf");
FileOutputStream os = new FileOutputStream( "C:\temp\Signed.pdf");
PdfStamper stamper = PdfStamper.createSignature(reader, os, '[=12=]');
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason("Okay");
appearance.setLocation("Home");
appearance.setVisibleSignature(new Rectangle(36,748,144,780), 1, "sig");
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature sig = new PrivateKeySignature(authnPrivateKey, "SHA1", "BeIDProvider");
MakeSignature.signDetached(appearance, digest, sig, keyStore.getCertificateChain("Signature"), null, null, null, 0, CryptoStandard.CMS);
}
我基本上是通过反复试验共同构建了这段代码。我已经得到它,所以我可以在 PDF 上实际签名(在通过输入 PIN 解锁我的签名证书后),但是当我打开 PDF 时,它告诉我签名无效。我可以在签名上看到我的名字,但是当我尝试在 Adobe Reader 中验证它时,我收到错误消息 0x2726
一定是我哪里做错了,但是一直找不到确切的原因。
您正在使用 keyStore.getKey("Authentication", null)
获取密钥并使用 keyStore.getCertificateChain("Signature")
获取认证链。看来您的卡有两个证书。那么 Signature
证书的 public 密钥将与 Authentication
证书
的私钥不匹配
尝试用
替换PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Authentication", null);
PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Signature", null);
我在 Whosebug 上看到了一些类似的问题,但遗憾的是我一直无法找到解决方案。我相信我已经很接近了,但只是缺少正确的步骤。
我正在使用我的比利时 EID 卡,上面有我可以用来签署 PDF 的签名证书。
使用的 Maven 库:
be.fedict.commons-eid - 0.6.5
com.itextpdf - 5.5.10
org.bouncycastle - 1.55
代码如下:
BeIDCardManager manager = new BeIDCardManager();
manager.addBeIDCardEventListener(new BeIDCardEventsListener() {
public void eIDCardInserted(CardTerminal arg0, BeIDCard arg1) {
log.info("Inserted");
try {
dostuffwithmycard(arg1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
...
protected static void dostuffwithmycard(BeIDCard card) throws IOException, DocumentException, GeneralSecurityException {
Security.addProvider(new BeIDProvider());
KeyStore keyStore = KeyStore.getInstance("BeID");
keyStore.load(null, null);
PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Authentication", null);
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(authnPrivateKey);
PdfReader reader = new PdfReader("C:\Untitled.pdf");
FileOutputStream os = new FileOutputStream( "C:\temp\Signed.pdf");
PdfStamper stamper = PdfStamper.createSignature(reader, os, '[=12=]');
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason("Okay");
appearance.setLocation("Home");
appearance.setVisibleSignature(new Rectangle(36,748,144,780), 1, "sig");
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature sig = new PrivateKeySignature(authnPrivateKey, "SHA1", "BeIDProvider");
MakeSignature.signDetached(appearance, digest, sig, keyStore.getCertificateChain("Signature"), null, null, null, 0, CryptoStandard.CMS);
}
我基本上是通过反复试验共同构建了这段代码。我已经得到它,所以我可以在 PDF 上实际签名(在通过输入 PIN 解锁我的签名证书后),但是当我打开 PDF 时,它告诉我签名无效。我可以在签名上看到我的名字,但是当我尝试在 Adobe Reader 中验证它时,我收到错误消息 0x2726
一定是我哪里做错了,但是一直找不到确切的原因。
您正在使用 keyStore.getKey("Authentication", null)
获取密钥并使用 keyStore.getCertificateChain("Signature")
获取认证链。看来您的卡有两个证书。那么 Signature
证书的 public 密钥将与 Authentication
证书
尝试用
替换PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Authentication", null);
PrivateKey authnPrivateKey = (PrivateKey) keyStore.getKey("Signature", null);