Парсинг информации о сертификате по словарям

This commit is contained in:
Artem Vasilev 2022-11-04 16:37:33 +03:00
parent c4f93acd3b
commit 4b24a92425
2 changed files with 47 additions and 50 deletions

View File

@ -3,6 +3,8 @@
namespace Webmasterskaya\CryptoPro;
use Webmasterskaya\CryptoPro\Constants\OIDsDictionary;
use Webmasterskaya\CryptoPro\Dictionary\IssuerTagsDictionary;
use Webmasterskaya\CryptoPro\Dictionary\SubjectTagsDictionary;
use Webmasterskaya\CryptoPro\Helpers\ArrayHelper;
use Webmasterskaya\CryptoPro\Helpers\CertificateHelper;
use Webmasterskaya\CryptoPro\Helpers\ErrorMessageHelper;
@ -132,40 +134,28 @@ class Certificate
*/
public function getOwnerInfo()
{
return $this->getInfo(SubjectTagsTranslations::class, 'SubjectName');
return $this->getInfo(SubjectTagsDictionary::class, 'SubjectName');
}
/**
* @param string $tags
* @param string $dictionary
* @param string $entitiesPath
*
* @throws \Exception
* @return array|array[]
*/
protected function getInfo(string $tags, string $entitiesPath)
protected function getInfo(string $dictionary, string $entitiesPath)
{
if (!is_subclass_of($tags, TagsTranslationsInterface::class))
try
{
throw new \TypeError(
sprintf(
'Argument 1 passed to %s::getInfo() must be an instance of \Webmasterskaya\CryptoPro\Tags\TagsTranslationsInterface, instance of %s given.',
get_called_class(), $tags
)
);
$entities = $this->getCadesProp($entitiesPath);
}
catch (\Throwable $e)
{
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при извлечении информации из сертификата'));
}
{
try
{
$entities = $this->getCadesProp($entitiesPath);
}
catch (\Throwable $e)
{
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при извлечении информации из сертификата'));
}
}
return CertificateHelper::parseCertInfo($tags, $entities);
return CertificateHelper::parseCertInfo($dictionary, $entities);
}
/**
@ -176,7 +166,7 @@ class Certificate
*/
public function getIssuerInfo()
{
return $this->getInfo(IssuerTagsTranslations::class, 'IssuerName');
return $this->getInfo(IssuerTagsDictionary::class, 'IssuerName');
}
/**

View File

@ -2,31 +2,37 @@
namespace Webmasterskaya\CryptoPro\Helpers;
use Webmasterskaya\CryptoPro\Tags\TagsCodes;
use Webmasterskaya\CryptoPro\Tags\TagsOIDs;
use Webmasterskaya\CryptoPro\Tags\TagsTranslationsInterface;
use Webmasterskaya\CryptoPro\Dictionary\DictionaryInterface;
class CertificateHelper
{
public static function parseCertInfo($tagsTranslations, string $rawInfo)
public static function parseCertInfo($dictionary, string $rawInfo)
{
if (!is_subclass_of($tagsTranslations, TagsTranslationsInterface::class))
$implements = class_implements($dictionary);
if (!isset($implements[DictionaryInterface::class]))
{
throw new \TypeError(
sprintf(
'Argument 1 passed to %s::parseCertInfo() must be an instance of \Webmasterskaya\CryptoPro\Tags\TagsTranslationsInterface, instance of %s given.',
get_called_class(), $tagsTranslations
'Argument 1 passed to %s::parseCertInfo() must implement %s',
get_called_class(), DictionaryInterface::class
)
);
}
$extractedEntities = [];
preg_match_all('/([а-яА-Яa-zA-Z0-9\s.]+)=(?:("[^"]+?")|(.+?))(?:,|$)/', $rawInfo, $extractedEntities, PREG_SET_ORDER, 0);
preg_match_all(
'/([\w0-9\s.]+)=(?:("[^"]+?")|(.+?))(?:,|$)/',
$rawInfo,
$extractedEntities,
PREG_SET_ORDER,
0
);
if (!empty($extractedEntities))
{
return array_map(function ($extractedEntity) use ($tagsTranslations) {
return array_map(function ($extractedEntity) use ($dictionary) {
$title = trim($extractedEntity[1]);
@ -38,40 +44,41 @@ class CertificateHelper
$oidIdentifier = trim($oidIdentifierMatch[1]);
}
// Если нашли OID в заголовке, пытаемся его расшифровать
// Если нашли OID то декодируем по нему
if (!empty($oidIdentifier))
{
$titleCode = TagsOIDs::codeByOid($oidIdentifier);
if (empty($titleCode))
{
$titleCode = 'OID.' . $oidIdentifier;
}
$dictionaryItem = $dictionary::getByOID($oidIdentifier);
}
else
{
$titleCode = TagsCodes::codeByName($title);
if (empty($titleCode))
{
$titleCode = $title;
}
$dictionaryItem = $dictionary::getByTitle($title);
}
$result = [];
// Получаем человекочитаемый заголовок
$title = $tagsTranslations::translationByCode($titleCode);
if ($dictionaryItem !== null)
{
$title = $dictionaryItem->title ?? $title;
$rdn = $dictionaryItem->RDN ?? null;
$oid = $dictionaryItem->OID ?? null;
}
// Вырезаем лишние кавычки
$description = preg_replace(
'/"{2}/g', '"',
'/"{2}/', '"',
preg_replace(
'/^"(.*)"/', "$1",
trim($extractedEntity[2] ?? $extractedEntity[3])
trim($extractedEntity[2] ?: $extractedEntity[3])
)
);
return ['title' => $title, 'description' => $description, 'code' => $titleCode];
return [
'title' => $title,
'description' => $description,
'RDN' => $rdn ?? null,
'OID' => $oid ?? null
];
}, $extractedEntities);
}