-
-
Save kernusr/aded2c230a05776bdbd456320f6ae33f to your computer and use it in GitHub Desktop.
| { | |
| "require": { | |
| "sop/asn1": "^4.1", | |
| "webmasterskaya/x509": "dev-master" | |
| }, | |
| "minimum-stability": "dev" | |
| } |
| <?php | |
| use Sop\ASN1\Element; | |
| use Sop\ASN1\Type\Constructed\Sequence; | |
| use Webmasterskaya\X509\Certificate\Certificate; | |
| require_once __DIR__ . './vendor/autoload.php'; | |
| $content = file_get_contents(__DIR__ . '/Polozhenie.pdf'); | |
| $regexp | |
| = '#ByteRange\[\s*(\d+) (\d+) (\d+)#'; // subexpressions are used to extract b and c | |
| $result = []; | |
| preg_match_all($regexp, $content, $result); | |
| 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(__DIR__ . '/Polozhenie.pdf', 'rb')) { | |
| $signature = stream_get_contents( | |
| $stream, $end - $start - 2, $start + 1 | |
| ); // because we need to exclude < and > from start and end | |
| fclose($stream); | |
| } | |
| if (!empty($signature)) { | |
| $binary = hex2bin($signature); | |
| $seq = Sequence::fromDER($binary); | |
| $signed_data = $seq->getTagged(0)->asExplicit()->asSequence(); | |
| $ecac = $signed_data->getTagged(0)->asImplicit(Element::TYPE_SET) | |
| ->asSet(); | |
| /** @var Sop\ASN1\Type\UnspecifiedType $ecoc */ | |
| $ecoc = $ecac->at($ecac->count() - 1); | |
| $cert = Certificate::fromASN1($ecoc->asSequence()); | |
| foreach ($cert->tbsCertificate()->subject()->all() as $attr) { | |
| /** @var Webmasterskaya\X501\ASN1\AttributeTypeAndValue $atv */ | |
| $atv = $attr->getIterator()->current(); | |
| echo $atv->type()->typeName() . ' : ' . $atv->value()->stringValue() . PHP_EOL; | |
| } | |
| } | |
| } |
$cert->tbsCertificate()->validity()->notBefore()->dateTime()->format('d-m-Y H:i:s'); // Дата начала
$cert->tbsCertificate()->validity()->notAfter()->dateTime()->format('d-m-Y H:i:s'); // Дата окончания$cert->tbsCertificate()->serialNumber(); // Серийный номерКак извлечь отпечаток - не знаю. Я его не нашёл в объекте подписи =(
Спасибо за даты. Отпечаток я тоже на нашел, но вместо него можно серийный номер. Серийный номер присутствует еще до преобразования в hex, если вардампить $cert->tbsCertificate() мы сверху видим _serialNumber, я думаю это оно, вот только для этого поля нужно сделать все в обратном направлении включая обратно преобразовать в bin2hex. Это пока догадки, я не знаю как обратить некоторые действия.
Не понял, в чем проблема с серийником.
Я метод выше дал. Он возвращает неверные данные? Или о чем речь?
Да если сравнивать с https://dss.cryptopro.ru/Verify/Verify/ серийник не совпадает, думаю над этим.
Теперь понял!
Они различаются чисто представлением. То что показывает криптопро - 16-битной представление, а то что возвращает класс - простой int
Можно конвертировать!
function dec2hex($number)
{
$hexvalues = array('0','1','2','3','4','5','6','7',
'8','9','A','B','C','D','E','F');
$hexval = '';
while($number != '0')
{
$hexval = $hexvalues[bcmod($number,'16')].$hexval;
$number = bcdiv($number,'16',0);
}
return $hexval;
}И потом просто сделать
echo dec2hex($cert->tbsCertificate()->serialNumber());Вернёт 5E110D84305C855577E75FBFC50F92B71AF6ACF6
Класс, потребовалось включить расширение в php "bcmath", но это работает, то что нужно, имеем все необходимые поля.
Проверил несколько подписанных pdf, везде отработало отлично.

Для полного идеала еще бы получать дату подписи и серийный номер.