Java 如何验证iText数字签名?
我正在研究数字签名验证,在写下我的问题之前,我必须说我发现了很多例子,我相信有些与旧的iText版本有关,因为这些方法似乎已经不存在了 我使用的是iText 5.8.8,我没有任何例外,但是当我检查验证状态时,它总是返回false,我不知道该怎么办,我开始认为签名过程中可能有问题,但仍然不知道是什么 这是我试图检查它的方式:Java 如何验证iText数字签名?,java,itext,signature,Java,Itext,Signature,我正在研究数字签名验证,在写下我的问题之前,我必须说我发现了很多例子,我相信有些与旧的iText版本有关,因为这些方法似乎已经不存在了 我使用的是iText 5.8.8,我没有任何例外,但是当我检查验证状态时,它总是返回false,我不知道该怎么办,我开始认为签名过程中可能有问题,但仍然不知道是什么 这是我试图检查它的方式: public List<VerificationException> verifySignatures(byte[] assinado) throws Gene
public List<VerificationException> verifySignatures(byte[] assinado) throws GeneralSecurityException, IOException {
// Security.addProvider(pkcs11Provider);
List<VerificationException> errors = null;
PdfReader reader = new PdfReader(assinado);
AcroFields af = reader.getAcroFields();
ArrayList<String> names = af.getSignatureNames();
for (String name : names) {
System.out.println("Signature name: " + name);
System.out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name));
System.out.println("Document revision: " + af.getRevision(name) + " of " + af.getTotalRevisions());
PdfPKCS7 pk = af.verifySignature(name);
if (!pk.verify()) {
throw new GeneralSecurityException("some erros message... ");
}
public List verifySignatures(byte[]assinado)抛出GeneralSecurityException,IOException{
//Security.addProvider(pkcs11Provider);
列表错误=null;
PdfReader读取器=新PdfReader(assinado);
AcroFields af=reader.getAcroFields();
ArrayList name=af.getSignatureNames();
for(字符串名称:名称){
System.out.println(“签名名称:”+名称);
System.out.println(“签名涵盖整个文档:+af.SignatureOverwholeDocument(名称));
System.out.println(“文档修订:“+af.getTotalRevisions()的+af.getRevision(名称)+”);
PdfPKCS7 pk=af.verifySignature(名称);
如果(!pk.verify()){
抛出新的GeneralSecurityException(“某些错误消息…”);
}
}
关键是每次我检查pk.verify()时,它都返回false
JohnDoe:00000099999证书
以下是该协议的签署方式:
public byte[] signPdfFirstTime(PrivateKey pk, Certificate[] chain, String providerName, String conteudoBase64, X509Certificate cert, String alias) throws IOException, DocumentException, GeneralSecurityException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Document document = new Document();
PdfWriter.getInstance(document, bos);
document.open();
document.addTitle("Dummy PDF");
document.addSubject("Dummy PDF");
document.addKeywords("dummy, test");
document.addAuthor("John Doe ");
document.addCreator("John Doe ");
document.newPage();
document.add(new Paragraph("Title2"));
document.close();
String name = alias;
byte[] bytes = bos.toByteArray();
PdfReader reader = new PdfReader(bytes);
PdfStamper stamper = PdfStamper.createSignature(reader, bos, '\0');
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason("REASON");
appearance.setLocation("CITY");
appearance.setCertificate(cert);
Rectangle rectangle = new Rectangle(550, 50, 610, 500);
//here it goes the name
appearance.setVisibleSignature(rectangle, 1, name);
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, providerName);
ExternalDigest digest = new BouncyCastleDigest();
List<CrlClient> crlList = new ArrayList<CrlClient>();
crlList.add(new CrlClientOnline());
LtvVerification v = stamper.getLtvVerification();
OcspClient ocspClient = new OcspClientBouncyCastle();
String url = CertificateUtil.getCRLURL(cert);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509CRL crl = (X509CRL) cf.generateCRL(new URL(url).openStream());
System.out.println("CRL valid until: " + crl.getNextUpdate());
System.out.println("Certificate revoked: " + crl.isRevoked(chain[0]));
if (crl.isRevoked(chain[0])) {
throw new GeneralSecurityException("CERT REVOKED!");
}
else {
MakeSignature.processCrl(cert, crlList);
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
byte[] b = bos.toByteArray();
bos.close();
return b;
}
}
public byte[]signPdfFirstTime(私钥pk、证书[]链、字符串提供程序名称、字符串conteudoBase64、X509证书证书证书、字符串别名)引发IOException、DocumentException、GeneralSecurityException{
ByteArrayOutputStream bos=新建ByteArrayOutputStream();
文档=新文档();
getInstance(文档,bos);
document.open();
文件。添加标题(“虚拟PDF”);
文件。添加主题(“虚拟PDF”);
文件。添加关键词(“假人,试验”);
文件作者(以下简称“John Doe”);
文件。addCreator(“John Doe”);
document.newPage();
文件.添加(新的段落(“标题2”);
document.close();
字符串名称=别名;
byte[]bytes=bos.toByteArray();
PdfReader reader=新PdfReader(字节);
PdfStamper stamper=PdfStamper.createSignature(读卡器,bos,'\0');
PdfSignatureAppearance外观=母版。getSignatureAppearance();
外观。设置原因(“原因”);
外观。设置位置(“城市”);
外观.证书(cert);
矩形=新矩形(550、50、610、500);
//名字在这里
外观。setVisibleSignature(矩形,1,名称);
//创建签名
ExternalSignature pks=新的PrivateKeySignature(pk,DigestAlgorithms.SHA256,providerName);
ExternalDigest=新的BouncyCastleDigest();
List crlList=new ArrayList();
添加(新的CrlClientOnline());
LtvVerification v=母版。getLtvVerification();
OcspClient-OcspClient=new-OcspClientBouncyCastle();
字符串url=CertificateUtil.getCRLURL(证书);
CertificateFactory cf=CertificateFactory.getInstance(“X.509”);
X509CRL crl=(X509CRL)cf.generateCRL(新URL(URL).openStream());
System.out.println(“CRL有效期至:”+CRL.getNextUpdate());
System.out.println(“证书已吊销:+crl.isrelock(链[0]));
if(crl.isr(链[0])){
抛出新的GeneralSecurityException(“证书已吊销!”);
}
否则{
MakeSignature.processCrl(证书、crlList);
签名分离(外观、摘要、pks、链、null、null、null、null、0、CryptoStandard.CMS);
字节[]b=bos.toByteArray();
bos.close();
返回b;
}
}
签名正在根据上述方法返回的字节数组进行验证iText 5.8.8不存在(尚未存在),也许您的意思是5.5.8?(这里是iText QA&Release Engineer,我应该知道)请共享一个签名的示例文档来重现该问题。我的错,正如您所说的,它实际上是5.5.8。没有可共享的示例文档,因为正在签名的是在signPdfFirstTime方法的第一行上创建的文档。我的主要目标是在服务器端验证签名,而我无法获得简单的字符串或其他内容比文档签名更简单,所以我认为在内存中创建一个文档,签名然后检查签名是个好主意。你认为这可能是一个不好的方法吗?谢谢你的注意。我刚刚在这里读了你的帖子,我可以说几乎是一样的,pk.verify总是返回false。我尝试了你的工作,但没有成功帮助,因为您建议通过反射获取的参数的值已为null。我尝试反编译PdfPKCS7以查看verify()内部发生的情况,其中有一些内容:AbscentencContDigestCompare=Arrays.equals(msgDigestBytes,this.digestAttr)..比较这两个数组的结果是不同的,因此缺席比较标志的结果始终为false,然后将一切都搞糟。现在我正在寻找一些原因,最后尝试修复导致两个不同数组的某个地方。