web-dev-qa-db-ja.com

PHPでPDFからデジタル署名情報を取得する方法は?

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

前もって感謝します !

21
celsowm

まあ、PHPだけでこれを達成するのは複雑です(私は不可能とさえ言いますが、誰が知っているでしょうか)。

まず、お読みください Adobe PDFのデジタル署名に関する記事

次に、これを読んだ後、署名が/ ByteRange [a b c d]インジケータに従ってbバイトとcバイトの間に格納されていることがわかります

3番目に、ドキュメントからbとcを抽出してから、署名自体を抽出できます(ガイドでは、16進数にデコードされた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));
}

4番目に、3番目のステップの後、ファイルsignature.pkcs7にPKCS#7オブジェクトがあります。残念ながら、PHPを使用して署名から情報を抽出する方法はわかりません。したがって、opensslを使用するには、シェルコマンドを実行できる必要があります。

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

ファイルinfo.txtでこのコマンドを実行すると、証明書のチェーンが作成されます。最後はあなたが必要なものです。ファイルの構造を確認し、必要なデータを解析できます。

この質問この質問 および このトピック も参照してください

EDIT at 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;

調整しましたが、残りはご自身でお作りください。

15
Denis Alimov

私はiTextを使用しましたが、非常に信頼できることがわかりましたので、強くお勧めします。 PHPからJavaコードを「マイクロサービス」としていつでも呼び出すことができます。

0
Felipe Valdes