英文:
PDFBox Library to read Invisible PDFSignature from Signed PDF..Signer name is not shown
问题
对于一个带有不可见签名的签名PDF文档,我正在使用PDFBox库来提取签名者信息,但它返回为空。对于可见签名,相同的代码可以正常工作。如果需要,有人可以帮助解决这个问题。
//加载PDF文档
PDDocument document = PDDocument.load(doc);
//迭代每个签名
for (PDSignature pdSignature : document.getSignatureDictionaries()) {
if (pdSignature != null) {
HashMap values = new HashMap();
String subFilter = pdSignature.getSubFilter();
if (subFilter != null) {
LOG.debug("---------签名详情----------");
LOG.debug("签名者姓名:" + pdSignature.getName());
values.put(SignerName, pdSignature.getName());
注意:这是您提供的代码段的翻译部分。
英文:
For a signed PDF document, with invisible signature, I am using PDFBox library to extract signer information, but it's coming as null. Same code works fine for visible signature. Can someone help on this if we need to make?
//Load PDF Document
PDDocument document = PDDocument.load(doc);
//Iterate each Signature
for (PDSignature pdSignature : document.getSignatureDictionaries()) {
if (pdSignature != null) {
HashMap values = new HashMap();
String subFilter = pdSignature.getSubFilter();
if (subFilter != null) {
LOG.debug("---------Siganature Details---------- ");
LOG.debug("Signer Name : " + pdSignature.getName());
values.put(SignerName, pdSignature.getName());
答案1
得分: 2
pdSignature.getName()
返回签名字典的 Name 条目的值。但是这个条目是可选的:
Name 文本字符串 (可选) 签署文档的人员或机构的名称。
当无法从签名中提取名称时,应仅使用此值。
通常,您需要分析嵌入式签名容器中的签名证书,以获取签名者的通用名称。
正如 @Tilman 在评论中指出的那样,pdfbox 示例 ShowSignature 展示了从 CMS 签名容器中检索数据的许多方法。
对您的评论
在一条评论中,您写道
只能提取完整的主体字符串,其中包含使用以下代码的完整字符串:“certFromSignedData.getSubjectX500Principal().toString()” [...] 有没有直接查询仅限于 CN 名称的方法?
的确,只有当您对 certFromSignedData.getSubjectX500Principal()
返回的 X500Principal
应用 toString()
时,您才会获得完整的主题可分辨名称。但是,如果您为其创建一个 sun.security.x509.X500Name
,您可以轻松检索常见名称:
X500Principal principal = certFromSignedData.getSubjectX500Principal();
sun.security.x509.X500Name name = sun.security.x509.X500Name.asX500Name(principal);
System.out.printf("Whole DN: %s\n", name);
System.out.printf("CN: %s\n", name.getCommonName());
如果您不想使用 sun.security.x509
类,您可以类似地使用 BouncyCastle 类,从匹配的 BouncyCastle X509CertificateHolder
开始:
org.bouncycastle.asn1.x500.X500Name name = certificateHolder.getSubject();
System.out.printf("Whole DN: %s\n", name);
RDN[] cns = name.getRDNs(BCStyle.CN);
System.out.printf("CN: %s\n", cns.length > 0 ? cns[0].getFirst().getValue() : null);
但对于不可见和可见的签名,它的格式是不同的。对于可见签名:SERIALNUMBER=xxxx、DNQ=xxx、EMAILADDRESS=xx、SURNAME=xx、GIVENNAME=xx、C=xx、CN=xx;而对于不可见签名,“CN=”xx“ + EMAILADDRESS=xx、OU=xx、O=”xx“、L=xx、ST=xx、C=xx”。
在主题可分辨名称中使用哪些属性,以及是否使用具有多个属性/值对的 RDN,取决于签名证书本身,与可见和不可见的签名无关。如果您对不可见和可见签名有不同的特定模式,那么您的测试 PDF 集合就会有偏差。
英文:
pdSignature.getName()
returns the value of the Name entry of the signature dictionary. But this entry is optional:
>Name text string (Optional) The name of the person or authority signing the document.
>This value should be used only when it is not possible to extract the name from the signature.
Generally you'll have to analyze the signer certificate in the embedded signature container to get the common name of the signer.
As @Tilman pointed out in a comment, the pdfbox example ShowSignature shows quite a number of means to retrieve data from a CMS signature container.
On Your Comment
In a comment you write
> Only the complete principal string can be extracted which contains the complete string using the below code "certFromSignedData.getSubjectX500Principal().toString()" [...] Any direct way of querying CN name alone?
Indeed you only get the complete subject distinguished name if you apply toString()
to the X500Principal
returned by certFromSignedData.getSubjectX500Principal()
. But if you create a sun.security.x509.X500Name
for it, you can easily retrieve the common name:
X500Principal principal = certFromSignedData.getSubjectX500Principal();
sun.security.x509.X500Name name = sun.security.x509.X500Name.asX500Name(principal);
System.out.printf("Whole DN: %s\n", name);
System.out.printf("CN: %s\n", name.getCommonName());
If you don't want to use sun.security.x509
classes, you can similarly use BouncyCastle classes, starting from the matching BouncyCastle X509CertificateHolder
:
org.bouncycastle.asn1.x500.X500Name name = certificateHolder.getSubject();
System.out.printf("Whole DN: %s\n", name);
RDN[] cns = name.getRDNs(BCStyle.CN);
System.out.printf("CN: %s\n", cns.length > 0 ? cns[0].getFirst().getValue() : null);
> however it's in different format for invisible and visible signature. For visible signature: SERIALNUMBER=xxxx, DNQ=xxx, EMAILADDRESS=xx, SURNAME=xx, GIVENNAME=xx, C=xx, CN=xx and for invisible signature "CN="xx" + EMAILADDRESS=xx, OU=xx, O="xx", L=xx, ST=xx, C=xx".
Which attributes are used in the subject DN and whether RDNs with multiple attribute/value pairs are used, depends on the signer certificate alone, it does not have anything to do with visible and invisible signature. If you have distinct specific patterns for invisible and visible signatures, then your test PDF pool is biased.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论