mirror of
https://github.com/crypto-pro-web/crypto-pro-php.git
synced 2025-01-18 19:25:51 +03:00
Создание совмещённой подписи
This commit is contained in:
parent
b3d5eb0f5a
commit
b63f1037c6
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Webmasterskaya\CryptoPro;
|
namespace Webmasterskaya\CryptoPro;
|
||||||
|
|
||||||
|
use CPAttribute;
|
||||||
use Webmasterskaya\CryptoPro\Helpers\CertificateHelper;
|
use Webmasterskaya\CryptoPro\Helpers\CertificateHelper;
|
||||||
use Webmasterskaya\CryptoPro\Helpers\ErrorMessageHelper;
|
use Webmasterskaya\CryptoPro\Helpers\ErrorMessageHelper;
|
||||||
|
|
||||||
@ -167,23 +168,128 @@ class CryptoPro
|
|||||||
/**
|
/**
|
||||||
* Возвращает сертификат по отпечатку
|
* Возвращает сертификат по отпечатку
|
||||||
*
|
*
|
||||||
* @return void
|
* @param string $thumbprint отпечаток сертификата
|
||||||
*/
|
* @param bool $validOnly проверять сертификат по дате и наличию приватного ключа
|
||||||
public static function getCertificate()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* создает совмещенную (присоединенную) подпись сообщения
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @throws \Exception
|
||||||
|
* @return Certificate
|
||||||
*/
|
*/
|
||||||
public static function createAttachedSignature()
|
public static function getCertificate(string $thumbprint, bool $validOnly = true)
|
||||||
{
|
{
|
||||||
|
$thumbprint = trim($thumbprint);
|
||||||
|
|
||||||
|
if (!$thumbprint)
|
||||||
|
{
|
||||||
|
throw new \Exception('Отпечаток не указан');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($validOnly === true)
|
||||||
|
{
|
||||||
|
$certificates = self::getCertificates();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$certificates = self::getAllCertificates();
|
||||||
|
}
|
||||||
|
|
||||||
|
$found = false;
|
||||||
|
|
||||||
|
foreach ($certificates as $certificate)
|
||||||
|
{
|
||||||
|
if ($certificate->thumbprint === $thumbprint)
|
||||||
|
{
|
||||||
|
$found = $certificate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($found === false)
|
||||||
|
{
|
||||||
|
throw new \Exception('Сертификат с отпечатком: "' . $thumbprint . '" не найден');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* создает отсоединенную (открепленную) подпись сообщения
|
* Создает совмещенную (присоединенную) подпись сообщения
|
||||||
|
*
|
||||||
|
* @param string $thumbprint отпечаток сертификата
|
||||||
|
* @param string $unencryptedMessage подписываемое сообщение
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
|
* @return string подпись в формате PKCS#7
|
||||||
|
*/
|
||||||
|
public static function createAttachedSignature(string $thumbprint, string $unencryptedMessage)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$cadesCertificate = self::getCadesCertificateFromStore($thumbprint, CURRENT_USER_STORE);
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
$cadesCertificate = self::getCadesCertificateFromStore($thumbprint, CONTAINER_STORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$cadesAttrs = new \CPAttribute();
|
||||||
|
$cadesSignedData = new \CPSignedData();
|
||||||
|
$cadesSigner = new \CPSigner();
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при инициализации подписи'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentDateTime = (new \DateTime())->format('d.m.Y H:i:s');
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$cadesAttrs->set_Name(AUTHENTICATED_ATTRIBUTE_SIGNING_TIME);
|
||||||
|
$cadesAttrs->set_Value($currentDateTime);
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при установке времени подписи'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$messageBase64 = base64_encode($unencryptedMessage);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$cadesSigner->set_Certificate($cadesCertificate);
|
||||||
|
|
||||||
|
/** @var \CPAttributes $cadesAuthAttrs */
|
||||||
|
$cadesAuthAttrs = $cadesSigner->get_AuthenticatedAttributes();
|
||||||
|
$cadesAuthAttrs->Add($cadesAttrs);
|
||||||
|
|
||||||
|
$cadesSignedData->set_ContentEncoding(BASE64_TO_BINARY);
|
||||||
|
$cadesSignedData->set_Content($messageBase64);
|
||||||
|
|
||||||
|
$cadesSigner->set_Options(CERTIFICATE_INCLUDE_WHOLE_CHAIN);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при указании данных для подписи'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
/** @var string $signature */
|
||||||
|
$signature = $cadesSignedData->SignCades($cadesSigner, PKCS7_TYPE);
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при подписании данных'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Создает отсоединенную (открепленную) подпись сообщения
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@ -260,31 +366,27 @@ class CryptoPro
|
|||||||
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при открытии хранилища'));
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при открытии хранилища'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$cadesCertificates = null;
|
|
||||||
$cadesCertificatesCount = 0;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$cadesCertificates = $cadesStore->get_Certificates();
|
$cadesCertificates = $cadesStore->get_Certificates();
|
||||||
|
|
||||||
if ($cadesCertificates)
|
/**
|
||||||
|
* Не рассматриваются сертификаты не действительны на данный момент
|
||||||
|
*/
|
||||||
|
if ($validOnly === true)
|
||||||
{
|
{
|
||||||
if ($validOnly === true)
|
$cadesCertificates = $cadesCertificates->Find(CERTIFICATE_FIND_TIME_VALID);
|
||||||
{
|
|
||||||
$cadesCertificates = $cadesCertificates->Find(CERTIFICATE_FIND_TIME_VALID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Не рассматриваются сертификаты, в которых отсутствует закрытый ключ
|
|
||||||
* или не действительны на данный момент
|
|
||||||
*/
|
|
||||||
if ($withPrivateKey === true)
|
|
||||||
{
|
|
||||||
$cadesCertificates = $cadesCertificates->Find(CERTIFICATE_FIND_EXTENDED_PROPERTY, CAPICOM_PROPID_KEY_PROV_INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cadesCertificatesCount = $cadesCertificates->Count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Не рассматриваются сертификаты, в которых отсутствует закрытый ключ
|
||||||
|
*/
|
||||||
|
if ($withPrivateKey === true)
|
||||||
|
{
|
||||||
|
$cadesCertificates = $cadesCertificates->Find(CERTIFICATE_FIND_EXTENDED_PROPERTY, CAPICOM_PROPID_KEY_PROV_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cadesCertificatesCount = $cadesCertificates->Count();
|
||||||
}
|
}
|
||||||
catch (\Throwable $e)
|
catch (\Throwable $e)
|
||||||
{
|
{
|
||||||
@ -325,6 +427,62 @@ class CryptoPro
|
|||||||
return $certificates;
|
return $certificates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function getCadesCertificateFromStore(string $thumbprint, int $storeLocation, string $storeName = 'My')
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$cadesStore = new \CPStore();
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при попытке доступа к хранилищу'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$cadesStore->Open($storeLocation, $storeName, STORE_OPEN_MAXIMUM_ALLOWED);
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при открытии хранилища'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$cadesCertificates = $cadesStore->get_Certificates();
|
||||||
|
$cadesCertificatesCount = $cadesCertificates->Count();
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка получения списка сертификатов из хранилища'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$cadesCertificatesCount)
|
||||||
|
{
|
||||||
|
throw new \Exception('Нет доступных сертификатов в хранилище');
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$cadesCertificates = $cadesCertificates->Find(CERTIFICATE_FIND_SHA1_HASH, $thumbprint);
|
||||||
|
|
||||||
|
$cadesCertificatesCount = $cadesCertificates->Count();
|
||||||
|
|
||||||
|
if (!$cadesCertificatesCount)
|
||||||
|
{
|
||||||
|
throw new \Exception('Сертификат с отпечатком: "' . $thumbprint . '" не найден в хранилище');
|
||||||
|
}
|
||||||
|
|
||||||
|
$cadesCertificate = $cadesCertificates->Item(1);
|
||||||
|
}
|
||||||
|
catch (\Throwable $e)
|
||||||
|
{
|
||||||
|
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при получении сертификата из хранилища'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cadesCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
protected static function mergeToAvailableCertificates(array &$availableCertificates = [], array $mergedCertificates = [])
|
protected static function mergeToAvailableCertificates(array &$availableCertificates = [], array $mergedCertificates = [])
|
||||||
{
|
{
|
||||||
if (empty($availableCertificates))
|
if (empty($availableCertificates))
|
||||||
|
Loading…
Reference in New Issue
Block a user