简体   繁体   English

如何使用PHP从PDF检索数字签名信息?

[英]How to retrieve digital signature information from PDF with PHP?

I have app that needs to retrieve some data (signer name) from digital signature "attached" on PDF files. 我有app需要从PDF文件上的“附加”数字签名中检索一些数据(签名者名称)。

I have found only examples in Java and C# using the iText class AcroFields method GetSignatureNames 我在Java和C#中只找到了使用iText类AcroFields方法GetSignatureNames的示例

edit: I've tried pdftk with dump_data_fields and generate_fpdf and the result was that (unfortunately): 编辑:我用dump_data_fields和generate_fpdf尝试了pdftk ,结果是(不幸的):

/Fields [
<<
/V /dftk.com.lowagie.text.pdf.PdfDictionary@3048918
/T (Signature1)
>>]

and

FieldType: Signature
FieldName: Signature1
FieldFlags: 0
FieldJustification: Left

Thanks in Advance ! 提前致谢 !

Well, it's complicated (I would say even impossible, but who knows) to achieve this only with PHP. 好吧,它很复杂(我会说甚至不可能,但谁知道)只能用PHP实现这一点。

At first, please read article about digital signature in Adobe PDF 首先,请在Adobe PDF中阅读关于数字签名的文章

Second, after reading this you will know that signature is stored between b and c bytes according to /ByteRange[abcd] indicator 其次,阅读本文后,您将知道根据/ ByteRange [abcd]指示符在b和c字节之间存储签名

Third, we can extract b and c from document and then extract signature itself (guide says it will be hexdecoded PKCS7# object). 第三,我们可以从文档中提取b和c然后提取签名本身(指南说它将是十六进制编码的PKCS7#对象)。

<?php

 $content = file_get_contents('test.pdf');

 $regexp = '#ByteRange\[\s*(\d+) (\d+) (\d+)#'; // subexpressions are used to extract b and c

 $result = [];
 preg_match_all($regexp, $content, $result);

 // $result[2][0] and $result[3][0] are b and c
 if (isset($result[2]) && isset($result[3]) && isset($result[2][0]) && isset($result[3][0]))
 {
     $start = $result[2][0];
     $end = $result[3][0];
     if ($stream = fopen('test.pdf', 'rb')) {
         $signature = stream_get_contents($stream, $end - $start - 2, $start + 1); // because we need to exclude < and > from start and end

         fclose($stream);
     }

     file_put_contents('signature.pkcs7', hex2bin($signature));
}

Forth, after third step we have PKCS#7 object in file signature.pkcs7. 第四步,我们在文件signature.pkcs7中有PKCS#7对象。 Unfortunately, I don't know methods to extract information from signature using PHP. 不幸的是,我不知道使用PHP从签名中提取信息的方法。 So you must be able to run shell commands to use openssl 因此,您必须能够运行shell命令才能使用openssl

openssl pkcs7 -in signature.pkcs7 -inform DER -print_certs > info.txt

After running this command in file info.txt you will have a chain of certificates. 在文件info.txt中运行此命令后,您将拥有一系列证书。 Last one is the one you need. 最后一个是你需要的。 You can see the structure of the file and parse needed data. 您可以看到文件的结构并解析所需的数据。

Please also refer to this question , this question and this topic 请同时参考这个问题这个问题这个主题

EDIT at 2017-10-09 I knowingly advised you to see exactly this question There is a code that you can adjust to your needs. 编辑于2017-10-09我故意建议你看看这个问题有一个代码,你可以根据自己的需要进行调整。

use ASN1\Type\Constructed\Sequence;
use ASN1\Element;
use X509\Certificate\Certificate;       

$seq = Sequence::fromDER($binaryData);
$signed_data = $seq->getTagged(0)->asExplicit()->asSequence();
// ExtendedCertificatesAndCertificates: https://tools.ietf.org/html/rfc2315#section-6.6
$ecac = $signed_data->getTagged(0)->asImplicit(Element::TYPE_SET)->asSet();
// ExtendedCertificateOrCertificate: https://tools.ietf.org/html/rfc2315#section-6.5
$ecoc = $ecac->at($ecac->count() - 1);
$cert = Certificate::fromASN1($ecoc->asSequence());
$commonNameValue = $cert->tbsCertificate()->subject()->toString();
echo $commonNameValue;

I've adjusted it for you, but please make the rest by yourself. 我已经为你调整过了,但请自己做好休息。

I've used iText and found it to be very reliable, I highly recommend it. 我使用iText并发现它非常可靠,我强烈推荐它。 you can always call the java code as a "microservice" from PHP. 你总是可以把Java代码称为PHP的“微服务”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM