-
-
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, везде отработало отлично.

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