簡體   English   中英

如何使用PHP從PDF檢索數字簽名信息?

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

我有app需要從PDF文件上的“附加”數字簽名中檢索一些數據(簽名者名稱)。

我在Java和C#中只找到了使用iText類AcroFields方法GetSignatureNames的示例

編輯:我用dump_data_fields和generate_fpdf嘗試了pdftk ,結果是(不幸的):

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

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

提前致謝 !

好吧,它很復雜(我會說甚至不可能,但誰知道)只能用PHP實現這一點。

首先,請在Adobe PDF中閱讀關於數字簽名的文章

其次,閱讀本文后,您將知道根據/ ByteRange [abcd]指示符在b和c字節之間存儲簽名

第三,我們可以從文檔中提取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));
}

第四步,我們在文件signature.pkcs7中有PKCS#7對象。 不幸的是,我不知道使用PHP從簽名中提取信息的方法。 因此,您必須能夠運行shell命令才能使用openssl

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

在文件info.txt中運行此命令后,您將擁有一系列證書。 最后一個是你需要的。 您可以看到文件的結構並解析所需的數據。

請同時參考這個問題這個問題這個主題

編輯於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;

我已經為你調整過了,但請自己做好休息。

我使用iText並發現它非常可靠,我強烈推薦它。 你總是可以把Java代碼稱為PHP的“微服務”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM