2.0.0
10
.editorconfig
Normal file
@ -0,0 +1,10 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{js, ts}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
51
.eslintrc.js
Normal file
@ -0,0 +1,51 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true
|
||||
},
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'prettier/@typescript-eslint',
|
||||
'plugin:prettier/recommended'
|
||||
],
|
||||
globals: {
|
||||
Atomics: 'readonly',
|
||||
SharedArrayBuffer: 'readonly'
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: [
|
||||
'@typescript-eslint'
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/no-inferrable-types': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/ban-ts-ignore': 'off',
|
||||
'@typescript-eslint/camelcase': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off'
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.test.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/explicit-function-return-type': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['./types/**/*'],
|
||||
rules: {
|
||||
'no-var': 'off'
|
||||
}
|
||||
}
|
||||
],
|
||||
ignorePatterns: [
|
||||
'*.js',
|
||||
'lib/**/*',
|
||||
'dist/**/*',
|
||||
'coverage/**/*',
|
||||
'examples/**/*'
|
||||
]
|
||||
};
|
6
.gitignore
vendored
@ -1,2 +1,6 @@
|
||||
.idea
|
||||
node_modules/
|
||||
node_modules/
|
||||
lib/
|
||||
dist/
|
||||
package/
|
||||
coverage/
|
||||
|
11
.npmignore
Normal file
@ -0,0 +1,11 @@
|
||||
# see what'll be included with `npm pack --dry-run`
|
||||
|
||||
/examples
|
||||
/src
|
||||
/types
|
||||
/package
|
||||
|
||||
/tsconfig*
|
||||
/*.js
|
||||
/*.gif
|
||||
/.*
|
8
.prettierrc.js
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
semi: true,
|
||||
trailingComma: 'all',
|
||||
singleQuote: true,
|
||||
printWidth: 120,
|
||||
tabWidth: 2,
|
||||
arrowParens: 'always',
|
||||
};
|
10
CHANGELOG.md
@ -1,3 +1,9 @@
|
||||
2.0.0 / 2020-03-28
|
||||
==================
|
||||
|
||||
* Улучшение: Проект переписан с использованием Typescript
|
||||
* Улучшение: В Readme обновлены примеры, документация и добавлен [список изменений](README.md#Миграция-с-версии-1-на-2) для миграции с 1 на 2 версию
|
||||
|
||||
1.1.2 / 2019-12-07
|
||||
==================
|
||||
|
||||
@ -37,7 +43,7 @@
|
||||
1.0.7 / 2017-01-30
|
||||
==================
|
||||
|
||||
* Улучшение: Указание хэша сертификата при ошибке доступа к нему
|
||||
* Улучшение: Указание отпечатка сертификата при ошибке доступа к нему
|
||||
|
||||
1.0.6 / 2017-01-30
|
||||
==================
|
||||
@ -62,4 +68,4 @@
|
||||
1.0.2 / 2017-01-16
|
||||
==================
|
||||
|
||||
* Улучшение: Добавлена возможность подключать модуль напрямую из папки src/ для приложений, собираемых webpack'ом
|
||||
* Улучшение: Добавлена возможность подключать модуль напрямую из папки src/ для приложений, собираемых webpack'ом
|
||||
|
333
README.md
Executable file → Normal file
@ -1,40 +1,304 @@
|
||||
# CryptoPro
|
||||
Единое, асинхронное API для взаимодействия с КриптоПРО ЭЦП Browser Plug-In (IE8+)
|
||||
[![NPM version][npm-version-image]][npm-url]
|
||||
[![NPM downloads][npm-downloads-image]][downloads-url]
|
||||
|
||||
## Поддерживаемые браузеры
|
||||
- [Google Chrome](https://www.google.ru/chrome/browser/desktop/) (v45+) с расширением [CryptoPro Extension for CAdES Browser Plug-in](https://chrome.google.com/webstore/detail/cryptopro-extension-for-c/iifchhfnnmpdbibifmljnfjhpififfog?utm_source=chrome-app-launcher-info-dialog)
|
||||
- [Opera](https://www.google.ru/chrome/browser/desktop/) (v40+) с расширением [CryptoPro Extension for CAdES Browser Plug-in](https://addons.opera.com/en/extensions/details/cryptopro-extension-for-cades-browser-plug-in/)
|
||||
- [Mozilla Firefox](https://www.mozilla.org/ru/firefox/new/) (v43+). Начиная с версии 52, с [расширением](https://www.cryptopro.ru/sites/default/files/products/cades/extensions/cryptopro_extension_for_cades_browser_plug_in-1.1.1-an+fx-windows.xpi).
|
||||
- [Internet Explorer](http://windows.microsoft.com/ru-ru/internet-explorer/download-ie) (v8+).
|
||||
- [cryptoPro](#cryptopro)
|
||||
- [Зачем мне этот пакет?](#Зачем-мне-этот-пакет?)
|
||||
- [Установка](#Установка)
|
||||
- [API](#API)
|
||||
- [Методы объекта cryptoPro](#Методы-объекта-cryptoPro)
|
||||
- [Методы объекта сертификата](#Методы-объекта-сертификата)
|
||||
- [Поддерживаемые браузеры](#Поддерживаемые-браузеры)
|
||||
- [Поддерживаемые СКЗИ](#Поддерживаемые-СКЗИ)
|
||||
- [Примеры](#Примеры)
|
||||
- [Тэг script (UMD)](#Тэг-script-(UMD))
|
||||
- [Angular (ES Modules + Typescript)](#Angular-(ES-Modules-+-Typescript))
|
||||
- [React (ES Modules + JavaScript)](#React-(ES-Modules-+-JavaScript))
|
||||
- [Миграция с версии 1 на 2](#Миграция-с-версии-1-на-2)
|
||||
- [Тем, кто хочет помочь](#Тем,-кто-хочет-помочь)
|
||||
- [Запуск режима разработки](#Запуск-режима-разработки)
|
||||
- [Запуск тестов](#Запуск-тестов)
|
||||
- [Проверка работы примеров с React и Angular](#Проверка-работы-примеров-с-React-и-Angular)
|
||||
- [Проверка пакета перед публикацией в NPM](#Проверка-пакета-перед-публикацией-в-NPM)
|
||||
- [Полезная информация](#Полезная-информация)
|
||||
- [Установка КриптоПРО CSP в Linux / OSX](#Установка-КриптоПРО-CSP-в-Linux-/-OSX)
|
||||
- [Установка КриптоПРО ЭЦП browser plug-in в Linux](#Установка-КриптоПРО-ЭЦП-browser-plugin-в-Linux)
|
||||
- [Настройка плагина для Firefox (до версии 52)](#Настройка-плагина-для-Firefox-(до-версии-52))
|
||||
- [Установка сертификатов в Linux](#Установка-сертификатов-в-Linux)
|
||||
- [Лицензия](#Лицензия)
|
||||
|
||||
Список необходимых полифиллов (подключаются самостоятельно):
|
||||
- Promise
|
||||
- EventTarget.addEventListener
|
||||
- Array.prototype.forEach
|
||||
- Array.prototype.map
|
||||
# cryptoPro
|
||||
Единое, асинхронное API для взаимодействия с КриптоПРО ЭЦП Browser Plug-In с поддержкой IE9+
|
||||
|
||||
## Установка и настройка
|
||||
### NPM
|
||||
## Зачем мне этот пакет?
|
||||
КриптоПРО ЭЦП Browser Plug-In доступен в разных браузерах в двух версиях.
|
||||
Асинхронной (в современных браузерах) и синхронной (в браузерах постарше).
|
||||
С помощью этого пакета можно не писать реализацию под каждую версию плагина дважды.
|
||||
И вместо [этого](http://cpdn.cryptopro.ru/content/cades/plugin-samples-sign.html)
|
||||
и [этого](http://cpdn.cryptopro.ru/content/cades/plugin-samples-sign-cades-bes-async.html)
|
||||
написать это (UMD):
|
||||
|
||||
![crypto-pro-umd.gif](crypto-pro-umd.gif)
|
||||
|
||||
или это (ES Modules):
|
||||
|
||||
![crypto-pro-esm.gif](crypto-pro-esm.gif)
|
||||
|
||||
## Установка
|
||||
Для NPM:
|
||||
```bash
|
||||
npm install crypto-pro
|
||||
```
|
||||
|
||||
### Bower
|
||||
Для yarn:
|
||||
```bash
|
||||
yarn add crypto-pro
|
||||
```
|
||||
|
||||
Для Bower:
|
||||
```bash
|
||||
bower install crypto-pro
|
||||
```
|
||||
|
||||
Для корректной работы используйте:
|
||||
1. [КриптоПРО CSP](https://www.cryptopro.ru/products/csp/downloads) (v3.6+) *рекомендуется использование только сертифицированных версий*. Инструкция по установке:
|
||||
## API
|
||||
При использовании пакета как UMD модуля из папки `dist/`:
|
||||
```javascript
|
||||
window.cryptoPro.getUserCertificates()
|
||||
.then(function (certificates) {
|
||||
//...
|
||||
})
|
||||
.catch(function (error) {
|
||||
//...
|
||||
});
|
||||
```
|
||||
|
||||
При использовании пакета в режиме ES модулей с typescript или javascript из папки `lib/`:
|
||||
```typescript
|
||||
import { getUserCertificates, Certificate } from 'crypto-pro';
|
||||
|
||||
(async () => {
|
||||
let certificates: Certificate[];
|
||||
|
||||
try {
|
||||
certificates = await getUserCertificates();
|
||||
} catch(error) {
|
||||
// ...
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
### Методы объекта cryptoPro
|
||||
- [getUserCertificates](src/api/getUserCertificates.ts) - возвращает список [сертификатов](#методы-объекта-сертификата), доступных пользователю в системе
|
||||
- [getCertificate](src/api/getCertificate.ts) - возвращает [сертификат](#методы-объекта-сертификата) по отпечатку
|
||||
- [createSignature](src/api/createSignature.ts) - создает подпись данных
|
||||
- [getSystemInfo](src/api/getSystemInfo.ts) - возвращает информацию о CSP и плагине
|
||||
- [isValidSystemSetup](src/api/isValidSystemSetup.ts) - возвращает флаг корректности настроек ЭП на машине
|
||||
|
||||
### Методы объекта сертификата
|
||||
[Сертификат](src/api/certificate/certificate.ts) предоставляет следущее API:
|
||||
- [isValid](src/api/certificate/isValid.ts) - возвращает флаг действительности сертификата
|
||||
- [getCadesProp](src/api/certificate/getCadesProp.ts) - возвращает указанное внутренее свойство у сертификата в формате Cades
|
||||
- [exportBase64](src/api/certificate/exportBase64.ts) - возвращает сертификат в формате base64
|
||||
- [getAlgorithm](src/api/certificate/getAlgorithm.ts) - возвращает информацию об алгоритме сертификата
|
||||
- [getOwnerInfo](src/api/certificate/getInfo.ts) - возвращает расшифрованную информацию о владельце сертификата
|
||||
- [getIssuerInfo](src/api/certificate/getInfo.ts) - возвращает расшифрованную информацию об издателе сертификата
|
||||
- [getExtendedKeyUsage](src/api/certificate/getExtendedKeyUsage.ts) - возвращает ОИД'ы сертификата
|
||||
- [getDecodedExtendedKeyUsage](src/api/certificate/getDecodedExtendedKeyUsage.ts) - возвращает расшифрованные ОИД'ы
|
||||
- [hasExtendedKeyUsage](src/api/certificate/hasExtendedKeyUsage.ts) - проверяет наличие ОИД'а (ОИД'ов) у сертификата
|
||||
|
||||
## Поддерживаемые браузеры
|
||||
- [Google Chrome](https://www.chromium.org/getting-involved/download-chromium#TOC-Downloading-old-builds-of-Chrome-Chromium) (v45+) с расширением [CryptoPro Extension for CAdES Browser Plug-in](https://chrome.google.com/webstore/detail/cryptopro-extension-for-c/iifchhfnnmpdbibifmljnfjhpififfog?utm_source=chrome-app-launcher-info-dialog)
|
||||
- [Opera](http://get.opera.com/ftp/pub/opera/desktop/) (v40+) с расширением [CryptoPro Extension for CAdES Browser Plug-in](https://addons.opera.com/en/extensions/details/cryptopro-extension-for-cades-browser-plug-in/)
|
||||
- [Mozilla Firefox](https://ftp.mozilla.org/pub/firefox/releases/) (v43+). Начиная с версии 52, с [расширением](https://www.cryptopro.ru/sites/default/files/products/cades/extensions/cryptopro_extension_for_cades_browser_plug_in-1.1.1-an+fx-windows.xpi).
|
||||
- [Internet Explorer](https://www.microsoft.com/ru-ru/download/details.aspx?id=43374) (v9+).
|
||||
|
||||
Список требуемых полифиллов для старых браузеров (если необходимы, подключаются самостоятельно):
|
||||
- Promise
|
||||
- Array.prototype.find
|
||||
|
||||
## Поддерживаемые СКЗИ
|
||||
[КриптоПРО CSP](https://www.cryptopro.ru/products/csp/downloads) (v4.0+) *рекомендуется использование только сертифицированных версий*. Инструкция по установке:
|
||||
- [Linux / OSX](#install_csp_linux)
|
||||
- (в Windows следуйте указаниям программы-установщика)
|
||||
1. [КриптоПРО ЭЦП browser plug-in](https://www.cryptopro.ru/products/cades/plugin) (v1.5+). Инструкция по установке:
|
||||
- [Linux](#install_plugin_linux)
|
||||
- (в Windows и OSX следуйте указаниям программы-установщика)
|
||||
|
||||
Затем установите необходимые сертификаты в систему. [Инструкция](#install_cert_linux) для Linux / OSX.
|
||||
[КриптоПРО ЭЦП browser plug-in](https://www.cryptopro.ru/products/cades/plugin) (v2.0.12438+).
|
||||
|
||||
### <a name="install_csp_linux"></a> Установка КриптоПРО CSP в Linux / OSX
|
||||
[Инструкция](#install_plugin_linux) по установке плагина в Linux. В Windows и OSX следуйте указаниям программы-установщика.
|
||||
|
||||
[Инструкция](#install_cert_linux) по установке сертификатов в систему для Linux / OSX.
|
||||
|
||||
## Примеры
|
||||
Для их запуска необходим NodeJS LTS.
|
||||
|
||||
### Тэг script (UMD)
|
||||
```bash
|
||||
cd examples/script-tag
|
||||
npm i
|
||||
npm start
|
||||
```
|
||||
|
||||
### Angular (ES Modules + Typescript)
|
||||
```bash
|
||||
cd examples/angular
|
||||
npm i
|
||||
```
|
||||
|
||||
Запуск в режиме разработки:
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
Запуск в продакшн режиме:
|
||||
```bash
|
||||
npm run build
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### React (ES Modules + JavaScript)
|
||||
```bash
|
||||
cd examples/react
|
||||
npm i
|
||||
```
|
||||
|
||||
Запуск в режиме разработки:
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
Запуск в продакшн режиме:
|
||||
```bash
|
||||
npm run build
|
||||
npm run serve
|
||||
```
|
||||
|
||||
## Миграция с версии 1 на 2
|
||||
Внесены следующие изменения:
|
||||
- Пакет собран в форматах:
|
||||
- UMD, в папке `dist/`, для подключения через тэг script. Объект `window.cryptoPro` доступен глобально.
|
||||
- ES Modules, в папке `lib/`, для использования с разными системами сборки.
|
||||
Методы API импортируются напрямую из npm пакета.
|
||||
- В UMD версии переименован глобальный объект с `window.CryptoPro` на `window.cryptoPro`
|
||||
- Переименованы общие методы:
|
||||
- `getCertsList` -> `getUserCertificates`
|
||||
- `getCert` -> `getCertificate`
|
||||
- `signData` -> `createSignature`
|
||||
- `isValidEDSSettings`, `isValidCSPVersion`, `isValidCadesVersion` -> `isValidSystemSetup`
|
||||
- Убран метод `signDataXML`
|
||||
- Переименованы методы сертификата:
|
||||
- `getProp` -> `getCadesProp`
|
||||
- Результат методов сертификата `getOwnerInfo` и `getIssuerInfo`
|
||||
изменился с `{ descr, title, translated }` на `{ description, title, isTranslated }`
|
||||
- Принципиальная реализация методов, обращающихся к Крипто ПРО не изменилась.
|
||||
Получение сертификатов, создание подписи, проверка корректности настроек работают по-прежнему.
|
||||
- Убрана поддержка IE8 (Крипто ПРО его больше не поддерживает)
|
||||
- Убрана поддержка КриптоПРО CSP версий ниже 4.0
|
||||
- Убрана поддержка КриптоПРО ЭЦП browser plug-in версий ниже 2.0
|
||||
- Доработана обработка ошибок, выбрасываемых из Крипто ПРО
|
||||
- При написании кода будут работать автодополнения и подсказки
|
||||
- Исправлена [проблема](https://github.com/vgoma/crypto-pro/issues/11) работы библиотеки с UglifyJs
|
||||
- Методы API доступны напрямую:
|
||||
|
||||
В версии 1:
|
||||
```javascript
|
||||
window.CryptoPro.call('getSystemInfo');
|
||||
```
|
||||
|
||||
В версии 2 (UMD):
|
||||
```javascript
|
||||
window.cryptoPro.getSystemInfo();
|
||||
```
|
||||
|
||||
В версии 2 (ES Modules):
|
||||
```javascript
|
||||
import { getSystemInfo } from 'crypto-pro';
|
||||
|
||||
getSystemInfo();
|
||||
```
|
||||
|
||||
# Тем, кто хочет помочь
|
||||
Буду благодарен за расширение/улучшение/доработку API.
|
||||
Вам будут полезны [примеры](http://cpdn.cryptopro.ru/?url=/content/cades/plugin-samples-sign.html),
|
||||
предоставляемые Крипто ПРО.
|
||||
|
||||
## Запуск режима разработки
|
||||
Устанавливаем зависимости:
|
||||
```bash
|
||||
npm i
|
||||
```
|
||||
|
||||
Во время работы с кодом необходим запущенный сборщик:
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
И пример, на котором можно тестировать изменения.
|
||||
Удобнее всего тестировать на примере с тэгом script, тк он отвязан от фреймворков
|
||||
и использует сборку в формате UMD из папки `dist/`, постоянно обновляемую пока работает
|
||||
сборщик. Запускаем его таким образом:
|
||||
```bash
|
||||
cd examples/script-tag
|
||||
npm i
|
||||
npm link ../../
|
||||
npm start
|
||||
```
|
||||
> После выполнения `npm link ../../` в директории `examples/script-tag/node_modules` папка `crypto-pro` станет ярлыком,
|
||||
> указывающим на папку содержащую локально собранный пакет.
|
||||
|
||||
## Запуск тестов
|
||||
Тесты написаны с использованием [Jest](https://jestjs.io/docs/en/configuration#testpathignorepatterns-arraystring):
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
## Проверка работы примеров с React и Angular
|
||||
React и Angular используют версию сборки пакета в формате ES модулей из директории `lib/`.
|
||||
Для их запуска необходимо сначала собрать пакет выполнив:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
После этого из папки `examples/angular` или `examples/react` залинковать пакет:
|
||||
```bash
|
||||
cd examples/angular
|
||||
npm i
|
||||
npm link ../../
|
||||
```
|
||||
|
||||
И запустить пример в одном из двух режимов. В режиме разработки:
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
или в режиме продакшн:
|
||||
```bash
|
||||
npm run build
|
||||
npm run serve
|
||||
```
|
||||
|
||||
## Проверка пакета перед публикацией в NPM
|
||||
Необходимо протестировать работу в заявленных браузерах, сделав это на локально запакованной версии пакета.
|
||||
Для этого собираем пакет:
|
||||
```bash
|
||||
npm run package
|
||||
mv package ..
|
||||
```
|
||||
> Важно переместить папку `package` куда-нибудь выше для избежания конфликтов при линковке с текущим `package.json`.
|
||||
|
||||
Переходим в любую директорию с примером и создаем там ссылку на только что собранный пакет:
|
||||
```bash
|
||||
cd examples/script-tag
|
||||
npm link ../../../package
|
||||
```
|
||||
|
||||
Проверяем работу примеров в режимах разработки и продакшн.
|
||||
|
||||
После завершения экспериментов можно удалить глобальную ссылку из директории `../../../package` таким образом:
|
||||
```bash
|
||||
cd ../../../package
|
||||
npm unlink
|
||||
```
|
||||
|
||||
# Полезная информация
|
||||
## Установка КриптоПРО CSP в Linux / OSX
|
||||
> Процесс установки в OSX незначительно отличается от Linux, поэтому описание приведено на примере дистрибутива семейства Debian (x64).
|
||||
|
||||
Некоторые команды могут потребовать запуска с `sudo`.
|
||||
@ -63,7 +327,7 @@ dpkg -i linux-amd64_deb/cprocsp-rdr-gui-gtk-64_4.0.0-4_amd64.deb
|
||||
|
||||
[Дополнительная информация по установке](https://www.cryptopro.ru/faq/gde-vzyat-dokumentatsiyu-po-ustanovke-kakie-pakety-stavit)
|
||||
|
||||
### <a name="install_plugin_linux"></a> Установка КриптоПРО ЭЦП browser plug-in в Linux
|
||||
## Установка КриптоПРО ЭЦП browser plugin в Linux
|
||||
Загрузите [КриптоПРО ЭЦП browser plug-in](https://www.cryptopro.ru/products/cades/plugin) и распакуйте его:
|
||||
```bash
|
||||
mkdir cades_linux_amd64
|
||||
@ -92,7 +356,7 @@ ls -la /opt/cprocsp/lib/amd64 | grep libnpcades
|
||||
-rwxr-xr-x 1 root root 2727236 Июн 8 14:33 libnpcades.so.2.0.0
|
||||
```
|
||||
|
||||
#### Настройка плагина для Firefox (до версии 52):
|
||||
### Настройка плагина для Firefox (до версии 52)
|
||||
> После настройки плагина на страницах, запрашивающих работу с ЭП в панели навигации, рядом с url будет кнопка,
|
||||
позволяющая "разрешить и запомнить" использование установленного плагина.
|
||||
|
||||
@ -107,7 +371,7 @@ ldd libnpcades.so
|
||||
```
|
||||
Перезапустите Firefox, и убедитесь в наличии CryptoPRO Cades plugin (см. Menu -> Addons).
|
||||
|
||||
### <a name="install_cert_linux"></a> Установка сертификатов в Linux
|
||||
## Установка сертификатов в Linux
|
||||
> В OSX процесс схож с Linux.
|
||||
|
||||
Подключите USB носитель с ключевыми контейнерами и проверьте результат команды:
|
||||
@ -170,17 +434,10 @@ ldd libnpcades.so
|
||||
/opt/cprocsp/bin/amd64/certmgr -list -store uMy
|
||||
```
|
||||
|
||||
## API
|
||||
Пример работы с API лежит в папке `example`.
|
||||
# Лицензия
|
||||
MIT
|
||||
|
||||
``` js
|
||||
window.CryptoPro.call('getCertsList').then(function (certList) {
|
||||
console.log(certList);
|
||||
});
|
||||
```
|
||||
|
||||
### Доступные методы
|
||||
Список доступных методов можно посмотреть в файле `src/api.js`.
|
||||
|
||||
### License
|
||||
Licensed as MIT. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
|
||||
[npm-url]: https://npmjs.org/package/crypto-pro
|
||||
[npm-version-image]: http://img.shields.io/npm/v/crypto-pro.svg?style=flat
|
||||
[npm-downloads-image]: http://img.shields.io/npm/dm/crypto-pro.svg?style=flat
|
||||
[downloads-url]: https://npmcharts.com/compare/crypto-pro?minimal=true
|
||||
|
16
bower.json
@ -1,24 +1,30 @@
|
||||
{
|
||||
"name": "crypto-pro",
|
||||
"description": "API для взаимодействия с КриптоПро",
|
||||
"main": "dist/crypto-pro.js",
|
||||
"main": "./lib/crypto-pro.js",
|
||||
"authors": [
|
||||
"vgoma <vgoma@yandex.ru>"
|
||||
],
|
||||
"license": "ISC",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"crypto",
|
||||
"cryptopro",
|
||||
"crypto-pro",
|
||||
"cades",
|
||||
"КриптоПро"
|
||||
"КриптоПро",
|
||||
"Крипто ПРО"
|
||||
],
|
||||
"homepage": "https://github.com/vgoma/crypto-pro",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"/*.js",
|
||||
"/*.gif",
|
||||
"/tsconfig*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
"examples",
|
||||
"src",
|
||||
"types",
|
||||
"package"
|
||||
]
|
||||
}
|
||||
|
BIN
crypto-pro-esm.gif
Normal file
After Width: | Height: | Size: 954 KiB |
BIN
crypto-pro-umd.gif
Normal file
After Width: | Height: | Size: 740 KiB |
18
definition-header.js
Normal file
@ -0,0 +1,18 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const tsConfig = require(`./${process.env.TS_CONFIG}`);
|
||||
const packageJson = require('./package.json');
|
||||
const typingsPath = path.resolve(__dirname, tsConfig.compilerOptions.outDir, `${packageJson.name}.d.ts`);
|
||||
const typings = fs.readFileSync(typingsPath, 'utf8');
|
||||
|
||||
let header = [
|
||||
`// Type definitions for ${packageJson.name} ${packageJson.version}`,
|
||||
`// Project: ${packageJson.name}`,
|
||||
`// Definitions by: ${packageJson.author.name} ${packageJson.author.url}`
|
||||
].join('\n');
|
||||
|
||||
if (tsConfig.compilerOptions.target === 'es5') {
|
||||
header += '\n\nexport as namespace cryptoPro;';
|
||||
}
|
||||
|
||||
fs.writeFileSync(typingsPath, `${header}\n\n${typings}`);
|
1071
dist/1.crypto-pro.js
vendored
1
dist/1.crypto-pro.js.map
vendored
1047
dist/2.crypto-pro.js
vendored
1
dist/2.crypto-pro.js.map
vendored
2557
dist/crypto-pro.js
vendored
1
dist/crypto-pro.js.map
vendored
@ -1,26 +0,0 @@
|
||||
;(function () {
|
||||
'use strict';
|
||||
|
||||
var $certs = document.querySelector('#certList');
|
||||
|
||||
/**
|
||||
* Пример получения списка сертификатов
|
||||
* */
|
||||
window.CryptoPro.call('getCertsList').then(function (list) {
|
||||
list.forEach(function (cert) {
|
||||
var $certOption = document.createElement('option');
|
||||
|
||||
if (typeof $certOption.textContent !== 'undefined') {
|
||||
$certOption.textContent = cert.label;
|
||||
} else {
|
||||
$certOption.innerText = cert.label;
|
||||
}
|
||||
|
||||
$certOption.value = cert.thumbprint;
|
||||
|
||||
$certs.appendChild($certOption);
|
||||
});
|
||||
}, function (error) {
|
||||
console.error(error);
|
||||
});
|
||||
}());
|
@ -1,24 +0,0 @@
|
||||
;(function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Пример создания подписи данных, сгенерированных по ГОСТ Р 34.11-94
|
||||
* https://ru.wikipedia.org/wiki/%D0%93%D0%9E%D0%A1%D0%A2_%D0%A0_34.11-94
|
||||
* */
|
||||
var $certs = document.querySelector('#certList'),
|
||||
$createSignBtn = document.querySelector('#createSign'),
|
||||
$signatureCnt = document.querySelector('#createdSign'),
|
||||
|
||||
// Вычислинный hash по ГОСТ Р 34.11-94 для строки: "abc"
|
||||
hash = 'b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c',
|
||||
|
||||
hashBase64 = window.btoa(hash);
|
||||
|
||||
$createSignBtn.addEventListener('click', function () {
|
||||
var thumbprint = $certs.value;
|
||||
|
||||
window.CryptoPro.call('signData', thumbprint, hashBase64).then(function (signature) {
|
||||
$signatureCnt.value = signature;
|
||||
});
|
||||
});
|
||||
}());
|
@ -1,32 +0,0 @@
|
||||
!window.addEventListener && (function (WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) {
|
||||
WindowPrototype[addEventListener] = DocumentPrototype[addEventListener] = ElementPrototype[addEventListener] = function (type, listener) {
|
||||
var target = this;
|
||||
|
||||
registry.unshift([target, type, listener, function (event) {
|
||||
event.currentTarget = target;
|
||||
event.preventDefault = function () {
|
||||
event.returnValue = false
|
||||
};
|
||||
event.stopPropagation = function () {
|
||||
event.cancelBubble = true
|
||||
};
|
||||
event.target = event.srcElement || target;
|
||||
|
||||
listener.call(target, event);
|
||||
}]);
|
||||
|
||||
this.attachEvent("on" + type, registry[0][3]);
|
||||
};
|
||||
|
||||
WindowPrototype[removeEventListener] = DocumentPrototype[removeEventListener] = ElementPrototype[removeEventListener] = function (type, listener) {
|
||||
for (var index = 0, register; register = registry[index]; ++index) {
|
||||
if (register[0] == this && register[1] == type && register[2] == listener) {
|
||||
return this.detachEvent("on" + type, registry.splice(index, 1)[0][3]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
WindowPrototype[dispatchEvent] = DocumentPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = function (eventObject) {
|
||||
return this.fireEvent("on" + eventObject.type, eventObject);
|
||||
};
|
||||
})(Window.prototype, HTMLDocument.prototype, Element.prototype, "addEventListener", "removeEventListener", "dispatchEvent", []);
|
@ -1,59 +0,0 @@
|
||||
// Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.18
|
||||
// Ссылка (en): http://es5.github.io/#x15.4.4.18
|
||||
// Ссылка (ru): http://es5.javascript.ru/x15.4.html#x15.4.4.18
|
||||
if (!Array.prototype.forEach) {
|
||||
|
||||
Array.prototype.forEach = function (callback, thisArg) {
|
||||
|
||||
var T, k;
|
||||
|
||||
if (this == null) {
|
||||
throw new TypeError(' this is null or not defined');
|
||||
}
|
||||
|
||||
// 1. Положим O равным результату вызова ToObject passing the |this| value as the argument.
|
||||
var O = Object(this);
|
||||
|
||||
// 2. Положим lenValue равным результату вызова внутреннего метода Get объекта O с аргументом "length".
|
||||
// 3. Положим len равным ToUint32(lenValue).
|
||||
var len = O.length >>> 0;
|
||||
|
||||
// 4. Если IsCallable(callback) равен false, выкинем исключение TypeError.
|
||||
// Смотрите: http://es5.github.com/#x9.11
|
||||
if (typeof callback !== 'function') {
|
||||
throw new TypeError(callback + ' is not a function');
|
||||
}
|
||||
|
||||
// 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
|
||||
if (arguments.length > 1) {
|
||||
T = thisArg;
|
||||
}
|
||||
|
||||
// 6. Положим k равным 0
|
||||
k = 0;
|
||||
|
||||
// 7. Пока k < len, будем повторять
|
||||
while (k < len) {
|
||||
|
||||
var kValue;
|
||||
|
||||
// a. Положим Pk равным ToString(k).
|
||||
// Это неявное преобразование для левостороннего операнда в операторе in
|
||||
// b. Положим kPresent равным результату вызова внутреннего метода HasProperty объекта O с аргументом Pk.
|
||||
// Этот шаг может быть объединён с шагом c
|
||||
// c. Если kPresent равен true, то
|
||||
if (k in O) {
|
||||
|
||||
// i. Положим kValue равным результату вызова внутреннего метода Get объекта O с аргументом Pk.
|
||||
kValue = O[k];
|
||||
|
||||
// ii. Вызовем внутренний метод Call функции callback с объектом T в качестве значения this и
|
||||
// списком аргументов, содержащим kValue, k и O.
|
||||
callback.call(T, kValue, k, O);
|
||||
}
|
||||
// d. Увеличим k на 1.
|
||||
k++;
|
||||
}
|
||||
// 8. Вернём undefined.
|
||||
};
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
// Шаги алгоритма ECMA-262, 5-е издание, 15.4.4.19
|
||||
// Ссылка (en): http://es5.github.com/#x15.4.4.19
|
||||
// Ссылка (ru): http://es5.javascript.ru/x15.4.html#x15.4.4.19
|
||||
if (!Array.prototype.map) {
|
||||
|
||||
Array.prototype.map = function(callback, thisArg) {
|
||||
|
||||
var T, A, k;
|
||||
|
||||
if (this == null) {
|
||||
throw new TypeError(' this is null or not defined');
|
||||
}
|
||||
|
||||
// 1. Положим O равным результату вызова ToObject с передачей ему
|
||||
// значения |this| в качестве аргумента.
|
||||
var O = Object(this);
|
||||
|
||||
// 2. Положим lenValue равным результату вызова внутреннего метода Get
|
||||
// объекта O с аргументом "length".
|
||||
// 3. Положим len равным ToUint32(lenValue).
|
||||
var len = O.length >>> 0;
|
||||
|
||||
// 4. Если вызов IsCallable(callback) равен false, выкидываем исключение TypeError.
|
||||
// Смотрите (en): http://es5.github.com/#x9.11
|
||||
// Смотрите (ru): http://es5.javascript.ru/x9.html#x9.11
|
||||
if (typeof callback !== 'function') {
|
||||
throw new TypeError(callback + ' is not a function');
|
||||
}
|
||||
|
||||
// 5. Если thisArg присутствует, положим T равным thisArg; иначе положим T равным undefined.
|
||||
if (arguments.length > 1) {
|
||||
T = thisArg;
|
||||
}
|
||||
|
||||
// 6. Положим A равным новому масиву, как если бы он был создан выражением new Array(len),
|
||||
// где Array является стандартным встроенным конструктором с этим именем,
|
||||
// а len является значением len.
|
||||
A = new Array(len);
|
||||
|
||||
// 7. Положим k равным 0
|
||||
k = 0;
|
||||
|
||||
// 8. Пока k < len, будем повторять
|
||||
while (k < len) {
|
||||
|
||||
var kValue, mappedValue;
|
||||
|
||||
// a. Положим Pk равным ToString(k).
|
||||
// Это неявное преобразование для левостороннего операнда в операторе in
|
||||
// b. Положим kPresent равным результату вызова внутреннего метода HasProperty
|
||||
// объекта O с аргументом Pk.
|
||||
// Этот шаг может быть объединён с шагом c
|
||||
// c. Если kPresent равен true, то
|
||||
if (k in O) {
|
||||
|
||||
// i. Положим kValue равным результату вызова внутреннего метода Get
|
||||
// объекта O с аргументом Pk.
|
||||
kValue = O[k];
|
||||
|
||||
// ii. Положим mappedValue равным результату вызова внутреннего метода Call
|
||||
// функции callback со значением T в качестве значения this и списком
|
||||
// аргументов, содержащим kValue, k и O.
|
||||
mappedValue = callback.call(T, kValue, k, O);
|
||||
|
||||
// iii. Вызовем внутренний метод DefineOwnProperty объекта A с аргументами
|
||||
// Pk, Описатель Свойства
|
||||
// { Value: mappedValue,
|
||||
// Writable: true,
|
||||
// Enumerable: true,
|
||||
// Configurable: true }
|
||||
// и false.
|
||||
|
||||
// В браузерах, поддерживающих Object.defineProperty, используем следующий код:
|
||||
// Object.defineProperty(A, k, {
|
||||
// value: mappedValue,
|
||||
// writable: true,
|
||||
// enumerable: true,
|
||||
// configurable: true
|
||||
// });
|
||||
|
||||
// Для лучшей поддержки браузерами, используем следующий код:
|
||||
A[k] = mappedValue;
|
||||
}
|
||||
// d. Увеличим k на 1.
|
||||
k++;
|
||||
}
|
||||
|
||||
// 9. Вернём A.
|
||||
return A;
|
||||
};
|
||||
}
|
13
examples/angular/.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
46
examples/angular/.gitignore
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
/bazel-out
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# profiling files
|
||||
chrome-profiler-events*.json
|
||||
speed-measure-plugin*.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
27
examples/angular/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Angular
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.0.7.
|
||||
|
||||
## Development server
|
||||
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||
|
||||
## Further help
|
||||
|
||||
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
|
124
examples/angular/angular.json
Normal file
@ -0,0 +1,124 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"angular": {
|
||||
"projectType": "application",
|
||||
"schematics": {},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/angular",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"aot": true,
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "angular:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "angular:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "angular:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"tsconfig.app.json",
|
||||
"tsconfig.spec.json",
|
||||
"e2e/tsconfig.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "angular:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "angular:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
"defaultProject": "angular"
|
||||
}
|
12
examples/angular/browserslist
Normal file
@ -0,0 +1,12 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
> 0.5%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
32
examples/angular/e2e/protractor.conf.js
Normal file
@ -0,0 +1,32 @@
|
||||
// @ts-check
|
||||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
/**
|
||||
* @type { import("protractor").Config }
|
||||
*/
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./src/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
browserName: 'chrome'
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:4200/',
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
showColors: true,
|
||||
defaultTimeoutInterval: 30000,
|
||||
print: function() {}
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: require('path').join(__dirname, './tsconfig.json')
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
||||
};
|
23
examples/angular/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { AppPage } from './app.po';
|
||||
import { browser, logging } from 'protractor';
|
||||
|
||||
describe('workspace-project App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
});
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getTitleText()).toEqual('angular app is running!');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// Assert that there are no errors emitted from the browser
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
expect(logs).not.toContain(jasmine.objectContaining({
|
||||
level: logging.Level.SEVERE,
|
||||
} as logging.Entry));
|
||||
});
|
||||
});
|
11
examples/angular/e2e/src/app.po.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class AppPage {
|
||||
navigateTo(): Promise<unknown> {
|
||||
return browser.get(browser.baseUrl) as Promise<unknown>;
|
||||
}
|
||||
|
||||
getTitleText(): Promise<string> {
|
||||
return element(by.css('app-root .content span')).getText() as Promise<string>;
|
||||
}
|
||||
}
|
13
examples/angular/e2e/tsconfig.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/e2e",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
32
examples/angular/karma.conf.js
Normal file
@ -0,0 +1,32 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/angular'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
13350
examples/angular/package-lock.json
generated
Normal file
51
examples/angular/package.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "crypto-pro-example-angular",
|
||||
"version": "0.0.0",
|
||||
"description": "Пример использования пакета crypto-pro в typescript проекте с angular",
|
||||
"scripts": {
|
||||
"serve": "static --host-address localhost --port 8082 dist/angular",
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "~9.0.7",
|
||||
"@angular/common": "~9.0.7",
|
||||
"@angular/compiler": "~9.0.7",
|
||||
"@angular/core": "~9.0.7",
|
||||
"@angular/forms": "~9.0.7",
|
||||
"@angular/platform-browser": "~9.0.7",
|
||||
"@angular/platform-browser-dynamic": "~9.0.7",
|
||||
"@angular/router": "~9.0.7",
|
||||
"crypto-pro": "2.0.0",
|
||||
"rxjs": "~6.5.4",
|
||||
"tslib": "^1.10.0",
|
||||
"zone.js": "~0.10.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.900.7",
|
||||
"@angular/cli": "~9.0.7",
|
||||
"@angular/compiler-cli": "~9.0.7",
|
||||
"@angular/language-service": "~9.0.7",
|
||||
"@types/node": "^12.11.1",
|
||||
"@types/jasmine": "~3.5.0",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"codelyzer": "^5.1.2",
|
||||
"jasmine-core": "~3.5.0",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~4.3.0",
|
||||
"karma-chrome-launcher": "~3.1.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.1.0",
|
||||
"karma-jasmine": "~2.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.4.2",
|
||||
"node-static": "0.7.11",
|
||||
"protractor": "~5.4.3",
|
||||
"ts-node": "~8.3.0",
|
||||
"tslint": "~5.18.0",
|
||||
"typescript": "~3.7.5"
|
||||
}
|
||||
}
|
0
examples/angular/src/app/app.component.css
Normal file
1
examples/angular/src/app/app.component.html
Normal file
@ -0,0 +1 @@
|
||||
<app-crypto-pro></app-crypto-pro>
|
24
examples/angular/src/app/app.component.spec.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'angular'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('angular');
|
||||
});
|
||||
});
|
10
examples/angular/src/app/app.component.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'angular';
|
||||
}
|
20
examples/angular/src/app/app.module.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { CryptoProComponent } from './crypto-pro/crypto-pro.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
CryptoProComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
@ -0,0 +1,34 @@
|
||||
<select name="certificate"
|
||||
[(ngModel)]="thumbprint">
|
||||
<option value="null" disabled>Не выбран</option>
|
||||
|
||||
<option *ngFor="let cert of certificateList"
|
||||
[value]="cert.thumbprint">
|
||||
{{cert.name}}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<button type="button"
|
||||
[disabled]="!thumbprint"
|
||||
(click)="createSignature(thumbprint)">
|
||||
Создать подпись
|
||||
</button>
|
||||
|
||||
<button type="button"
|
||||
[disabled]="!thumbprint"
|
||||
(click)="showCertInfo(thumbprint)">
|
||||
Информация о сертификате
|
||||
</button>
|
||||
|
||||
<pre *ngIf="certInfo">{{certInfo | json}}</pre>
|
||||
|
||||
<br>
|
||||
|
||||
<textarea name="signature"
|
||||
[(ngModel)]="signature"
|
||||
cols="100"
|
||||
rows="30"></textarea>
|
||||
|
||||
<pre *ngIf="error">{{error}}</pre>
|
||||
|
||||
<pre *ngIf="systemInfo">{{systemInfo | json}}</pre>
|
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CryptoProComponent } from './crypto-pro.component';
|
||||
|
||||
describe('CryptoProComponent', () => {
|
||||
let component: CryptoProComponent;
|
||||
let fixture: ComponentFixture<CryptoProComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CryptoProComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CryptoProComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
99
examples/angular/src/app/crypto-pro/crypto-pro.component.ts
Normal file
@ -0,0 +1,99 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {
|
||||
getCertificate,
|
||||
getUserCertificates,
|
||||
getSystemInfo,
|
||||
isValidSystemSetup,
|
||||
createSignature,
|
||||
SystemInfo,
|
||||
Certificate
|
||||
} from 'crypto-pro';
|
||||
|
||||
@Component({
|
||||
selector: 'app-crypto-pro',
|
||||
templateUrl: './crypto-pro.component.html',
|
||||
styleUrls: ['./crypto-pro.component.css']
|
||||
})
|
||||
export class CryptoProComponent implements OnInit {
|
||||
public certificateList: Certificate[] = [];
|
||||
public thumbprint: string = null;
|
||||
public signature: string;
|
||||
public systemInfo: SystemInfo & {
|
||||
isValidSystemSetup: boolean;
|
||||
};
|
||||
public error: string;
|
||||
public certInfo;
|
||||
|
||||
constructor() { }
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.displayCertificates();
|
||||
this.displaySystemInfo();
|
||||
}
|
||||
|
||||
public async createSignature(thumbprint) {
|
||||
// Вычислинный hash по ГОСТ Р 34.11-94 для строки: "abc"
|
||||
const hash = 'b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c';
|
||||
const hashBase64 = window.btoa(hash);
|
||||
|
||||
try {
|
||||
this.signature = await createSignature(thumbprint, hashBase64);
|
||||
} catch (error) {
|
||||
this.error = error.message;
|
||||
}
|
||||
}
|
||||
|
||||
public async showCertInfo(thumbprint) {
|
||||
try {
|
||||
const certificate = await getCertificate(thumbprint);
|
||||
|
||||
this.certInfo = {
|
||||
name: certificate.name,
|
||||
issuerName: certificate.issuerName,
|
||||
subjectName: certificate.subjectName,
|
||||
thumbprint: certificate.thumbprint,
|
||||
validFrom: certificate.validFrom,
|
||||
validTo: certificate.validTo,
|
||||
isValid: await certificate.isValid(),
|
||||
version: await certificate.getCadesProp('Version'),
|
||||
base64: await certificate.exportBase64(),
|
||||
algorithm: await certificate.getAlgorithm(),
|
||||
extendedKeyUsage: await certificate.getExtendedKeyUsage(),
|
||||
ownerInfo: await certificate.getOwnerInfo(),
|
||||
issuerInfo: await certificate.getIssuerInfo(),
|
||||
decodedExtendedKeyUsage: await certificate.getDecodedExtendedKeyUsage(),
|
||||
'1.3.6.1.4.1.311.80.1': await certificate.hasExtendedKeyUsage('1.3.6.1.4.1.311.80.1'),
|
||||
'[\'1.3.6.1.5.5.7.3.2\', \'1.3.6.1.4.1.311.10.3.12\']': await certificate.hasExtendedKeyUsage([
|
||||
'1.3.6.1.5.5.7.3.2',
|
||||
'1.3.6.1.4.1.311.10.3.12'
|
||||
]),
|
||||
'1.3.6.1.4.1.311.80.2': await certificate.hasExtendedKeyUsage('1.3.6.1.4.1.311.80.2'),
|
||||
'\'1.3.6.1.5.5.7.3.3\', \'1.3.6.1.4.1.311.10.3.12\'': await certificate.hasExtendedKeyUsage([
|
||||
'1.3.6.1.5.5.7.3.3',
|
||||
'1.3.6.1.4.1.311.10.3.12'
|
||||
]),
|
||||
};
|
||||
} catch (error) {
|
||||
this.error = error.message;
|
||||
}
|
||||
}
|
||||
|
||||
private async displayCertificates() {
|
||||
try {
|
||||
this.certificateList = await getUserCertificates();
|
||||
} catch (error) {
|
||||
this.error = error.message;
|
||||
}
|
||||
}
|
||||
|
||||
private async displaySystemInfo() {
|
||||
try {
|
||||
this.systemInfo = {
|
||||
...await getSystemInfo(),
|
||||
isValidSystemSetup: await isValidSystemSetup()
|
||||
};
|
||||
} catch (error) {
|
||||
this.error = error.message;
|
||||
}
|
||||
}
|
||||
}
|
0
examples/angular/src/assets/.gitkeep
Normal file
3
examples/angular/src/environments/environment.prod.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const environment = {
|
||||
production: true
|
||||
};
|
16
examples/angular/src/environments/environment.ts
Normal file
@ -0,0 +1,16 @@
|
||||
// This file can be replaced during build by using the `fileReplacements` array.
|
||||
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||||
// The list of file replacements can be found in `angular.json`.
|
||||
|
||||
export const environment = {
|
||||
production: false
|
||||
};
|
||||
|
||||
/*
|
||||
* For easier debugging in development mode, you can import the following file
|
||||
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||||
*
|
||||
* This import should be commented out in production mode because it will have a negative impact
|
||||
* on performance if an error is thrown.
|
||||
*/
|
||||
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
BIN
examples/angular/src/favicon.ico
Normal file
After Width: | Height: | Size: 948 B |
13
examples/angular/src/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Angular</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
12
examples/angular/src/main.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
63
examples/angular/src/polyfills.ts
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* This file includes polyfills needed by Angular and is loaded before the app.
|
||||
* You can add your own extra polyfills to this file.
|
||||
*
|
||||
* This file is divided into 2 sections:
|
||||
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||||
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||||
* file.
|
||||
*
|
||||
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||||
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||||
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||||
*
|
||||
* Learn more in https://angular.io/guide/browser-support
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* BROWSER POLYFILLS
|
||||
*/
|
||||
|
||||
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||
|
||||
/**
|
||||
* Web Animations `@angular/platform-browser/animations`
|
||||
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||||
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
||||
*/
|
||||
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||||
|
||||
/**
|
||||
* By default, zone.js will patch all possible macroTask and DomEvents
|
||||
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||||
* because those flags need to be set before `zone.js` being loaded, and webpack
|
||||
* will put import in the top of bundle, so user need to create a separate file
|
||||
* in this directory (for example: zone-flags.ts), and put the following flags
|
||||
* into that file, and then add the following code before importing zone.js.
|
||||
* import './zone-flags';
|
||||
*
|
||||
* The flags allowed in zone-flags.ts are listed here.
|
||||
*
|
||||
* The following flags will work for all browsers.
|
||||
*
|
||||
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
|
||||
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||||
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
|
||||
*
|
||||
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||||
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||||
*
|
||||
* (window as any).__Zone_enable_cross_context_check = true;
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
* Zone JS is required by default for Angular itself.
|
||||
*/
|
||||
import 'zone.js/dist/zone'; // Included with Angular CLI.
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
1
examples/angular/src/styles.css
Normal file
@ -0,0 +1 @@
|
||||
/* You can add global styles to this file, and also import other style files */
|
25
examples/angular/src/test.ts
Normal file
@ -0,0 +1,25 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
|
||||
import 'zone.js/dist/zone-testing';
|
||||
import { getTestBed } from '@angular/core/testing';
|
||||
import {
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting
|
||||
} from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: {
|
||||
context(path: string, deep?: boolean, filter?: RegExp): {
|
||||
keys(): string[];
|
||||
<T>(id: string): T;
|
||||
};
|
||||
};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting()
|
||||
);
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
14
examples/angular/tsconfig.app.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/app",
|
||||
"types": []
|
||||
},
|
||||
"files": [
|
||||
"src/main.ts",
|
||||
"src/polyfills.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
23
examples/angular/tsconfig.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"outDir": "./dist/out-tsc",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"lib": [
|
||||
"es2018",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"fullTemplateTypeCheck": true,
|
||||
"strictInjectionParameters": true
|
||||
}
|
||||
}
|
18
examples/angular/tsconfig.spec.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/spec",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts",
|
||||
"src/polyfills.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
91
examples/angular/tslint.json
Normal file
@ -0,0 +1,91 @@
|
||||
{
|
||||
"extends": "tslint:recommended",
|
||||
"rules": {
|
||||
"array-type": false,
|
||||
"arrow-parens": false,
|
||||
"deprecation": {
|
||||
"severity": "warning"
|
||||
},
|
||||
"component-class-suffix": true,
|
||||
"contextual-lifecycle": true,
|
||||
"directive-class-suffix": true,
|
||||
"directive-selector": [
|
||||
true,
|
||||
"attribute",
|
||||
"app",
|
||||
"camelCase"
|
||||
],
|
||||
"component-selector": [
|
||||
true,
|
||||
"element",
|
||||
"app",
|
||||
"kebab-case"
|
||||
],
|
||||
"import-blacklist": [
|
||||
true,
|
||||
"rxjs/Rx"
|
||||
],
|
||||
"interface-name": false,
|
||||
"max-classes-per-file": false,
|
||||
"max-line-length": [
|
||||
true,
|
||||
140
|
||||
],
|
||||
"member-access": false,
|
||||
"member-ordering": [
|
||||
true,
|
||||
{
|
||||
"order": [
|
||||
"static-field",
|
||||
"instance-field",
|
||||
"static-method",
|
||||
"instance-method"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-consecutive-blank-lines": false,
|
||||
"no-console": [
|
||||
true,
|
||||
"debug",
|
||||
"info",
|
||||
"time",
|
||||
"timeEnd",
|
||||
"trace"
|
||||
],
|
||||
"no-empty": false,
|
||||
"no-inferrable-types": [
|
||||
true,
|
||||
"ignore-params"
|
||||
],
|
||||
"no-non-null-assertion": true,
|
||||
"no-redundant-jsdoc": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-var-requires": false,
|
||||
"object-literal-key-quotes": [
|
||||
true,
|
||||
"as-needed"
|
||||
],
|
||||
"object-literal-sort-keys": false,
|
||||
"ordered-imports": false,
|
||||
"quotemark": [
|
||||
true,
|
||||
"single"
|
||||
],
|
||||
"trailing-comma": false,
|
||||
"no-conflicting-lifecycle": true,
|
||||
"no-host-metadata-property": true,
|
||||
"no-input-rename": true,
|
||||
"no-inputs-metadata-property": true,
|
||||
"no-output-native": true,
|
||||
"no-output-on-prefix": true,
|
||||
"no-output-rename": true,
|
||||
"no-outputs-metadata-property": true,
|
||||
"template-banana-in-box": true,
|
||||
"template-no-negated-async": true,
|
||||
"use-lifecycle-interface": true,
|
||||
"use-pipe-transform-interface": true
|
||||
},
|
||||
"rulesDirectory": [
|
||||
"codelyzer"
|
||||
]
|
||||
}
|
1
examples/react/.env
Normal file
@ -0,0 +1 @@
|
||||
SKIP_PREFLIGHT_CHECK=true
|
23
examples/react/.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
68
examples/react/README.md
Normal file
@ -0,0 +1,68 @@
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm start`
|
||||
|
||||
Runs the app in the development mode.<br />
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.<br />
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `npm test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.<br />
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `npm run build`
|
||||
|
||||
Builds the app for production to the `build` folder.<br />
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.<br />
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `npm run eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
|
||||
|
||||
### `npm run build` fails to minify
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
|
15010
examples/react/package-lock.json
generated
Normal file
41
examples/react/package.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "crypto-pro-example-react",
|
||||
"version": "0.1.0",
|
||||
"description": "Пример использования пакета crypto-pro в javascript проекте с react",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "4.2.4",
|
||||
"@testing-library/react": "9.5.0",
|
||||
"@testing-library/user-event": "7.2.1",
|
||||
"crypto-pro": "2.0.0",
|
||||
"react": "^16.13.1",
|
||||
"react-app-polyfill": "1.0.6",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"node-static": "0.7.11"
|
||||
},
|
||||
"scripts": {
|
||||
"serve": "static --host-address localhost --port 8081 build",
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
BIN
examples/react/public/favicon.ico
Normal file
After Width: | Height: | Size: 3.1 KiB |
45
examples/react/public/index.html
Normal file
@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<!-- Полифилл для работы демо в IE9 -->
|
||||
<script src="atob-btoa.js"></script>
|
||||
</body>
|
||||
</html>
|
BIN
examples/react/public/logo192.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
examples/react/public/logo512.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
25
examples/react/public/manifest.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
3
examples/react/public/robots.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
38
examples/react/src/App.css
Normal file
@ -0,0 +1,38 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
22
examples/react/src/App.js
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import './App.css';
|
||||
import CryptoPro from './components/CryptoPro';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<CryptoPro>{({certificate, setCertificate, signature, setSignature, error, setError}) =>
|
||||
<>
|
||||
<CryptoPro.CertList onChange={setCertificate} onError={setError}/>
|
||||
<CryptoPro.Sign certificate={certificate} onSign={setSignature} onError={setError}>
|
||||
Создать подпись
|
||||
</CryptoPro.Sign>
|
||||
<CryptoPro.CertInfo certificate={certificate} onError={setError}/>
|
||||
<textarea value={signature} readOnly cols="100" rows="30"/>
|
||||
<pre>{error}</pre>
|
||||
<CryptoPro.SystemInfo onError={setError}/>
|
||||
</>
|
||||
}</CryptoPro>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
9
examples/react/src/App.test.js
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
xtest('renders learn react link', () => {
|
||||
const { getByText } = render(<App />);
|
||||
const linkElement = getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
55
examples/react/src/components/CryptoPro/CertInfo.js
Normal file
@ -0,0 +1,55 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
function CertInfo({certificate, onError}) {
|
||||
const [certInfo, setCertInfo] = useState(null);
|
||||
|
||||
async function showCertInfo() {
|
||||
try {
|
||||
setCertInfo({
|
||||
name: certificate.name,
|
||||
issuerName: certificate.issuerName,
|
||||
subjectName: certificate.subjectName,
|
||||
thumbprint: certificate.thumbprint,
|
||||
validFrom: certificate.validFrom,
|
||||
validTo: certificate.validTo,
|
||||
isValid: await certificate.isValid(),
|
||||
version: await certificate.getCadesProp('Version'),
|
||||
base64: await certificate.exportBase64(),
|
||||
algorithm: await certificate.getAlgorithm(),
|
||||
extendedKeyUsage: await certificate.getExtendedKeyUsage(),
|
||||
ownerInfo: await certificate.getOwnerInfo(),
|
||||
issuerInfo: await certificate.getIssuerInfo(),
|
||||
decodedExtendedKeyUsage: await certificate.getDecodedExtendedKeyUsage(),
|
||||
'1.3.6.1.4.1.311.80.1': await certificate.hasExtendedKeyUsage('1.3.6.1.4.1.311.80.1'),
|
||||
"['1.3.6.1.5.5.7.3.2', '1.3.6.1.4.1.311.10.3.12']": await certificate.hasExtendedKeyUsage([
|
||||
'1.3.6.1.5.5.7.3.2',
|
||||
'1.3.6.1.4.1.311.10.3.12'
|
||||
]),
|
||||
'1.3.6.1.4.1.311.80.2': await certificate.hasExtendedKeyUsage('1.3.6.1.4.1.311.80.2'),
|
||||
"'1.3.6.1.5.5.7.3.3', '1.3.6.1.4.1.311.10.3.12'": await certificate.hasExtendedKeyUsage([
|
||||
'1.3.6.1.5.5.7.3.3',
|
||||
'1.3.6.1.4.1.311.10.3.12'
|
||||
]),
|
||||
});
|
||||
} catch (error) {
|
||||
onError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={showCertInfo}
|
||||
disabled={!certificate}>
|
||||
Информация о сертификате
|
||||
</button>
|
||||
<br/>
|
||||
{certInfo ? (
|
||||
<pre>{JSON.stringify(certInfo, null, ' ')}</pre>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default CertInfo;
|
31
examples/react/src/components/CryptoPro/CertList.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { getUserCertificates } from 'crypto-pro';
|
||||
|
||||
function CertList({onChange, onError}) {
|
||||
const [certificates, setCertificates] = useState([]);
|
||||
|
||||
function selectCertificate(event) {
|
||||
onChange(certificates.find(({thumbprint}) => thumbprint === event.target.value));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
setCertificates(await getUserCertificates());
|
||||
} catch (error) {
|
||||
onError(error.message);
|
||||
}
|
||||
})();
|
||||
}, [onError]);
|
||||
|
||||
return (
|
||||
<select onChange={selectCertificate}>
|
||||
<option defaultValue={null}>Не выбран</option>
|
||||
{certificates.map(({name, thumbprint}) =>
|
||||
<option key={thumbprint} value={thumbprint}>{name}</option>
|
||||
)}
|
||||
</select>
|
||||
);
|
||||
}
|
||||
|
||||
export default CertList;
|
27
examples/react/src/components/CryptoPro/Sign.js
Normal file
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import { createSignature } from 'crypto-pro';
|
||||
|
||||
function Sign({certificate, onSign, onError, children}) {
|
||||
async function sign() {
|
||||
// Вычислинный hash по ГОСТ Р 34.11-94 для строки: "abc"
|
||||
const hash = 'b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c';
|
||||
const hashBase64 = window.btoa(hash);
|
||||
|
||||
try {
|
||||
onSign(await createSignature(certificate.thumbprint, hashBase64));
|
||||
} catch (error) {
|
||||
onError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
disabled={!certificate}
|
||||
onClick={sign}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export default Sign;
|
29
examples/react/src/components/CryptoPro/SystemInfo.js
Normal file
@ -0,0 +1,29 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { getSystemInfo, isValidSystemSetup } from 'crypto-pro';
|
||||
|
||||
function SystemInfo({onError}) {
|
||||
const [systemInfo, setSystemInfo] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
setSystemInfo({
|
||||
...await getSystemInfo(),
|
||||
isValidSystemSetup: await isValidSystemSetup()
|
||||
});
|
||||
} catch (error) {
|
||||
onError(error.message);
|
||||
}
|
||||
})();
|
||||
}, [onError]);
|
||||
|
||||
if (!systemInfo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<pre>{JSON.stringify(systemInfo, null, ' ')}</pre>
|
||||
);
|
||||
}
|
||||
|
||||
export default SystemInfo;
|
27
examples/react/src/components/CryptoPro/index.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { useState } from 'react';
|
||||
import CertList from './CertList';
|
||||
import CertInfo from './CertInfo';
|
||||
import Sign from './Sign';
|
||||
import SystemInfo from './SystemInfo';
|
||||
|
||||
const CryptoPro = ({children}) => {
|
||||
const [certificate, setCertificate] = useState(null);
|
||||
const [signature, setSignature] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
||||
return children({
|
||||
certificate,
|
||||
setCertificate,
|
||||
signature,
|
||||
setSignature,
|
||||
error,
|
||||
setError
|
||||
});
|
||||
};
|
||||
|
||||
CryptoPro.CertList = CertList;
|
||||
CryptoPro.Sign = Sign;
|
||||
CryptoPro.CertInfo = CertInfo;
|
||||
CryptoPro.SystemInfo = SystemInfo;
|
||||
|
||||
export default CryptoPro;
|
13
examples/react/src/index.css
Normal file
@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
20
examples/react/src/index.js
Normal file
@ -0,0 +1,20 @@
|
||||
import 'react-app-polyfill/ie9';
|
||||
import 'react-app-polyfill/stable';
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
7
examples/react/src/logo.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
|
||||
<g fill="#61DAFB">
|
||||
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
|
||||
<circle cx="420.9" cy="296.5" r="45.7"/>
|
||||
<path d="M520.5 78.1z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
141
examples/react/src/serviceWorker.js
Normal file
@ -0,0 +1,141 @@
|
||||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' },
|
||||
})
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then(registration => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
5
examples/react/src/setupTests.js
Normal file
@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom/extend-expect';
|
213
examples/script-tag/package-lock.json
generated
Normal file
@ -0,0 +1,213 @@
|
||||
{
|
||||
"name": "crypto-pro-example-es5-script-tag",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
},
|
||||
"better-path-resolve": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz",
|
||||
"integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-windows": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
|
||||
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"crypto-pro": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-pro/-/crypto-pro-2.0.0.tgz",
|
||||
"integrity": "sha512-U1N9CsPMca9vhYVfNShKraJtW+eRpD0Ly2n3QJMkHvud/WuMEQUMX5PLsdnOzTD3bcEyfOB2YBRJKguGmwtelA=="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
|
||||
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-windows": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
|
||||
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
|
||||
"dev": true
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz",
|
||||
"integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
|
||||
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
|
||||
"dev": true
|
||||
},
|
||||
"node-static": {
|
||||
"version": "0.7.11",
|
||||
"resolved": "https://registry.npmjs.org/node-static/-/node-static-0.7.11.tgz",
|
||||
"integrity": "sha512-zfWC/gICcqb74D9ndyvxZWaI1jzcoHmf4UTHWQchBNuNMxdBLJMDiUgZ1tjGLEIe/BMhj2DxKD8HOuc2062pDQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colors": ">=0.6.0",
|
||||
"mime": "^1.2.9",
|
||||
"optimist": ">=0.3.4"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"optimist": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
|
||||
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "~0.0.1",
|
||||
"wordwrap": "~0.0.2"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
},
|
||||
"rename-overwrite": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rename-overwrite/-/rename-overwrite-2.0.2.tgz",
|
||||
"integrity": "sha512-XodkUmbg11ZzZoAkYfJYEmj8FscfeRL2KHGALeDSB76ia8A1zqQq0+WkcepXm7QkuzmW0CE3uiFUBr/UJfin+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.11",
|
||||
"rimraf": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"symlink-dir": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/symlink-dir/-/symlink-dir-3.1.2.tgz",
|
||||
"integrity": "sha512-wuqI+beQTU3XQq6bHTg4tcFiXlAN5uWNus+R0/I/R9O/ORpVHdCo2JQp04dCexBIb94VarosKFU+kjVEgzIQpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"better-path-resolve": "^1.0.0",
|
||||
"graceful-fs": "^4.1.11",
|
||||
"make-dir": "^3.0.0",
|
||||
"rename-overwrite": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
|
||||
"dev": true
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
18
examples/script-tag/package.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "crypto-pro-example-es5-script-tag",
|
||||
"version": "0.0.0",
|
||||
"description": "Пример использования пакета crypto-pro через тэг script",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"link-library": "symlink-dir ./node_modules/crypto-pro/dist ./public/dist",
|
||||
"serve": "static --host-address localhost --port 8080 public",
|
||||
"start": "npm run link-library && npm run serve"
|
||||
},
|
||||
"devDependencies": {
|
||||
"node-static": "0.7.11",
|
||||
"symlink-dir": "3.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"crypto-pro": "2.0.0"
|
||||
}
|
||||
}
|
24
examples/script-tag/public/cert-list.js
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Пример получения списка сертификатов
|
||||
* */
|
||||
;(function () {
|
||||
'use strict';
|
||||
|
||||
var $certs = document.getElementById('certList'),
|
||||
$errorMsg = document.getElementById('errorMessage');
|
||||
|
||||
window.cryptoPro.getUserCertificates()
|
||||
.then(function (certificateList) {
|
||||
certificateList.forEach(function (certificate) {
|
||||
var $certOption = document.createElement('option');
|
||||
|
||||
$certOption.textContent = certificate.name + ' (действителен до: ' + certificate.validTo + ')';
|
||||
|
||||
$certOption.value = certificate.thumbprint;
|
||||
|
||||
$certs.appendChild($certOption);
|
||||
});
|
||||
}, function (error) {
|
||||
$errorMsg.textContent = '\n' + error.message;
|
||||
});
|
||||
})();
|
24
examples/script-tag/public/create-sign.js
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Пример создания подписи данных, сгенерированных по ГОСТ Р 34.11-94
|
||||
* https://ru.wikipedia.org/wiki/%D0%93%D0%9E%D0%A1%D0%A2_%D0%A0_34.11-94
|
||||
* */
|
||||
;(function () {
|
||||
'use strict';
|
||||
|
||||
var $errorMsg = document.getElementById('errorMessage');
|
||||
|
||||
document
|
||||
.getElementById('createSign')
|
||||
.addEventListener('click', function () {
|
||||
// Вычислинный hash по ГОСТ Р 34.11-94 для строки: "abc"
|
||||
var hash = 'b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c',
|
||||
hashBase64 = window.btoa(hash),
|
||||
thumbprint = document.getElementById('certList').value;
|
||||
|
||||
window.cryptoPro.createSignature(thumbprint, hashBase64).then(function (signature) {
|
||||
document.getElementById('createdSign').value = signature;
|
||||
}, function (error) {
|
||||
$errorMsg.textContent = '\n' + error.message;
|
||||
});
|
||||
});
|
||||
})();
|
20
examples/script-tag/public/get-env-info.js
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Пример получения сведений о системе
|
||||
*/
|
||||
;(function () {
|
||||
'use strict';
|
||||
|
||||
var $errorMsg = document.getElementById('errorMessage');
|
||||
|
||||
window.cryptoPro.getSystemInfo().then(function (systemInfo) {
|
||||
window.cryptoPro.isValidSystemSetup().then(function (isValidSystemSetup) {
|
||||
systemInfo.isValidSystemSetup = isValidSystemSetup;
|
||||
|
||||
document.getElementById('systemInfo').textContent = JSON.stringify(systemInfo, null, ' ');
|
||||
}, function (error) {
|
||||
$errorMsg.textContent = '\n' + error.message;
|
||||
});
|
||||
}, function (error) {
|
||||
$errorMsg.textContent = '\n' + error.message;
|
||||
});
|
||||
})();
|
@ -2,22 +2,24 @@
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Пример использования CryptoPro</title>
|
||||
<title>Пример использования cryptoPro</title>
|
||||
</head>
|
||||
<body>
|
||||
<select id="certList"></select>
|
||||
<button id="createSign" type="button">Создать подпись</button>
|
||||
<button id="showCertificate" type="button">Информация о сертификате</button>
|
||||
<br>
|
||||
<textarea id="createdSign" cols="90" rows="30"></textarea>
|
||||
<pre id="certificateInfo"></pre>
|
||||
<textarea id="createdSign" cols="100" rows="30"></textarea>
|
||||
<pre id="errorMessage"></pre>
|
||||
<pre id="systemInfo"></pre>
|
||||
|
||||
<!-- Полифиллы для работы библиотеки -->
|
||||
<script src="polyfills/addEventListener.js"></script>
|
||||
<script src="polyfills/promise.js"></script>
|
||||
<script src="polyfills/forEach.js"></script>
|
||||
<script src="polyfills/map.js"></script>
|
||||
<script src="polyfills/find.js"></script>
|
||||
|
||||
<!-- Библиотека -->
|
||||
<script src="../dist/crypto-pro.js"></script>
|
||||
<script src="dist/crypto-pro.js"></script>
|
||||
|
||||
<!-- Полифиллы для работы демо скриптов -->
|
||||
<script src="polyfills/atob-btoa.js"></script>
|
||||
@ -25,5 +27,7 @@
|
||||
<!-- Демо скрипты -->
|
||||
<script src="cert-list.js"></script>
|
||||
<script src="create-sign.js"></script>
|
||||
<script src="get-env-info.js"></script>
|
||||
<script src="show-cert.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
76
examples/script-tag/public/polyfills/atob-btoa.js
Normal file
@ -0,0 +1,76 @@
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([], function () {
|
||||
factory(root);
|
||||
});
|
||||
} else factory(root);
|
||||
// node.js has always supported base64 conversions, while browsers that support
|
||||
// web workers support base64 too, but you may never know.
|
||||
})(typeof exports !== "undefined" ? exports : this, function (root) {
|
||||
if (root.atob) {
|
||||
// Some browsers' implementation of atob doesn't support whitespaces
|
||||
// in the encoded string (notably, IE). This wraps the native atob
|
||||
// in a function that strips the whitespaces.
|
||||
// The original function can be retrieved in atob.original
|
||||
try {
|
||||
root.atob(" ");
|
||||
} catch (e) {
|
||||
root.atob = (function (atob) {
|
||||
var func = function (string) {
|
||||
return atob(String(string).replace(/[\t\n\f\r ]+/g, ""));
|
||||
};
|
||||
func.original = atob;
|
||||
return func;
|
||||
})(root.atob);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// base64 character set, plus padding character (=)
|
||||
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
||||
// Regular expression to check formal correctness of base64 encoded strings
|
||||
b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
||||
|
||||
root.btoa = function (string) {
|
||||
string = String(string);
|
||||
var bitmap, a, b, c,
|
||||
result = "", i = 0,
|
||||
rest = string.length % 3; // To determine the final padding
|
||||
|
||||
for (; i < string.length;) {
|
||||
if ((a = string.charCodeAt(i++)) > 255
|
||||
|| (b = string.charCodeAt(i++)) > 255
|
||||
|| (c = string.charCodeAt(i++)) > 255)
|
||||
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
|
||||
|
||||
bitmap = (a << 16) | (b << 8) | c;
|
||||
result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63)
|
||||
+ b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
|
||||
}
|
||||
|
||||
// If there's need of padding, replace the last 'A's with equal signs
|
||||
return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
|
||||
};
|
||||
|
||||
root.atob = function (string) {
|
||||
// atob can work with strings with whitespaces, even inside the encoded part,
|
||||
// but only \t, \n, \f, \r and ' ', which can be stripped.
|
||||
string = String(string).replace(/[\t\n\f\r ]+/g, "");
|
||||
if (!b64re.test(string))
|
||||
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
||||
|
||||
// Adding the padding if missing, for semplicity
|
||||
string += "==".slice(2 - (string.length & 3));
|
||||
var bitmap, result = "", r1, r2, i = 0;
|
||||
for (; i < string.length;) {
|
||||
bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12
|
||||
| (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));
|
||||
|
||||
result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255)
|
||||
: r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255)
|
||||
: String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
});
|
43
examples/script-tag/public/polyfills/find.js
Normal file
@ -0,0 +1,43 @@
|
||||
// https://tc39.github.io/ecma262/#sec-array.prototype.find
|
||||
if (!Array.prototype.find) {
|
||||
Array.prototype.find = function(predicate) {
|
||||
'use strict';
|
||||
// 1. Let O be ? ToObject(this value).
|
||||
if (this == null) {
|
||||
throw new TypeError('"this" is null or not defined');
|
||||
}
|
||||
|
||||
var o = Object(this);
|
||||
|
||||
// 2. Let len be ? ToLength(? Get(O, "length")).
|
||||
var len = o.length >>> 0;
|
||||
|
||||
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
|
||||
if (typeof predicate !== 'function') {
|
||||
throw new TypeError('predicate must be a function');
|
||||
}
|
||||
|
||||
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
||||
var thisArg = arguments[1];
|
||||
|
||||
// 5. Let k be 0.
|
||||
var k = 0;
|
||||
|
||||
// 6. Repeat, while k < len
|
||||
while (k < len) {
|
||||
// a. Let Pk be ! ToString(k).
|
||||
// b. Let kValue be ? Get(O, Pk).
|
||||
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
|
||||
// d. If testResult is true, return kValue.
|
||||
var kValue = o[k];
|
||||
if (predicate.call(thisArg, kValue, k, o)) {
|
||||
return kValue;
|
||||
}
|
||||
// e. Increase k by 1.
|
||||
k++;
|
||||
}
|
||||
|
||||
// 7. Return undefined.
|
||||
return undefined;
|
||||
};
|
||||
}
|
50
examples/script-tag/public/show-cert.js
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Пример извлечения информации о сертификате
|
||||
* */
|
||||
;(function () {
|
||||
'use strict';
|
||||
|
||||
document
|
||||
.getElementById('showCertificate')
|
||||
.addEventListener('click', function () {
|
||||
var thumbprint = document.getElementById('certList').value;
|
||||
|
||||
window.cryptoPro.getCertificate(thumbprint).then(function (certificate) {
|
||||
Promise.all([
|
||||
certificate.isValid(),
|
||||
certificate.getCadesProp('Version'),
|
||||
certificate.exportBase64(),
|
||||
certificate.getAlgorithm(),
|
||||
certificate.getExtendedKeyUsage(),
|
||||
certificate.getOwnerInfo(),
|
||||
certificate.getIssuerInfo(),
|
||||
certificate.getDecodedExtendedKeyUsage(),
|
||||
certificate.hasExtendedKeyUsage('1.3.6.1.4.1.311.80.1'),
|
||||
certificate.hasExtendedKeyUsage(['1.3.6.1.5.5.7.3.2', '1.3.6.1.4.1.311.10.3.12']),
|
||||
certificate.hasExtendedKeyUsage('1.3.6.1.4.1.311.80.2'),
|
||||
certificate.hasExtendedKeyUsage(['1.3.6.1.5.5.7.3.3', '1.3.6.1.4.1.311.10.3.12']),
|
||||
]).then(function (results) {
|
||||
document.getElementById('certificateInfo').textContent = JSON.stringify({
|
||||
name: certificate.name,
|
||||
issuerName: certificate.issuerName,
|
||||
subjectName: certificate.subjectName,
|
||||
thumbprint: certificate.thumbprint,
|
||||
validFrom: certificate.validFrom,
|
||||
validTo: certificate.validTo,
|
||||
isValid: results[0],
|
||||
version: results[1],
|
||||
base64: results[2],
|
||||
algorithm: results[3],
|
||||
extendedKeyUsage: results[4],
|
||||
ownerInfo: results[5],
|
||||
issuerInfo: results[6],
|
||||
decodedExtendedKeyUsage: results[7],
|
||||
'1.3.6.1.4.1.311.80.1': results[8],
|
||||
"['1.3.6.1.5.5.7.3.2', '1.3.6.1.4.1.311.10.3.12']": results[9],
|
||||
'1.3.6.1.4.1.311.80.2': results[10],
|
||||
"'1.3.6.1.5.5.7.3.3', '1.3.6.1.4.1.311.10.3.12'": results[11],
|
||||
}, null, ' ');
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
10
jest.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'jsdom',
|
||||
coveragePathIgnorePatterns: [
|
||||
'<rootDir>/src/vendor/',
|
||||
],
|
||||
testPathIgnorePatterns: [
|
||||
'<rootDir>/examples/',
|
||||
],
|
||||
};
|
845
npm-shrinkwrap.json
generated
@ -1,845 +0,0 @@
|
||||
{
|
||||
"name": "crypto-pro",
|
||||
"version": "1.1.2",
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "3.3.0",
|
||||
"from": "acorn@>=3.0.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"align-text": {
|
||||
"version": "0.1.4",
|
||||
"from": "align-text@>=0.1.3 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"amdefine": {
|
||||
"version": "1.0.1",
|
||||
"from": "amdefine@>=0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "1.3.0",
|
||||
"from": "anymatch@>=1.3.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"arr-diff": {
|
||||
"version": "2.0.0",
|
||||
"from": "arr-diff@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"arr-flatten": {
|
||||
"version": "1.0.1",
|
||||
"from": "arr-flatten@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"array-unique": {
|
||||
"version": "0.2.1",
|
||||
"from": "array-unique@>=0.2.1 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"arrify": {
|
||||
"version": "1.0.1",
|
||||
"from": "arrify@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"assert": {
|
||||
"version": "1.4.1",
|
||||
"from": "assert@>=1.1.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"async": {
|
||||
"version": "1.5.2",
|
||||
"from": "async@>=1.3.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"async-each": {
|
||||
"version": "1.0.1",
|
||||
"from": "async-each@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "0.4.2",
|
||||
"from": "balanced-match@>=0.4.1 <0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"Base64": {
|
||||
"version": "0.2.1",
|
||||
"from": "Base64@>=0.2.0 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "1.2.0",
|
||||
"from": "base64-js@>=1.0.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"big.js": {
|
||||
"version": "3.1.3",
|
||||
"from": "big.js@>=3.1.3 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"binary-extensions": {
|
||||
"version": "1.8.0",
|
||||
"from": "binary-extensions@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.8.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"bowser": {
|
||||
"version": "1.5.0",
|
||||
"from": "bowser@1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bowser/-/bowser-1.5.0.tgz"
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.6",
|
||||
"from": "brace-expansion@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"braces": {
|
||||
"version": "1.8.5",
|
||||
"from": "braces@>=1.8.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"browserify-zlib": {
|
||||
"version": "0.1.4",
|
||||
"from": "browserify-zlib@>=0.1.4 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"buffer": {
|
||||
"version": "4.9.1",
|
||||
"from": "buffer@>=4.9.0 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"buffer-shims": {
|
||||
"version": "1.0.0",
|
||||
"from": "buffer-shims@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "1.2.1",
|
||||
"from": "camelcase@>=1.0.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"center-align": {
|
||||
"version": "0.1.3",
|
||||
"from": "center-align@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "1.6.1",
|
||||
"from": "chokidar@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"cliui": {
|
||||
"version": "2.1.0",
|
||||
"from": "cliui@>=2.1.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wordwrap": {
|
||||
"version": "0.0.2",
|
||||
"from": "wordwrap@0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"clone": {
|
||||
"version": "1.0.2",
|
||||
"from": "clone@>=1.0.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"from": "concat-map@0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"console-browserify": {
|
||||
"version": "1.1.0",
|
||||
"from": "console-browserify@>=1.1.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"constants-browserify": {
|
||||
"version": "0.0.1",
|
||||
"from": "constants-browserify@0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"from": "core-util-is@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"crypto-browserify": {
|
||||
"version": "3.2.8",
|
||||
"from": "crypto-browserify@>=3.2.6 <3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.2.8.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"date-now": {
|
||||
"version": "0.1.4",
|
||||
"from": "date-now@>=0.1.4 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"decamelize": {
|
||||
"version": "1.2.0",
|
||||
"from": "decamelize@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"domain-browser": {
|
||||
"version": "1.1.7",
|
||||
"from": "domain-browser@>=1.1.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"emojis-list": {
|
||||
"version": "2.1.0",
|
||||
"from": "emojis-list@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
"version": "0.9.1",
|
||||
"from": "enhanced-resolve@>=0.9.0 <0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"memory-fs": {
|
||||
"version": "0.2.0",
|
||||
"from": "memory-fs@>=0.2.0 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"errno": {
|
||||
"version": "0.1.4",
|
||||
"from": "errno@>=0.1.3 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"events": {
|
||||
"version": "1.1.1",
|
||||
"from": "events@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"expand-brackets": {
|
||||
"version": "0.1.5",
|
||||
"from": "expand-brackets@>=0.1.4 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"expand-range": {
|
||||
"version": "1.8.2",
|
||||
"from": "expand-range@>=1.8.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"extglob": {
|
||||
"version": "0.3.2",
|
||||
"from": "extglob@>=0.3.1 <0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"filename-regex": {
|
||||
"version": "2.0.0",
|
||||
"from": "filename-regex@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "2.2.3",
|
||||
"from": "fill-range@>=2.1.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"for-in": {
|
||||
"version": "0.1.6",
|
||||
"from": "for-in@>=0.1.5 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.6.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"for-own": {
|
||||
"version": "0.1.4",
|
||||
"from": "for-own@>=0.1.4 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"glob-base": {
|
||||
"version": "0.3.0",
|
||||
"from": "glob-base@>=0.3.0 <0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "2.0.0",
|
||||
"from": "glob-parent@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"from": "graceful-fs@>=4.1.2 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "1.0.0",
|
||||
"from": "has-flag@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"http-browserify": {
|
||||
"version": "1.7.0",
|
||||
"from": "http-browserify@>=1.3.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"https-browserify": {
|
||||
"version": "0.0.0",
|
||||
"from": "https-browserify@0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.1.8",
|
||||
"from": "ieee754@>=1.1.4 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"indexof": {
|
||||
"version": "0.0.1",
|
||||
"from": "indexof@0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"from": "inherits@>=2.0.1 <2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"interpret": {
|
||||
"version": "0.6.6",
|
||||
"from": "interpret@>=0.6.4 <0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-binary-path": {
|
||||
"version": "1.0.1",
|
||||
"from": "is-binary-path@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-buffer": {
|
||||
"version": "1.1.4",
|
||||
"from": "is-buffer@>=1.0.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-dotfile": {
|
||||
"version": "1.0.2",
|
||||
"from": "is-dotfile@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-equal-shallow": {
|
||||
"version": "0.1.3",
|
||||
"from": "is-equal-shallow@>=0.1.3 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-extendable": {
|
||||
"version": "0.1.1",
|
||||
"from": "is-extendable@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "1.0.0",
|
||||
"from": "is-extglob@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "2.0.1",
|
||||
"from": "is-glob@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-number": {
|
||||
"version": "2.1.0",
|
||||
"from": "is-number@>=2.1.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-posix-bracket": {
|
||||
"version": "0.1.1",
|
||||
"from": "is-posix-bracket@>=0.1.0 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"is-primitive": {
|
||||
"version": "2.0.0",
|
||||
"from": "is-primitive@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"from": "isarray@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"isobject": {
|
||||
"version": "2.1.0",
|
||||
"from": "isobject@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"json5": {
|
||||
"version": "0.5.1",
|
||||
"from": "json5@>=0.5.0 <0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "3.1.0",
|
||||
"from": "kind-of@>=3.0.2 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.1.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"lazy-cache": {
|
||||
"version": "1.0.4",
|
||||
"from": "lazy-cache@>=1.0.3 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "0.2.16",
|
||||
"from": "loader-utils@>=0.2.11 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.16.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"longest": {
|
||||
"version": "1.0.1",
|
||||
"from": "longest@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"memory-fs": {
|
||||
"version": "0.3.0",
|
||||
"from": "memory-fs@>=0.3.0 <0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "2.3.11",
|
||||
"from": "micromatch@>=2.1.5 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.3",
|
||||
"from": "minimatch@>=3.0.2 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"from": "minimist@0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"from": "mkdirp@>=0.5.0 <0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"node-libs-browser": {
|
||||
"version": "0.6.0",
|
||||
"from": "node-libs-browser@>=0.6.0 <0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-0.6.0.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"from": "isarray@0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"from": "readable-stream@>=1.1.13 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "2.0.1",
|
||||
"from": "normalize-path@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"from": "object-assign@>=4.0.1 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"object.omit": {
|
||||
"version": "2.0.1",
|
||||
"from": "object.omit@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"optimist": {
|
||||
"version": "0.6.1",
|
||||
"from": "optimist@>=0.6.0 <0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"os-browserify": {
|
||||
"version": "0.1.2",
|
||||
"from": "os-browserify@>=0.1.2 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"pako": {
|
||||
"version": "0.2.9",
|
||||
"from": "pako@>=0.2.0 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"parse-glob": {
|
||||
"version": "3.0.4",
|
||||
"from": "parse-glob@>=3.0.4 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"path-browserify": {
|
||||
"version": "0.0.0",
|
||||
"from": "path-browserify@0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"from": "path-is-absolute@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"pbkdf2-compat": {
|
||||
"version": "2.0.1",
|
||||
"from": "pbkdf2-compat@2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"preserve": {
|
||||
"version": "0.2.0",
|
||||
"from": "preserve@>=0.2.0 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.9",
|
||||
"from": "process@>=0.11.0 <0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.9.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"from": "process-nextick-args@>=1.0.6 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"prr": {
|
||||
"version": "0.0.0",
|
||||
"from": "prr@>=0.0.0 <0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"from": "punycode@>=1.2.4 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"querystring": {
|
||||
"version": "0.2.0",
|
||||
"from": "querystring@0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"querystring-es3": {
|
||||
"version": "0.2.1",
|
||||
"from": "querystring-es3@>=0.2.0 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"randomatic": {
|
||||
"version": "1.1.6",
|
||||
"from": "randomatic@>=1.1.3 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.2.2",
|
||||
"from": "readable-stream@>=2.0.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "2.1.0",
|
||||
"from": "readdirp@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"regex-cache": {
|
||||
"version": "0.4.3",
|
||||
"from": "regex-cache@>=0.4.2 <0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"repeat-element": {
|
||||
"version": "1.1.2",
|
||||
"from": "repeat-element@>=1.1.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"repeat-string": {
|
||||
"version": "1.6.1",
|
||||
"from": "repeat-string@>=1.5.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"right-align": {
|
||||
"version": "0.1.3",
|
||||
"from": "right-align@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"ripemd160": {
|
||||
"version": "0.2.0",
|
||||
"from": "ripemd160@0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-0.2.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"set-immediate-shim": {
|
||||
"version": "1.0.1",
|
||||
"from": "set-immediate-shim@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.2.6",
|
||||
"from": "sha.js@2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.2.6.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"source-list-map": {
|
||||
"version": "0.1.8",
|
||||
"from": "source-list-map@>=0.1.7 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.6",
|
||||
"from": "source-map@>=0.5.1 <0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"stream-browserify": {
|
||||
"version": "1.0.0",
|
||||
"from": "stream-browserify@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-1.0.0.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"from": "isarray@0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.1.14",
|
||||
"from": "readable-stream@>=1.0.27-1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"from": "string_decoder@>=0.10.0 <0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "3.2.3",
|
||||
"from": "supports-color@>=3.1.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"tapable": {
|
||||
"version": "0.1.10",
|
||||
"from": "tapable@>=0.1.8 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-0.1.10.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"timers-browserify": {
|
||||
"version": "1.4.2",
|
||||
"from": "timers-browserify@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"tty-browserify": {
|
||||
"version": "0.0.0",
|
||||
"from": "tty-browserify@0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "2.6.4",
|
||||
"from": "uglify-js@>=2.6.0 <2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "0.2.10",
|
||||
"from": "async@>=0.2.6 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"uglify-to-browserify": {
|
||||
"version": "1.0.2",
|
||||
"from": "uglify-to-browserify@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"url": {
|
||||
"version": "0.10.3",
|
||||
"from": "url@>=0.10.1 <0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.3.2",
|
||||
"from": "punycode@1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"util": {
|
||||
"version": "0.10.3",
|
||||
"from": "util@>=0.10.3 <0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.1",
|
||||
"from": "inherits@2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"from": "util-deprecate@>=1.0.1 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"vm-browserify": {
|
||||
"version": "0.0.4",
|
||||
"from": "vm-browserify@0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "0.2.9",
|
||||
"from": "watchpack@>=0.2.1 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.9.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "0.9.2",
|
||||
"from": "async@>=0.9.0 <0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"webpack": {
|
||||
"version": "1.13.2",
|
||||
"from": "webpack@1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-1.13.2.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"webpack-core": {
|
||||
"version": "0.6.9",
|
||||
"from": "webpack-core@>=0.6.0 <0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.4.4",
|
||||
"from": "source-map@>=0.4.1 <0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"window-size": {
|
||||
"version": "0.1.0",
|
||||
"from": "window-size@0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"from": "wordwrap@>=0.0.2 <0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "3.10.0",
|
||||
"from": "yargs@>=3.10.0 <3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
8617
package-lock.json
generated
Normal file
58
package.json
@ -1,29 +1,65 @@
|
||||
{
|
||||
"name": "crypto-pro",
|
||||
"version": "1.1.2",
|
||||
"version": "2.0.0",
|
||||
"description": "API для взаимодействия с КриптоПро",
|
||||
"main": "src/index.js",
|
||||
"main": "./lib/crypto-pro.js",
|
||||
"types": "./lib/crypto-pro.d.ts",
|
||||
"scripts": {
|
||||
"start": "node_modules/.bin/webpack --config webpack.config.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"clean": "rimraf dist lib package coverage",
|
||||
"start": "cross-env TS_CONFIG=tsconfig-es5.json webpack --watch",
|
||||
"build:uncompressed:es5": "cross-env TS_CONFIG=tsconfig-es5.json webpack",
|
||||
"build:compressed:es5": "cross-env TS_CONFIG=tsconfig-es5.json NODE_ENV=production webpack",
|
||||
"build:definition-header:es5": "cross-env TS_CONFIG=tsconfig-es5.json node definition-header.js",
|
||||
"build:es5": "npm run build:uncompressed:es5 && npm run build:compressed:es5 && npm run build:definition-header:es5",
|
||||
"build:uncompressed:esm": "cross-env TS_CONFIG=tsconfig-esm.json webpack",
|
||||
"build:definition-header:esm": "cross-env TS_CONFIG=tsconfig-esm.json node definition-header.js",
|
||||
"build:esm": "npm run build:uncompressed:esm && npm run build:definition-header:esm",
|
||||
"build": "npm run clean && npm run build:es5 && npm run build:esm",
|
||||
"package:clean": "cross-env-shell rimraf $npm_package_name-$npm_package_version.tgz",
|
||||
"package:uncompress": "cross-env-shell tar xopf $npm_package_name-$npm_package_version.tgz",
|
||||
"package": "npm run build && npm pack && npm run package:uncompress && npm run package:clean",
|
||||
"serve": "static -p 8080",
|
||||
"test": "jest --collectCoverage",
|
||||
"lint": "eslint --config .eslintrc.js './src/**/*'",
|
||||
"lint:fix": "eslint --fix --config .eslintrc.js './src/**/*'"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vgoma/crypto-pro"
|
||||
},
|
||||
"author": "vgoma <vgoma@yandex.ru>",
|
||||
"author": {
|
||||
"name": "Vitalii Goma",
|
||||
"email": "vgoma@yandex.ru",
|
||||
"url": "https://github.com/vgoma"
|
||||
},
|
||||
"keywords": [
|
||||
"crypto",
|
||||
"cryptopro",
|
||||
"crypto-pro",
|
||||
"cades",
|
||||
"КриптоПро"
|
||||
"КриптоПро",
|
||||
"Крипто ПРО"
|
||||
],
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bowser": "1.5.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"webpack": "1.13.2"
|
||||
"@types/jest": "25.1.4",
|
||||
"@types/lodash": "4.14.149",
|
||||
"@types/node": "13.9.5",
|
||||
"@typescript-eslint/eslint-plugin": "2.25.0",
|
||||
"@typescript-eslint/parser": "2.25.0",
|
||||
"cross-env": "7.0.2",
|
||||
"eslint": "6.8.0",
|
||||
"eslint-config-prettier": "6.10.1",
|
||||
"eslint-plugin-prettier": "3.1.2",
|
||||
"jest": "25.2.3",
|
||||
"prettier": "2.0.2",
|
||||
"rimraf": "3.0.2",
|
||||
"sinon": "9.0.1",
|
||||
"tar": "6.0.1",
|
||||
"ts-jest": "25.2.1",
|
||||
"ts-loader": "6.2.2",
|
||||
"typescript": "3.8.3",
|
||||
"webpack": "4.42.1",
|
||||
"webpack-cli": "3.3.11"
|
||||
}
|
||||
}
|
||||
|
23
src/__mocks__/cadesplugin.ts
Normal file
@ -0,0 +1,23 @@
|
||||
let executionFlow = null;
|
||||
|
||||
Object.defineProperty(window, 'cadesplugin', {
|
||||
writable: true,
|
||||
value: {
|
||||
set_log_level: jest.fn(),
|
||||
getLastError: jest.fn(),
|
||||
CreateObjectAsync: jest.fn(),
|
||||
__defineExecutionFlow: (newExecutionFlow): void => {
|
||||
executionFlow = newExecutionFlow;
|
||||
},
|
||||
async_spawn: jest.fn((generatorFn) => {
|
||||
const generatorIterable = generatorFn();
|
||||
let iterable = generatorIterable.next();
|
||||
|
||||
while (!iterable.done) {
|
||||
iterable = generatorIterable.next(executionFlow[iterable.value]);
|
||||
}
|
||||
|
||||
return iterable.value;
|
||||
}),
|
||||
},
|
||||
});
|
42
src/__mocks__/certificates.ts
Normal file
@ -0,0 +1,42 @@
|
||||
export const rawCertificates = [
|
||||
{
|
||||
IssuerName: [
|
||||
'CN="ООО ""Сампо-Сервис"""',
|
||||
'O="Общество с ограниченной ответственностью ""Сампо-Сервис"""',
|
||||
'OU=Удостоверяющий центр',
|
||||
'STREET="ул. Большая Разночинная, д. 14, лит. А"',
|
||||
'L=Санкт-Петербург',
|
||||
'S=78 Санкт-Петербург',
|
||||
'C=RU',
|
||||
'INN=007813317783',
|
||||
'OGRN=1057810150892',
|
||||
'E=uc@sampokey.ru',
|
||||
].join(', '),
|
||||
SubjectName: [
|
||||
'CN=Иванов Иван Иванович',
|
||||
'SN=Иванов',
|
||||
'G=Иван Иванович',
|
||||
'C=RU',
|
||||
'S=78 Санкт-Петербург',
|
||||
'L=г. Санкт-Петербург',
|
||||
'STREET="ул. Строителей, д. 25, кв. 12"',
|
||||
'SNILS=41013691319',
|
||||
'INN=943018791378',
|
||||
'E=email@example.com',
|
||||
].join(', '),
|
||||
Thumbprint: '1C6838E1316C5F0C6A126D58D081D2435A3CFC7B',
|
||||
ValidFromDate: '2019-12-06T11:58:21.000Z',
|
||||
ValidToDate: '2020-12-06T12:08:21.000Z',
|
||||
},
|
||||
];
|
||||
|
||||
export const parsedCertificates = [
|
||||
{
|
||||
name: 'Иванов Иван Иванович',
|
||||
issuerName: rawCertificates[0].IssuerName,
|
||||
subjectName: rawCertificates[0].SubjectName,
|
||||
thumbprint: rawCertificates[0].Thumbprint,
|
||||
validFrom: rawCertificates[0].ValidFromDate,
|
||||
validTo: rawCertificates[0].ValidToDate,
|
||||
},
|
||||
];
|
2
src/__mocks__/console-error.ts
Normal file
@ -0,0 +1,2 @@
|
||||
// suppress logging errors to stdout while running tests
|
||||
window.console.error = jest.fn();
|
586
src/api.js
@ -1,586 +0,0 @@
|
||||
var cryptoCommon = require('./common'),
|
||||
cryptoConstants = require('./constants'),
|
||||
_certListCache;
|
||||
|
||||
function Certificate(item) {
|
||||
this._cert = item._cert;
|
||||
this.thumbprint = item.thumbprint;
|
||||
this.subjectName = item.subjectName;
|
||||
this.issuerName = item.issuerName;
|
||||
this.validFrom = item.validFrom;
|
||||
this.validTo = item.validTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, валиден ли сертификат
|
||||
* */
|
||||
Certificate.prototype.isValid = function isValid() {
|
||||
var cert = this._cert;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function isValid() {
|
||||
var result;
|
||||
|
||||
try {
|
||||
result = 'yield' + cert.IsValid();
|
||||
result = 'yield' + result.Result;
|
||||
} catch (err) {
|
||||
reject('Ошибка при проверке сертификата: ', err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(result);
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Достает указанное свойство у сертификата
|
||||
* */
|
||||
Certificate.prototype.getProp = function (propName) {
|
||||
var cert = this._cert;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function getProp() {
|
||||
var result;
|
||||
|
||||
try {
|
||||
result = 'yield' + cert[propName];
|
||||
} catch (err) {
|
||||
reject('Ошибка при обращении к свойству сертификата: ', err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(result);
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Экспорт base64 представления сертификата пользователя
|
||||
* */
|
||||
Certificate.prototype.exportBase64 = function exportBase64() {
|
||||
var cert = this._cert;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function exportBase64() {
|
||||
var base64;
|
||||
|
||||
try {
|
||||
base64 = 'yield' + cert.Export(0);
|
||||
} catch (err) {
|
||||
reject('Ошибка при экспорте сертификата: ', err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(base64);
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Возвращает информацию об алгоритме
|
||||
* */
|
||||
Certificate.prototype.getAlgorithm = function getAlgorithm() {
|
||||
var cert = this._cert;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function getAlgorithm() {
|
||||
var result = {},
|
||||
algorithm;
|
||||
|
||||
try {
|
||||
algorithm = 'yield' + cert.PublicKey();
|
||||
algorithm = 'yield' + algorithm.Algorithm;
|
||||
|
||||
result.algorithm = 'yield' + algorithm.FriendlyName;
|
||||
result.oid = 'yield' + algorithm.Value;
|
||||
} catch (err) {
|
||||
reject('Ошибка при получении алгоритма: ', err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(result);
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Разбирает SubjectName сертификата по тэгам
|
||||
* */
|
||||
Certificate.prototype.getOwnerInfo = function getOwnerInfo() {
|
||||
return getCertInfo.call(this, cryptoCommon.subjectNameTagsTranslations, 'SubjectName');
|
||||
};
|
||||
|
||||
/**
|
||||
* Разбирает IssuerName сертификата по тэгам
|
||||
* */
|
||||
Certificate.prototype.getIssuerInfo = function getIssuerInfo() {
|
||||
return getCertInfo.call(this, cryptoCommon.issuerNameTagsTranslations, 'IssuerName');
|
||||
};
|
||||
|
||||
/**
|
||||
* Получение OID сертификата
|
||||
*
|
||||
* @returns {Array} Возвращает массив OID (улучшенного ключа)
|
||||
* */
|
||||
Certificate.prototype.getExtendedKeyUsage = function getExtendedKeyUsage() {
|
||||
var cert = this._cert;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function getExtendedKeyUsage() {
|
||||
var OIDS = [],
|
||||
count,
|
||||
item;
|
||||
|
||||
try {
|
||||
count = 'yield' + cert.ExtendedKeyUsage();
|
||||
count = 'yield' + count.EKUs;
|
||||
count = 'yield' + count.Count;
|
||||
|
||||
if (count > 0) {
|
||||
while (count > 0) {
|
||||
item = 'yield' + cert.ExtendedKeyUsage();
|
||||
item = 'yield' + item.EKUs;
|
||||
item = 'yield' + item.Item(count);
|
||||
item = 'yield' + item.OID;
|
||||
|
||||
OIDS.push(item);
|
||||
|
||||
count--;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
reject('Ошибка при получении ОИД\'ов: ', err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(OIDS);
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
Certificate.prototype.getDecodedExtendedKeyUsage = cryptoCommon.getDecodedExtendedKeyUsage;
|
||||
|
||||
Certificate.prototype.hasExtendedKeyUsage = cryptoCommon.hasExtendedKeyUsage;
|
||||
|
||||
/**
|
||||
* Проверяет корректность настроек ЭП на машине
|
||||
* */
|
||||
function isValidEDSSettings() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function isValidEDSSettings() {
|
||||
var result;
|
||||
|
||||
try {
|
||||
result = 'yield' + cryptoCommon.createObj('CAdESCOM.About');
|
||||
} catch (error) {
|
||||
reject('Настройки ЭП на данной машине не верны');
|
||||
}
|
||||
|
||||
resolve();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить сертификат в формате cades по хэшу
|
||||
* */
|
||||
function getCadesCert(hash) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function getCadesCert() {
|
||||
var oStore,
|
||||
certs,
|
||||
certCnt,
|
||||
cert;
|
||||
|
||||
// Получаем доступ к хранилищу
|
||||
try {
|
||||
oStore = 'yield' + cryptoCommon.createObj('CAdESCOM.Store');
|
||||
} catch (err) {
|
||||
reject('Ошибка при попытке доступа к хранилищу: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!oStore) {
|
||||
reject('Не удалось получить доступ к хранилищу сертификатов');
|
||||
return;
|
||||
}
|
||||
|
||||
// Открываем хранилище
|
||||
try {
|
||||
void('yield' + oStore.Open(
|
||||
cadesplugin.CAPICOM_CURRENT_USER_STORE,
|
||||
cadesplugin.CAPICOM_MY_STORE,
|
||||
cadesplugin.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED
|
||||
));
|
||||
} catch (err) {
|
||||
reject('Ошибка при открытии хранилища: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Получаем доступ к сертификатам
|
||||
try {
|
||||
certs = 'yield' + oStore.Certificates;
|
||||
certCnt = 'yield' + certs.Count;
|
||||
} catch (err) {
|
||||
reject('Ошибка получения списка сертификатов: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!certCnt) {
|
||||
reject('Нет доступных сертификатов');
|
||||
return;
|
||||
}
|
||||
|
||||
// Получаем сертификат по хэшу
|
||||
try {
|
||||
certs = 'yield' + certs.Find(cadesplugin.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, hash);
|
||||
|
||||
if (certs.Count) {
|
||||
cert = 'yield' + certs.Item(1);
|
||||
} else {
|
||||
throw new Error(hash);
|
||||
}
|
||||
} catch (err) {
|
||||
reject('Не удалось получить сертификат по хэшу: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
oStore.Close();
|
||||
|
||||
resolve(cert);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Разбирает информацию сертификата по тэгам
|
||||
* */
|
||||
function getCertInfo(tags, propName) {
|
||||
var cert = this._cert;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function getCertInfo() {
|
||||
var propInfo;
|
||||
|
||||
try {
|
||||
propInfo = 'yield' + cert[propName];
|
||||
} catch (err) {
|
||||
reject('Ошибка при извлечении данных из сертификата: ', err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(cryptoCommon.parseCertInfo(tags, propInfo));
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список сертификатов, доступных в системе
|
||||
*
|
||||
* @param {Boolean} [resetCache=false] -- нужно ли сбросить кэш списка сертификатов
|
||||
* @returns {Promise} -- со списком сертификатов {Array}
|
||||
* */
|
||||
function getCertsList(resetCache) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (!resetCache && _certListCache) {
|
||||
resolve(_certListCache);
|
||||
return;
|
||||
}
|
||||
|
||||
eval(cryptoCommon.generateAsyncFn(function getCertsList() {
|
||||
var result = [],
|
||||
oStore,
|
||||
certs,
|
||||
count,
|
||||
item;
|
||||
|
||||
// Получаем доступ к хранилищу
|
||||
try {
|
||||
oStore = 'yield' + cryptoCommon.createObj('CAdESCOM.Store');
|
||||
} catch (err) {
|
||||
reject('Ошибка при попытке доступа к хранилищу: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Открываем хранилище
|
||||
try {
|
||||
void('yield' + oStore.Open(
|
||||
cadesplugin.CAPICOM_CURRENT_USER_STORE,
|
||||
cadesplugin.CAPICOM_MY_STORE,
|
||||
cadesplugin.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED
|
||||
));
|
||||
} catch (err) {
|
||||
reject('Ошибка при открытии хранилища: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Получаем доступ к сертификатам
|
||||
try {
|
||||
certs = 'yield' + oStore.Certificates;
|
||||
|
||||
if (certs) {
|
||||
certs = 'yield' + certs.Find(cadesplugin.CAPICOM_CERTIFICATE_FIND_TIME_VALID);
|
||||
/**
|
||||
* Не рассматриваются сертификаты, в которых отсутствует закрытый ключ
|
||||
* или не действительны на данный момент
|
||||
* */
|
||||
certs = 'yield' + certs.Find(
|
||||
cadesplugin.CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY,
|
||||
cryptoConstants.PropId.CAPICOM_PROPID_KEY_PROV_INFO
|
||||
);
|
||||
|
||||
count = 'yield' + certs.Count;
|
||||
}
|
||||
} catch (err) {
|
||||
reject('Ошибка получения списка сертификатов: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
reject('Нет доступных сертификатов');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
while (count) {
|
||||
item = 'yield' + certs.Item(count);
|
||||
|
||||
result.push(new Certificate({
|
||||
_cert: 'yield' + item,
|
||||
thumbprint: 'yield' + item.Thumbprint,
|
||||
subjectName: 'yield' + item.SubjectName,
|
||||
issuerName: 'yield' + item.IssuerName,
|
||||
validFrom: 'yield' + item.ValidFromDate,
|
||||
validTo: 'yield' + item.ValidToDate
|
||||
}));
|
||||
|
||||
count--;
|
||||
}
|
||||
} catch (err) {
|
||||
reject('Ошибка обработки сертификатов: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
oStore.Close();
|
||||
|
||||
_certListCache = cryptoCommon.prepareCertsInfo(result);
|
||||
|
||||
resolve(_certListCache);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить сертификат по хэшу
|
||||
* */
|
||||
function getCert(hash) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (!hash) {
|
||||
reject('Хэш не указан');
|
||||
return;
|
||||
}
|
||||
|
||||
getCertsList().then(function (list) {
|
||||
var foundCert;
|
||||
|
||||
list.some(function (cert) {
|
||||
if (hash === cert.thumbprint) {
|
||||
foundCert = cert;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (foundCert) {
|
||||
resolve(foundCert);
|
||||
} else {
|
||||
reject('Сертификат с хэшем: "' + hash + '" не найден');
|
||||
}
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает подпись base64 строки по hash'у сертификата
|
||||
*
|
||||
* @param {String} hash -- fingerprint (thumbprint) сертификата
|
||||
* @param {String} dataBase64 -- строковые данные в формате base64
|
||||
* @param {Boolean} signType -- тип подписи открепленная (true) / присоединенная (false) (default: true)
|
||||
* @returns {Promise} -- обещание, которое зарезолвится с данными о подписи {String}
|
||||
* */
|
||||
function signData(hash, dataBase64, signType) {
|
||||
signType = typeof signType === 'undefined' ? true : Boolean(signType);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
getCadesCert(hash).then(function (cert) {
|
||||
eval(cryptoCommon.generateAsyncFn(function signData() {
|
||||
var clientTime = new Date(),
|
||||
oAttrs,
|
||||
oSignedData,
|
||||
oSigner,
|
||||
attrs,
|
||||
signature;
|
||||
|
||||
try {
|
||||
oAttrs = 'yield' + cryptoCommon.createObj('CADESCOM.CPAttribute');
|
||||
oSignedData = 'yield' + cryptoCommon.createObj('CAdESCOM.CadesSignedData');
|
||||
oSigner = 'yield' + cryptoCommon.createObj('CAdESCOM.CPSigner');
|
||||
} catch (error) {
|
||||
reject('Ошибка при инициализации подписи: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
clientTime = cryptoCommon.getDateObj(clientTime);
|
||||
|
||||
try {
|
||||
void('yield' + oAttrs.propset_Name(cryptoConstants.Time.AUTHENTICATED_ATTRIBUTE_SIGNING_TIME));
|
||||
void('yield' + oAttrs.propset_Value(clientTime));
|
||||
} catch (err) {
|
||||
reject('Ошибка при установке данных подписи: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Задаем настройки для подписи
|
||||
try {
|
||||
void('yield' + oSigner.propset_Certificate(cert));
|
||||
attrs = 'yield' + oSigner.AuthenticatedAttributes2;
|
||||
void('yield' + attrs.Add(oAttrs));
|
||||
void('yield' + oSignedData.propset_ContentEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY));
|
||||
void('yield' + oSignedData.propset_Content(dataBase64));
|
||||
void('yield' + oSigner.propset_Options(cadesplugin.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY));
|
||||
} catch (err) {
|
||||
reject('Не удалось установить настройки для подписи: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
signature = 'yield' + oSignedData.SignCades(
|
||||
oSigner,
|
||||
cadesplugin.CADESCOM_CADES_BES,
|
||||
signType
|
||||
);
|
||||
} catch (err) {
|
||||
reject('Не удалось создать подпись: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(signature);
|
||||
}));
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает подпись XML строки по hash'у сертификата
|
||||
*
|
||||
* @param {String} hash -- fingerprint (thumbprint) сертификата
|
||||
* @param {String} dataXML -- данные в формате XML
|
||||
* @returns {Promise} -- обещание, которое зарезолвится с данными о подписи {String}
|
||||
* */
|
||||
function signDataXML(hash, dataXML) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
getCadesCert(hash).then(function (cert) {
|
||||
eval(cryptoCommon.generateAsyncFn(function signDataXML() {
|
||||
var cnts = cryptoConstants,
|
||||
oSigner,
|
||||
signerXML,
|
||||
signature;
|
||||
|
||||
try {
|
||||
oSigner = 'yield' + cryptoCommon.createObj('CAdESCOM.CPSigner');
|
||||
signerXML = 'yield' + cryptoCommon.createObj('CAdESCOM.SignedXML');
|
||||
} catch (err) {
|
||||
reject('Ошибка при инициализации подписи: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Задаем настройки для подписи
|
||||
try {
|
||||
void('yield' + oSigner.propset_Certificate(cert));
|
||||
// Добавляем данные для подписи
|
||||
void('yield' + signerXML.propset_Content(dataXML));
|
||||
// Устанавливаем тип подписи
|
||||
void('yield' + signerXML.propset_SignatureType(cnts.SignatureType.CADESCOM_XML_SIGNATURE_TYPE_ENVELOPED));
|
||||
// Устанавливаем алгоритм подписи
|
||||
void('yield' + signerXML.propset_SignatureMethod(cnts.GostXmlDSigUrls.XmlDsigGost3410Url));
|
||||
// Устанавливаем алгоритм хэширования
|
||||
void('yield' + signerXML.propset_DigestMethod(cnts.GostXmlDSigUrls.XmlDsigGost3411Url));
|
||||
} catch (err) {
|
||||
reject('Не удалось установить настройки для подписи: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
signature = 'yield' + signerXML.Sign(oSigner);
|
||||
} catch (err) {
|
||||
reject('Не удалось создать подпись: ' + err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(signature);
|
||||
}));
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает информацию о версии CSP и плагина
|
||||
* */
|
||||
function getSystemInfo() {
|
||||
var sysInfo = cryptoCommon.getEnvInfo();
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
eval(cryptoCommon.generateAsyncFn(function getSystemInfo() {
|
||||
var e;
|
||||
|
||||
try {
|
||||
e = 'yield' + cryptoCommon.createObj('CAdESCOM.About');
|
||||
|
||||
sysInfo.cadesVersion = 'yield' + e.PluginVersion;
|
||||
// Возможен вызов в ранних версиях в виде sysInfo.cspVersion = 'yield' + e.CSPVersion('', 75);
|
||||
sysInfo.cspVersion = 'yield' + e.CSPVersion();
|
||||
|
||||
if (!sysInfo.cadesVersion) {
|
||||
sysInfo.cadesVersion = 'yield' + e.Version;
|
||||
}
|
||||
|
||||
sysInfo.cadesVersion = 'yield' + sysInfo.cadesVersion.toString();
|
||||
sysInfo.cspVersion = 'yield' + sysInfo.cspVersion.toString();
|
||||
|
||||
resolve(sysInfo);
|
||||
} catch (err) {
|
||||
reject('Ошибка при получении информации о системе: ', err.message);
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Promise обертка для синхронного вызова проверки версии CSP
|
||||
* */
|
||||
function isValidCSPVersion(version) {
|
||||
return new Promise(function (resolve) {
|
||||
resolve(cryptoCommon.isValidCSPVersion(version));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Promise обертка для синхронного вызова проверки версии плагина
|
||||
* */
|
||||
function isValidCadesVersion(version) {
|
||||
return new Promise(function (resolve) {
|
||||
resolve(cryptoCommon.isValidCadesVersion(version));
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isValidEDSSettings: isValidEDSSettings,
|
||||
getCertsList: getCertsList,
|
||||
getCert: getCert,
|
||||
signData: signData,
|
||||
signDataXML: signDataXML,
|
||||
getSystemInfo: getSystemInfo,
|
||||
isValidCSPVersion: isValidCSPVersion,
|
||||
isValidCadesVersion: isValidCadesVersion
|
||||
};
|
70
src/api/certificate/certificate.test.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import 'cadesplugin';
|
||||
import { parsedCertificates } from '../../__mocks__/certificates';
|
||||
import { ISSUER_TAGS_TRANSLATIONS, SUBJECT_TAGS_TRANSLATIONS } from '../../constants';
|
||||
import { exportBase64 } from './exportBase64';
|
||||
import { getAlgorithm } from './getAlgorithm';
|
||||
import { getCadesProp } from './getCadesProp';
|
||||
import { getDecodedExtendedKeyUsage } from './getDecodedExtendedKeyUsage';
|
||||
import { getExtendedKeyUsage } from './getExtendedKeyUsage';
|
||||
import { getInfo } from './getInfo';
|
||||
import { hasExtendedKeyUsage } from './hasExtendedKeyUsage';
|
||||
import { isValid } from './isValid';
|
||||
import { Certificate } from './certificate';
|
||||
|
||||
const [parsedCertificateMock] = parsedCertificates;
|
||||
const oidsMock = ['oid 1', 'oid 2'];
|
||||
|
||||
jest.mock('./isValid', () => ({ isValid: jest.fn(() => 'isValid') }));
|
||||
jest.mock('./getCadesProp', () => ({ getCadesProp: jest.fn(() => 'getCadesProp') }));
|
||||
jest.mock('./exportBase64', () => ({ exportBase64: jest.fn(() => 'exportBase64') }));
|
||||
jest.mock('./getAlgorithm', () => ({ getAlgorithm: jest.fn(() => 'getAlgorithm') }));
|
||||
jest.mock('./getInfo', () => ({ getInfo: jest.fn(() => 'getInfo') }));
|
||||
jest.mock('./getExtendedKeyUsage', () => ({ getExtendedKeyUsage: jest.fn(() => 'getExtendedKeyUsage') }));
|
||||
jest.mock('./getDecodedExtendedKeyUsage', () => ({
|
||||
getDecodedExtendedKeyUsage: jest.fn(() => 'getDecodedExtendedKeyUsage'),
|
||||
}));
|
||||
jest.mock('./hasExtendedKeyUsage', () => ({ hasExtendedKeyUsage: jest.fn(() => 'hasExtendedKeyUsage') }));
|
||||
|
||||
beforeEach(() => {
|
||||
(isValid as jest.Mock).mockClear();
|
||||
(getCadesProp as jest.Mock).mockClear();
|
||||
(exportBase64 as jest.Mock).mockClear();
|
||||
(getAlgorithm as jest.Mock).mockClear();
|
||||
(getInfo as jest.Mock).mockClear();
|
||||
(getExtendedKeyUsage as jest.Mock).mockClear();
|
||||
(getDecodedExtendedKeyUsage as jest.Mock).mockClear();
|
||||
(hasExtendedKeyUsage as jest.Mock).mockClear();
|
||||
});
|
||||
|
||||
const certificate = new Certificate(
|
||||
null,
|
||||
parsedCertificateMock.name,
|
||||
parsedCertificateMock.issuerName,
|
||||
parsedCertificateMock.subjectName,
|
||||
parsedCertificateMock.thumbprint,
|
||||
parsedCertificateMock.validFrom,
|
||||
parsedCertificateMock.validTo,
|
||||
);
|
||||
|
||||
describe('getInfo', () => {
|
||||
test("calls external APIs for each method and passes it's results outside", async () => {
|
||||
expect(certificate.isValid()).toEqual('isValid');
|
||||
expect(isValid).toHaveBeenCalledTimes(1);
|
||||
expect(certificate.getCadesProp('property name')).toEqual('getCadesProp');
|
||||
expect(getCadesProp).toHaveBeenCalledWith('property name');
|
||||
expect(certificate.exportBase64()).toEqual('exportBase64');
|
||||
expect(exportBase64).toHaveBeenCalledTimes(1);
|
||||
expect(certificate.getAlgorithm()).toEqual('getAlgorithm');
|
||||
expect(getAlgorithm).toHaveBeenCalledTimes(1);
|
||||
expect(certificate.getOwnerInfo()).toEqual('getInfo');
|
||||
expect(getInfo).toHaveBeenCalledWith(SUBJECT_TAGS_TRANSLATIONS, 'SubjectName');
|
||||
expect(certificate.getIssuerInfo()).toEqual('getInfo');
|
||||
expect(getInfo).toHaveBeenCalledWith(ISSUER_TAGS_TRANSLATIONS, 'IssuerName');
|
||||
expect(certificate.getExtendedKeyUsage()).toEqual('getExtendedKeyUsage');
|
||||
expect(getExtendedKeyUsage).toHaveBeenCalledTimes(1);
|
||||
expect(certificate.getDecodedExtendedKeyUsage()).toEqual('getDecodedExtendedKeyUsage');
|
||||
expect(getDecodedExtendedKeyUsage).toHaveBeenCalledTimes(1);
|
||||
expect(certificate.hasExtendedKeyUsage(oidsMock)).toEqual('hasExtendedKeyUsage');
|
||||
expect(hasExtendedKeyUsage).toHaveBeenCalledWith(oidsMock);
|
||||
});
|
||||
});
|