У меня есть приложение, которое должно получить некоторые данные (имя подписавшего) из цифровой подписи, «прикрепленной» к файлам PDF.
Я нашел только примеры в Java и C # с использованием класса AceFields класса iText GetSignatureNames
редактировать: я пробовал Pdftk с помощью dump_data_fields и generate_fpdf, и результат был (к сожалению):
/Fields [
<<
/V /dftk.com.lowagie.text.pdf.PdfDictionary@3048918
/T (Signature1)
>>]
а также
FieldType: Signature
FieldName: Signature1
FieldFlags: 0
FieldJustification: Left
Заранее спасибо !
Ну, это сложно (я бы даже сказал, невозможно, но кто знает) добиться этого только с помощью PHP.
Сначала, пожалуйста, прочитайте статья о цифровой подписи в Adobe PDF
Во-вторых, прочитав это, вы узнаете, что подпись хранится между байтами b и c согласно индикатору / ByteRange [a b c d].
В-третьих, мы можем извлечь 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));
}
В-четвертых, после третьего шага у нас есть объект PKCS # 7 в файле signature.pkcs7. К сожалению, я не знаю способов извлечения информации из подписи с использованием PHP. Таким образом, вы должны иметь возможность запускать команды оболочки для использования 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.