Skip to content

Commit

Permalink
Merge pull request #25 from mt89vein/AR5-6225
Browse files Browse the repository at this point in the history
  • Loading branch information
AndTem authored May 27, 2022
2 parents 134accc + 9e8491f commit c346f4f
Show file tree
Hide file tree
Showing 35 changed files with 265 additions and 168 deletions.
15 changes: 15 additions & 0 deletions examples/cryptopro-cades/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
ICertificate,
ICryptoProvider,
ISystemInfo,
checkIsValidSystemSetup,
} from '@astral/cryptopro-cades';

import { CertificateInfo } from './components/CertificateInfo';
Expand Down Expand Up @@ -319,10 +320,24 @@ const CryptoApp = () => {
}
};

/**
* Проверить систему.
*/
async function checkSystem() {
try {
await checkIsValidSystemSetup();
window.alert('checkSystem: ok');
} catch (error) {
outputError(error);
window.alert(error.toString());
}
}

return (
<>
<p>Версия плагина {versionInfo?.cadesVersion}</p>
<p>Версия криптопровайдера {versionInfo?.cspVersion}</p>
<button onClick={() => checkSystem()}>Проверить систему</button>
<button onClick={() => setShowCryptoProviders(!showCryptoProviders)}>
{!showCryptoProviders
? 'Показать криптопровайдеры'
Expand Down
3 changes: 3 additions & 0 deletions packages/cryptopro-cades/src/Certificate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class Certificate {
surname: string | null;
name: string | null;
country: string | null;
region: string | null;
locality: string | null;
street: string | null;
organization: string | null;
Expand All @@ -34,6 +35,7 @@ export class Certificate {
surname: null,
name: null,
country: null,
region: null,
locality: null,
street: null,
organization: null,
Expand Down Expand Up @@ -142,6 +144,7 @@ export class Certificate {
/**
* Распарсить сертификат из исходного объекта.
* @param {ICertificate} cert исходный сертификат.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<Certificate>} распрасенный сертификат.
*/
public static async CreateFrom(cert: ICertificate): Promise<Certificate> {
Expand Down
22 changes: 19 additions & 3 deletions packages/cryptopro-cades/src/PluginConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { CryptoError } from './errors';
import { outputError } from './utils/outputError';
import { outputError } from './utils';
import { CRYPTO_PROVIDERS } from './constants';
import { ICryptoProvider } from './types';

/**
* Настройки плагина.
Expand All @@ -10,6 +12,14 @@ class PluginConfig {
*/
private errorListeners: ((error: CryptoError) => void)[] = [];

/**
* Функция для проверки (переопределения проверки) версии криптопровайдера.
* Если вернуть null, считаем что версия прошла проверку.
*/
checkCspVersionFunc:
| ((cryptoProvider: ICryptoProvider) => string | null)
| null = null;

/**
* Выводить дебаг-информацию.
*/
Expand All @@ -25,12 +35,18 @@ class PluginConfig {
*/
CheckSystemSetup: boolean = true;

/**
* Список криптопровайдеров для проверки и работы.
*/
CheckCryptoProviders: ICryptoProvider[] = CRYPTO_PROVIDERS;

/**
* Зарегистрировать подписчика ошибок.
* @param cb Функция обратного вызова.
* @remarks Подписчики ошибок будут вызваны в обратном порядке.
*/
public addErrorListener(cb: (error: CryptoError) => void) {
this.errorListeners.push(cb);
this.errorListeners.unshift(cb);
}

/**
Expand Down Expand Up @@ -62,7 +78,7 @@ const logErrorWhenInDebug = (error: CryptoError): void => {
}

if (errors?.length) {
outputError(errors);
outputError('Ошибка >>', errors);
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@ import { ISystemInfo } from '../types';
import { outputDebug } from '../utils';

import { getSystemInfo } from './getSystemInfo';
import { checkIsSupportedCSPVersion } from './internal/checkIsSupportedCSPVersion';
import { isSupportedCadesVersion } from './internal/isSupportedCadesVersion';
import { isSupportedCSPVersion } from './internal/isSupportedCSPVersion';

/**
* Проверяет корректность настроек ЭП на машине.
*
* @returns {boolean} флаг корректности настроек.
* @throws {CryptoError} в случае обнаружения ошибок, если не установлен криптопровайдер или версия не поддерживается.
*/
export const isValidSystemSetup = async (): Promise<boolean> => {
export const checkIsValidSystemSetup = async (): Promise<void> => {
let systemInfo: ISystemInfo | null = null;
let isValid = false;
const logData = [];
try {
try {
Expand Down Expand Up @@ -41,16 +39,14 @@ export const isValidSystemSetup = async (): Promise<boolean> => {
);
}

if (systemInfo.cspVersion && !isSupportedCSPVersion(systemInfo)) {
throw CryptoError.create('CBP-4', 'Не поддерживаемая версия CSP', null);
}
isValid = true;
await checkIsSupportedCSPVersion();
} catch (error) {
logData.push({ error });
throw error;
} finally {
logData.push({ isValid });
outputDebug('isValidSystemSetup >>', logData);
outputDebug(
'checkIsValidSystemSetup >>',
logData.length === 0 ? 'ok' : logData
);
}

return isValid;
};
8 changes: 5 additions & 3 deletions packages/cryptopro-cades/src/api/createObject.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CryptoError } from '../errors';
import { deasync } from '../utils';

import { afterPluginLoaded } from './internal/afterPluginLoaded';
import { canAsync } from './internal/canAsync';
Expand All @@ -7,10 +8,11 @@ import { canAsync } from './internal/canAsync';
* Создание криптографического объекта.
* @see https://docs.cryptopro.ru/cades/plugin/plugin-activation
* @param {string} objectIdentifier. наименование создаваемого объекта. Объекты указываются в @see CRYPTO_OBJECTS.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<object|null|undefined>} Созданный объект.
*/
export async function createObject(objectIdentifier: string): Promise<any> {
return afterPluginLoaded(async () => {
export function createObject(objectIdentifier: string): Promise<any | never> {
return afterPluginLoaded(() => {
if (!objectIdentifier) {
throw CryptoError.create(
'CBP-7',
Expand All @@ -23,7 +25,7 @@ export async function createObject(objectIdentifier: string): Promise<any> {
? window.cadesplugin.CreateObjectAsync(objectIdentifier)
: window.cadesplugin.CreateObject(objectIdentifier);

return object instanceof Promise ? await object : object;
return deasync(object);
} catch (error) {
throw CryptoError.createCadesError(
error,
Expand Down
1 change: 1 addition & 0 deletions packages/cryptopro-cades/src/api/decrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { setCryptoProperty } from './internal/setCryptoProperty';
/**
* Расшифровать данные.
* @param {string} encryptedData -входные данные для расшифровки в формате Base64 или ArrayBuffer.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<string>} .Расшифрованная строка в кодировке Base64.
*/
export function decrypt(encryptedData: ArrayBuffer | string): Promise<string> {
Expand Down
1 change: 1 addition & 0 deletions packages/cryptopro-cades/src/api/encrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { setCryptoProperty } from './internal/setCryptoProperty';
* Зашировать данные на указанные сертификаты.
* @param {string} data -входные данные для расшифровки в формате Base64 или ArrayBuffer.
* @param {ICertificate[]} recipientCertificates -список сертификатов получателей шифрованного сообщения.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<string>} .Зашифрованная строка в кодировке Base64.
*/
export function encrypt(
Expand Down
1 change: 1 addition & 0 deletions packages/cryptopro-cades/src/api/findCertificateBySkid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getCertificates } from './../api';
/**
* Поиск в хранилищах сертификата.
* @param {string} subjectKeyId -идентификатор ключа субъекта.
* @throws {CryptoError} в случае ошибки.
* @returns {@Promise<Certificate | undefined>} сертификат.
*/
export async function findCertificateBySkid(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { openStore } from './openStore';
/**
* Поиск в хранилищах сертификата.
* @param {string} thumbprint -отпечаток искомого сертификата.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<Certificate | undefined>} сертификат.
*/
export async function findCertificateByThumbprint(
Expand Down
6 changes: 3 additions & 3 deletions packages/cryptopro-cades/src/api/getCertInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { canAsync } from './internal/canAsync';

/**
* Получение информации из Сертификата.
*
* @example
* @see https://docs.microsoft.com/en-us/windows/win32/seccrypto/certificate-getinfo
* @example
* const simpleName = await getCertInfo(cert, CAPICOM_CERT_INFO_TYPE.CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME);
*
* @param {ICertificate} cert - объект сертификата.
* @param {number|string} what - параметр, по которому находим и отдаем значение.
* @throws {CryptoError} в случае ошибки.
* @returns {string} запрошенная информация из сертификата.
* @see https://docs.microsoft.com/en-us/windows/win32/seccrypto/certificate-getinfo
*/
export async function getCertInfo(
cert: ICertificate,
Expand Down
22 changes: 13 additions & 9 deletions packages/cryptopro-cades/src/api/getCertificates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from '../constants';
import { Certificate } from '../Certificate';
import { ICertificate, ICertificates, IStore } from '../types';
import { outputDebug } from '../utils/outputDebug';
import { outputDebug } from '../utils';
import { CryptoError } from '../errors';

import { afterPluginLoaded } from './internal/afterPluginLoaded';
Expand All @@ -20,7 +20,7 @@ const certificatesCache = {};
/**
* Возвращает список сертификатов из указанного хранилища.
* @param {IStore} store Хранилище
* @param {string} storeName Наименование хранилища.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<Certificate[]>} .Список сертификатов.
*/
async function getCertificatesFromStore(store: IStore): Promise<Certificate[]> {
Expand Down Expand Up @@ -61,6 +61,7 @@ async function getCertificatesFromStore(store: IStore): Promise<Certificate[]> {
/**
* Получить сертификаты из USB токенов.
* @param {STORE_TYPE} storeType Тип хранилища ключей.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<Certificate[]>} .Список сертификатов из USB токенов.
*/
async function ReadCertificatesFromUsbToken(): Promise<Certificate[]> {
Expand All @@ -76,6 +77,7 @@ async function ReadCertificatesFromUsbToken(): Promise<Certificate[]> {
/**
* Получить сертификаты из реестра.
* @param {STORE_TYPE} storeType Тип хранилища ключей.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<Certificate[]>} .Список сертификатов из реестра.
*/
async function ReadCertificatesFromRegistry(): Promise<Certificate[]> {
Expand All @@ -97,6 +99,7 @@ async function ReadCertificatesFromRegistry(): Promise<Certificate[]> {
*
* @param {STORE_TYPE} storeType из какого хранилища требуется получить сертификаты (из токена, реестра, все...).
* @param {resetCache} resetCache перезапросить данные, игнорируя закэшированные данные.
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<Certificate[]>} .сертификаты.
*/
export function getCertificates(
Expand Down Expand Up @@ -126,16 +129,17 @@ export function getCertificates(
break;

case STORE_TYPE.ALL:
result = await ReadCertificatesFromRegistry();
logData.push({ storeType: 'registry', result });
const usbTokenCertificates = await ReadCertificatesFromUsbToken();
logData.push({ storeType: 'usb', result });
result = result.concat(usbTokenCertificates);
logData.push({ storeType: 'usb', usbTokenCertificates });
const certificatesFromRegistry = await ReadCertificatesFromRegistry();
logData.push({ storeType: 'registry', certificatesFromRegistry });

result = usbTokenCertificates.concat(certificatesFromRegistry);

result = result.filter(
(cert, index) =>
result.findIndex(
(_cert) => _cert.thumbprint === cert.thumbprint
) === index
result.findIndex((c) => c.thumbprint === cert.thumbprint) ===
index
);
break;

Expand Down
11 changes: 8 additions & 3 deletions packages/cryptopro-cades/src/api/getCryptoProviders.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CRYPTO_OBJECTS, CRYPTO_PROVIDERS } from '../constants';
import { CRYPTO_OBJECTS } from '../constants';
import { IAbout, ICryptoProvider, IVersion } from '../types';
import { outputDebug } from '../utils';
import pluginConfig from '../PluginConfig';

import { afterPluginLoaded } from './internal/afterPluginLoaded';
import { createObject } from './createObject';
Expand All @@ -12,7 +13,8 @@ let cryptoProvidersCache: ICryptoProvider[] | null;

/**
* Получить список криптопровайдеров.
* @returns {Promise<ICryptoProvider[]>} информация о типе, наименовании и версии криптопровайдеров
* @throws {CryptoError} в случае ошибки.
* @returns {Promise<ICryptoProvider[]>} Bнформация о типе, наименовании и версии криптопровайдеров.
*/
export function getCryptoProviders(
resetCache: boolean = false
Expand All @@ -28,7 +30,10 @@ export function getCryptoProviders(
const availableCryptoProviders: ICryptoProvider[] = [];
const logData = [];
try {
for (const { ProviderType, ProviderName } of CRYPTO_PROVIDERS) {
for (const {
ProviderType,
ProviderName,
} of pluginConfig.CheckCryptoProviders) {
try {
const cadesAbout: IAbout = await createObject(CRYPTO_OBJECTS.about);
const cspVersion: IVersion = await cadesAbout.CSPVersion(
Expand Down
2 changes: 1 addition & 1 deletion packages/cryptopro-cades/src/api/getLastError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { IAnyError, ICryptoError } from '../types';
* Возвращает строку с описанием ошибки из исключения, порождённого плагином.
* Для Firefox данный метод является единственным способом получения кода ошибки и её текстового описания от плагина.
* @param {Error} error - ошибка, по которой нужно получить информацию.
* @returns {Function} .
* @returns {Error | undefined} объект ошибки, если имеется.
*/
export function getLastError(
error: ICryptoError | Error | IAnyError
Expand Down
2 changes: 1 addition & 1 deletion packages/cryptopro-cades/src/api/getSystemInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
DEFAULT_CRYPTO_PROVIDER,
VIP_NET_CRYPTO_PROVIDER_TYPES,
} from '../constants';
import { outputDebug } from '../utils/outputDebug';
import { outputDebug } from '../utils';
import { IAbout, ISystemInfo } from '../types';

import { afterPluginLoaded } from './internal/afterPluginLoaded';
Expand Down
2 changes: 1 addition & 1 deletion packages/cryptopro-cades/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export { openStore } from './openStore';
export { getCertificates } from './getCertificates';
export { getCryptoProviders } from './getCryptoProviders';
export { getSystemInfo } from './getSystemInfo';
export { isValidSystemSetup } from './isValidSystemSetup';
export { checkIsValidSystemSetup } from './checkIsValidSystemSetup';
export { validateCertificate } from './validateCertificate';
export { findCertificateByThumbprint } from './findCertificateByThumbprint';
export { findCertificateBySkid } from './findCertificateBySkid';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isValidSystemSetup } from '../isValidSystemSetup';
import { checkIsValidSystemSetup } from '../checkIsValidSystemSetup';

import { CryptoError } from './../../errors';
import PluginConfig from './../../PluginConfig';
Expand Down Expand Up @@ -59,7 +59,7 @@ export function afterPluginLoaded(

// для исключения зацикливания, проверку валидности системы делаем единожды.
if (PluginConfig.CheckSystemSetup && !isAlreadyLoaded) {
await isValidSystemSetup();
await checkIsValidSystemSetup();
}

const callbackResult = cb.apply(null, args);
Expand Down
2 changes: 1 addition & 1 deletion packages/cryptopro-cades/src/api/internal/canAsync.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Проверка доступности асинхронной функциональности.
* @returns {boolean} .
* @returns {boolean} true, если нужно выполнять асинхронно.
*/
export function canAsync(): boolean {
// !!window.Promise || !!Iterator
Expand Down
Loading

0 comments on commit c346f4f

Please sign in to comment.