Skip to content

Commit

Permalink
Merge pull request #46 from kaluga-astral/feat/SIGN-4344
Browse files Browse the repository at this point in the history
feat(cryptopro-cades): Добавлены ПИН и шаблон в функцию создания запроса на сертификат
  • Loading branch information
mfrolov89 authored Mar 13, 2024
2 parents 1235241 + bcbc839 commit 4b38682
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 12 deletions.
39 changes: 35 additions & 4 deletions packages/cryptopro-cades/src/api/createCSR.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import {
ALLOW_EXPORT_FLAG,
AT_KEYEXCHANGE,
CERTIFICATE_TEMPLATE_MAJOR_VERSION,
CERTIFICATE_TEMPLATE_MINOR_VERSION,
CERT_POLICY_QUALIFIER_TYPE,
CRYPTO_OBJECTS,
CSP_NAME_MAX_LENGTH,
SUBJECT_SIGN_TOOL_OID,
XCN_CRYPT_STRING_BASE64,
XCN_CRYPT_STRING_BASE64REQUESTHEADER,
} from '../constants';
import { CryptoError } from '../errors';
import { CreateCSRInputDTO } from '../types/СreateCSRInputDTO';
import { outputDebug } from '../utils';

Expand Down Expand Up @@ -35,6 +38,12 @@ export const createCSR = (data: CreateCSRInputDTO): Promise<string> => {
await setCryptoProperty(pKey, 'ProviderType', data.providerCode);
await setCryptoProperty(pKey, 'ContainerName', data.containerName);

// containerPin === undefined –> КриптоПро и Випнет показывают свои окна для ввода пина
// containerPin === '' –> КриптоПро не защищает контейнер паролем, Випнет показывает свое окно
if (data.containerPin !== undefined) {
await setCryptoProperty(pKey, 'Pin', data.containerPin);
}

await setCryptoProperty(
pKey,
'ExportPolicy',
Expand All @@ -56,7 +65,7 @@ export const createCSR = (data: CreateCSRInputDTO): Promise<string> => {
const distinguishedName = await createObject(
CRYPTO_OBJECTS.distinguishedName,
);
const dnValue = data.attributes
const dnValue = data.certAttributes
.map((attr) => `${attr.oid}="${attr.value}"`)
.join(', ');

Expand Down Expand Up @@ -166,15 +175,34 @@ export const createCSR = (data: CreateCSRInputDTO): Promise<string> => {
// добавляем способ подписания в расширения сертификата
await extensions.Add(subjectSignToolExt);

// identification kind
// описываем и добавляем identification kind
const identificationKindExt = await createObject(
CRYPTO_OBJECTS.extensionIdentificationKind,
);

await identificationKindExt.InitializeEncode(data.identificationKind);
await extensions.Add(identificationKindExt);

// запрос
// описываем и добавляем шаблон сертификата (если есть)
if (data.templateOid) {
const templateOid = await createObject(CRYPTO_OBJECTS.objectId);

await templateOid.InitializeFromValue(data.templateOid);

const templateExt = await createObject(
CRYPTO_OBJECTS.extensionTemplate,
);

await templateExt.InitializeEncode(
templateOid,
CERTIFICATE_TEMPLATE_MAJOR_VERSION,
CERTIFICATE_TEMPLATE_MINOR_VERSION,
);

extensions.Add(templateExt);
}

// запрос на сертификат
const enroll = await createObject(CRYPTO_OBJECTS.enrollment);

await enroll.InitializeFromRequest(certRequestPkcs10);
Expand All @@ -189,7 +217,10 @@ export const createCSR = (data: CreateCSRInputDTO): Promise<string> => {
} catch (error) {
logData.push({ error });

throw error;
throw CryptoError.createCadesError(
error,
'Ошибка при формировании контейнера.',
);
} finally {
outputDebug('createCSR >>', logData);
}
Expand Down
7 changes: 5 additions & 2 deletions packages/cryptopro-cades/src/api/getReaders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function getReaders(
if (!systemInfo.cryptoProInstalled) {
throw CryptoError.create(
'CBP-12',
'Ошибка получения списка доступных считывателей',
'Ошибка при получении списка доступных считывателей.',
null,
);
}
Expand Down Expand Up @@ -76,7 +76,10 @@ export function getReaders(
return (readersCache = readers);
} catch (error) {
logData.push({ error });
throw error;
throw CryptoError.createCadesError(
error,
'Ошибка при получении списка доступных считывателей.',
);
} finally {
logData.push({ readers });
outputDebug('getReaders >>', logData);
Expand Down
13 changes: 9 additions & 4 deletions packages/cryptopro-cades/src/api/installCertificate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
X509CertificateEnrollmentContext,
XCN_CRYPT_STRING_BASE64_ANY,
} from '../constants';
import { CryptoError } from '../errors';
import { outputDebug } from '../utils';

import { createObject } from './createObject';
Expand All @@ -12,7 +13,7 @@ import { afterPluginLoaded } from './internal/afterPluginLoaded';
/**
* Устанавливает цепочку сертификатов в хранилище
* @param {string} certificate ответ УЦ в DER кодировке
* @param {string | undefined} pin ПИН-код от контейнера
* @param {string | undefined} pin ПИН-код от контейнера. Если не указан, отобразится нативное окно ввода криптопровайдера.
* @returns {Promise<void>}
*/
export const installCertificate = (
Expand All @@ -28,10 +29,11 @@ export const installCertificate = (
await enroll.Initialize(X509CertificateEnrollmentContext.ContextUser);

await enroll.InstallResponse(
CADESCOM_InstallResponseRestrictionFlags.CADESCOM_AllowUntrustedRoot,
CADESCOM_InstallResponseRestrictionFlags.CADESCOM_AllowUntrustedRoot |
CADESCOM_InstallResponseRestrictionFlags.CADESCOM_UseContainerStore,
certificate,
XCN_CRYPT_STRING_BASE64_ANY,
pin,
pin ?? '',
);

logData.push('Сертификат установлен');
Expand All @@ -40,7 +42,10 @@ export const installCertificate = (
} catch (error) {
logData.push({ error });

throw error;
throw CryptoError.createCadesError(
error,
'Ошибка при установке сертификата.',
);
} finally {
outputDebug('installCertificate >>', logData);
}
Expand Down
12 changes: 12 additions & 0 deletions packages/cryptopro-cades/src/constants/cades.ts
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,12 @@ export enum CADESCOM_InstallResponseRestrictionFlags {
* Установка сертификата, даже если корневой центр сертификации для него не является доверенным.
*/
CADESCOM_AllowUntrustedRoot = 0x4,

/**
* Флаг для поиска закрытого ключа не в хранилище Request, а по всем контейнерам.
* @see https://www.cryptopro.ru/forum2/default.aspx?g=posts&t=21989
*/
CADESCOM_UseContainerStore = 0x40000000,
}

/**
Expand Down Expand Up @@ -1138,6 +1144,12 @@ export const enum CRYPTO_OBJECTS {
*/
extensionIdentificationKind = 'X509Enrollment.CX509ExtensionIdentificationKind',

/**
* Объект описывает расширение CertificateTemplate, сообщающее УЦ, какой шаблон следует использовать при выдаче сертификата
* @see https://docs.cryptopro.ru/cades/plugin/certenroll/cx509extensiontemplate
*/
extensionTemplate = 'X509Enrollment.CX509ExtensionTemplate',

/**
* Объект предназначен для создания запросов на сертификат и установки полученных сертификатов.
* @see https://docs.cryptopro.ru/cades/plugin/certenroll/cx509enrollment?id=cx509enrollment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,15 @@
* @see https://habr.com/ru/articles/722732/
*/
export const CSP_NAME_MAX_LENGTH = 127;

/**
* Сведения о версии расширения CertificateTemplate
* @see https://learn.microsoft.com/ru-ru/windows/win32/api/certenroll/nn-certenroll-ix509extensiontemplate
*/
export const CERTIFICATE_TEMPLATE_MAJOR_VERSION = 1;

/**
* Сведения о версии расширения CertificateTemplate
* @see https://learn.microsoft.com/ru-ru/windows/win32/api/certenroll/nn-certenroll-ix509extensiontemplate
*/
export const CERTIFICATE_TEMPLATE_MINOR_VERSION = 0;
2 changes: 1 addition & 1 deletion packages/cryptopro-cades/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ export * from './cryptoProviders';

export * from './oids-dictionary';

export * from './crypto';
export * from './enrollment';
12 changes: 11 additions & 1 deletion packages/cryptopro-cades/src/types/СreateCSRInputDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export type CreateCSRInputDTO = {
*/
containerName: string;

/**
* PIN-код для контейнера закрытого ключа.
*/
containerPin?: string;

/**
* Флаг возможности экспорта закрытого ключа
*/
Expand All @@ -23,7 +28,7 @@ export type CreateCSRInputDTO = {
/**
* Массив аттрибутов поля Subject
*/
attributes: { oid: string; value: string }[];
certAttributes: { oid: string; value: string }[];

/**
* Сумма флагов назначения ключа
Expand All @@ -50,4 +55,9 @@ export type CreateCSRInputDTO = {
* Тип идентификации в соответствии с 795 приказом ФСБ. Принимает значения {0, 1, 2, 3}
*/
identificationKind: number;

/**
* Oid, сообщающий УЦ, какой шаблон следует использовать при выдаче или продлении сертификата
*/
templateOid?: string;
};

0 comments on commit 4b38682

Please sign in to comment.