├── LICENSE
├── README.md
├── dev
├── CryptoConstant.js
├── CryptoMessage.js
└── CryptoPro.js
├── package.json
└── src
├── cryptoAPI.js
└── nativeBridge.js
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Alexander
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CryptoProAPI
2 | Простое API для работы с КриптоПро ЭЦП Browser plug-in
3 |
4 |
5 | ### Вкратце
6 | 1. Подключение
7 | 2. Получение информации из ключа
8 | 3. Получение всех сертификатов установленных на компьютере
9 | 4. Вычисление хеш
10 | 5. Создание подписи
11 | 6. Верификация подписи
12 |
13 |
14 | ### Использование
15 |
16 | #### Подключение
17 |
18 | Чтобы эта штура зарботала, достаточно подключить [один файл](https://github.com/shanhaichik/CryptoProAPI/blob/master/src/cryptoAPI.js).
19 |
20 | ```html
21 |
22 | ```
23 |
24 | #### Получение информации из ключа
25 |
26 | ##### Метод getByHash
27 | Получение сертификата по хешу ключа (fingerprint)
28 |
29 | ```javascript
30 | var key = CryptoPro.getByHash('000000000000000000000000').get();
31 |
32 | // или
33 |
34 | var key = CryptoPro.getByHash('000000000000000000000000');
35 | key.get();
36 | ```
37 |
38 | ##### Метод getExtendedKeyUsage
39 | Получение информации из ключа
40 | Получение OID сертификата (улучшенного ключа)
41 |
42 | ```javascript
43 | var key = CryptoPro.getByHash('000000000000000000000000');
44 |
45 | key.getExtendedKeyUsage();
46 | ```
47 |
48 | ##### Метод hasKeyUsageOID
49 | Проверка наличия OID или группы OID в ключе
50 |
51 | ```javascript
52 | key.hasKeyUsageOID('1.3.6.1.5.5.7.3.2');
53 |
54 | //или
55 |
56 | key.hasKeyUsageOID(["1.3.6.1.5.5.7.3.4", "1.3.6.1.5.5.7.3.2", "1.2.643.2.2.34.6"]);
57 | ```
58 |
59 | ##### Метод isKeyValid
60 | Получение информации валидный ключ или нет
61 |
62 | ```javascript
63 | key.isKeyValid();
64 | ```
65 |
66 | ##### Метод getOwner
67 | Парсит SubjectName ключа по тегам
68 |
69 | ```javascript
70 | key.getOwner();
71 | ```
72 |
73 | ##### Метод getIssuer
74 | Парсит IssuerName ключа по тегам
75 |
76 | ```javascript
77 | key.getIssuer();
78 | ```
79 |
80 | ##### Метод getAlgorithm
81 | Информауия об алгоритме
82 |
83 | ```javascript
84 | key.getAlgorithm();
85 | ```
86 |
87 | #### Получение всех сертификатов установленных на компьютере.
88 |
89 | ##### Метод getList
90 | ```javascript
91 | CryptoPro.getList();
92 | ```
93 |
94 |
95 | #### Создание ЭП
96 |
97 | ##### Метод SignPkcs7
98 | Создание ЭП в формате Pkcs7
99 |
100 | Параметры:
101 | * Хеш / Fingerprint {String}
102 | * Данные для подписи {String}
103 | * Прикрепленная / отсоединенная {Boolean, default:false}
104 |
105 | ```javascript
106 | CryptoPro.SignPkcs7(hash, signData, signType);
107 | ```
108 |
109 | ##### Метод SignXML
110 | Создание ЭП в формате XML
111 |
112 | Параметры:
113 | * Хеш / Fingerprint {String}
114 | * Данные для подписи {String}
115 |
116 | ```javascript
117 | CryptoPro.SignXML(hash, signData);
118 | ```
119 |
120 |
121 | ##### Метод SignHash
122 | Создание ЭП по хэш значению
123 |
124 | Параметры:
125 | * Хеш / Fingerprint {String}
126 | * Вычисленный хеш данных {String}
127 | * Отсоединенная {Boolean, default:false}
128 |
129 | ```javascript
130 | CryptoPro.SignHash(hash, hashValue, signType);
131 | ```
132 |
133 |
134 | #### Вычисление хеш
135 |
136 | ##### Метод getHash
137 | Вычисление хеш значеняи данных по Гост.
138 |
139 | Параметры:
140 | * Строка для вычисления хеш {String}
141 | * Вычисления хеш бинарных данных {Boolean, default:false}
142 |
143 | ```javascript
144 | CryptoPro.getHash(str, binary);
145 | ```
146 |
147 |
148 | #### Верификация ЭП
149 |
150 | ##### Метод getHash
151 | Верификация подписи в формате Pkcs7
152 |
153 | Параметры:
154 | * Строка с подписью {String}
155 | * Тип подписи открепленная/присоединенная {Boolean, default:false}
156 |
157 | ```javascript
158 | CryptoPro.getHash(signature, signType);
159 | ```
160 |
161 | ##### Метод VerifyXML
162 | Верификация подписи в формате XML
163 |
164 | Параметры:
165 | * Строка с подписью {String}
166 |
167 | ```javascript
168 | CryptoPro.VerifyXML(signature);
169 | ```
170 |
171 | ##### Метод VerifyHash
172 | Верификация подписипо хэш значению
173 |
174 | Параметры:
175 | * Хеш / Fingerprint {String}
176 | * Вычисленный хеш данных {String}
177 | * Строка с подписью {String}
178 | * Отсоединенная {Boolean, default:false}
179 |
180 | ```javascript
181 | CryptoPro.VerifyHash(hash, hashValue, signature, signType);
182 | ```
183 |
184 | #### Любые замечания, баги и предложения приветствуются и дают в карму +1.
--------------------------------------------------------------------------------
/dev/CryptoConstant.js:
--------------------------------------------------------------------------------
1 | var CryptoConstant = {};
2 |
3 | // CAPICOM_STORE_LOCATION enumeration
4 | CryptoConstant.StoreLocation = {
5 | CAPICOM_MEMORY_STORE: 0,
6 | CAPICOM_LOCAL_MACHINE_STORE: 1,
7 | CAPICOM_CURRENT_USER_STORE: 2,
8 | CAPICOM_ACTIVE_DIRECTORY_USER_STORE: 3,
9 | CAPICOM_SMART_CARD_USER_STORE: 4
10 | };
11 |
12 | // CAPICOM_STORE_OPEN_MODE enumeration
13 | CryptoConstant.StoreOpenMode = {
14 | CAPICOM_STORE_OPEN_READ_ONLY: 0,
15 | CAPICOM_STORE_OPEN_READ_WRITE: 1,
16 | CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED: 2,
17 | CAPICOM_STORE_OPEN_EXISTING_ONLY: 128,
18 | CAPICOM_STORE_OPEN_INCLUDE_ARCHIVED: 256
19 | };
20 |
21 | // CAPICOM_CERTIFICATE_FIND_TYPE enumeration
22 | CryptoConstant.CertFindType = {
23 | CAPICOM_CERTIFICATE_FIND_SHA1_HASH: 0,
24 | CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME: 1,
25 | CAPICOM_CERTIFICATE_FIND_ISSUER_NAME: 2,
26 | CAPICOM_CERTIFICATE_FIND_ROOT_NAME: 3,
27 | CAPICOM_CERTIFICATE_FIND_TEMPLATE_NAME: 4,
28 | CAPICOM_CERTIFICATE_FIND_EXTENSION: 5,
29 | CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY: 6,
30 | CAPICOM_CERTIFICATE_FIND_APPLICATION_POLICY: 7,
31 | CAPICOM_CERTIFICATE_FIND_CERTIFICATE_POLICY: 8,
32 | CAPICOM_CERTIFICATE_FIND_TIME_VALID: 9,
33 | CAPICOM_CERTIFICATE_FIND_TIME_NOT_YET_VALID: 10,
34 | CAPICOM_CERTIFICATE_FIND_TIME_EXPIRED: 11,
35 | CAPICOM_CERTIFICATE_FIND_KEY_USAGE: 12
36 | };
37 |
38 | CryptoConstant.Time = {
39 | AUTHENTICATED_ATTRIBUTE_SIGNING_TIME: 0
40 | };
41 |
42 | CryptoConstant.Check = {
43 | CHECK_NONE: 0,
44 | CHECK_TRUSTED_ROOT: 1,
45 | CHECK_TIME_VALIDITY: 2,
46 | CHECK_SIGNATURE_VALIDITY: 4,
47 | CHECK_ONLINE_REVOCATION_STATUS: 8,
48 | CHECK_OFFLINE_REVOCATION_STATUS: 16,
49 | TRUST_IS_NOT_TIME_VALID: 1,
50 | TRUST_IS_NOT_TIME_NESTED: 2,
51 | TRUST_IS_REVOKED: 4,
52 | TRUST_IS_NOT_SIGNATURE_VALID: 8,
53 | TRUST_IS_NOT_VALID_FOR_USAGE: 16,
54 | TRUST_IS_UNTRUSTED_ROOT: 32,
55 | TRUST_REVOCATION_STATUS_UNKNOWN: 64,
56 | TRUST_IS_CYCLIC: 128,
57 | TRUST_IS_PARTIAL_CHAIN: 65536,
58 | TRUST_CTL_IS_NOT_TIME_VALID: 131072,
59 | TRUST_CTL_IS_NOT_SIGNATURE_VALID: 262144,
60 | TRUST_CTL_IS_NOT_VALID_FOR_USAGE: 524288,
61 | };
62 |
63 | // CAPICOM_PROPID enumeration
64 | CryptoConstant.PropId = {
65 | CAPICOM_PROPID_UNKNOWN: 0,
66 | CAPICOM_PROPID_KEY_PROV_HANDLE: 1,
67 | CAPICOM_PROPID_KEY_PROV_INFO: 2,
68 | CAPICOM_PROPID_SHA1_HASH: 3,
69 | CAPICOM_PROPID_HASH_PROP: 3,
70 | CAPICOM_PROPID_MD5_HASH: 4,
71 | CAPICOM_PROPID_KEY_CONTEXT: 5,
72 | CAPICOM_PROPID_KEY_SPEC: 6,
73 | CAPICOM_PROPID_IE30_RESERVED: 7,
74 | CAPICOM_PROPID_PUBKEY_HASH_RESERVED: 8,
75 | CAPICOM_PROPID_ENHKEY_USAGE: 9,
76 | CAPICOM_PROPID_CTL_USAGE: 9,
77 | CAPICOM_PROPID_NEXT_UPDATE_LOCATION: 10,
78 | CAPICOM_PROPID_FRIENDLY_NAME: 11,
79 | CAPICOM_PROPID_PVK_FILE: 12,
80 | CAPICOM_PROPID_DESCRIPTION: 13,
81 | CAPICOM_PROPID_ACCESS_STATE: 14,
82 | CAPICOM_PROPID_SIGNATURE_HASH: 15,
83 | CAPICOM_PROPID_SMART_CARD_DATA: 16,
84 | CAPICOM_PROPID_EFS: 17,
85 | CAPICOM_PROPID_FORTEZZA_DATA: 18,
86 | CAPICOM_PROPID_ARCHIVED: 19,
87 | CAPICOM_PROPID_KEY_IDENTIFIER: 20,
88 | CAPICOM_PROPID_AUTO_ENROLL: 21,
89 | CAPICOM_PROPID_PUBKEY_ALG_PARA: 22,
90 | CAPICOM_PROPID_CROSS_CERT_DIST_POINTS: 23,
91 | CAPICOM_PROPID_ISSUER_PUBLIC_KEY_MD5_HASH: 24,
92 | CAPICOM_PROPID_SUBJECT_PUBLIC_KEY_MD5_HASH: 25,
93 | CAPICOM_PROPID_ENROLLMENT: 26,
94 | CAPICOM_PROPID_DATE_STAMP: 27,
95 | CAPICOM_PROPID_ISSUER_SERIAL_NUMBER_MD5_HASH: 28,
96 | CAPICOM_PROPID_SUBJECT_NAME_MD5_HASH: 29,
97 | CAPICOM_PROPID_EXTENDED_ERROR_INFO: 30,
98 | CAPICOM_PROPID_RENEWAL: 64,
99 | CAPICOM_PROPID_ARCHIVED_KEY_HASH: 65,
100 | CAPICOM_PROPID_FIRST_RESERVED: 66,
101 | CAPICOM_PROPID_LAST_RESERVED: 0x00007FFF,
102 | CAPICOM_PROPID_FIRST_USER: 0x00008000,
103 | CAPICOM_PROPID_LAST_USER: 0x0000FFFF
104 | };
105 |
106 | // CADESCOM_XML_SIGNATURE_TYPE enumeration
107 | CryptoConstant.SignatureType = {
108 | CADESCOM_XML_SIGNATURE_TYPE_ENVELOPED: 0,
109 | CADESCOM_XML_SIGNATURE_TYPE_ENVELOPING: 1,
110 | CADESCOM_XML_SIGNATURE_TYPE_TEMPLATE: 2
111 | };
112 |
113 | // CADESCOM_HASH_ALGORITHM enumeration
114 | CryptoConstant.HashAlgorithm = {
115 | CADESCOM_HASH_ALGORITHM_CP_GOST_3411: 100,
116 | CADESCOM_HASH_ALGORITHM_MD2: 1,
117 | CADESCOM_HASH_ALGORITHM_MD4: 2,
118 | CADESCOM_HASH_ALGORITHM_MD5: 3,
119 | CADESCOM_HASH_ALGORITHM_SHA_256: 4,
120 | CADESCOM_HASH_ALGORITHM_SHA_384: 5,
121 | CADESCOM_HASH_ALGORITHM_SHA_512: 6,
122 | CADESCOM_HASH_ALGORITHM_SHA1: 0
123 | };
124 |
125 | CryptoConstant.CadesType = {
126 | CADESCOM_CADES_DEFAULT: 0,
127 | CADESCOM_CADES_BES: 1,
128 | CADESCOM_CADES_X_LONG_TYPE_1: 0x5d
129 | };
130 |
131 | CryptoConstant.ContentEncoding = {
132 | CADESCOM_BASE64_TO_BINARY: 0x01,
133 | CADESCOM_STRING_TO_UCS2LE: 0x00
134 | };
135 |
136 | CryptoConstant.StoreNames = {
137 | CAPICOM_MY_STORE: "My"
138 | };
139 |
140 | CryptoConstant.Chain = {
141 | CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT: 0,
142 | CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN: 1,
143 | CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY: 2
144 | };
145 |
146 | CryptoConstant.GostXmlDSigUrls = {
147 | XmlDsigGost3410Url: "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102001-gostr3411",
148 | XmlDsigGost3411Url: "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr3411",
149 | XmlDsigGost3410UrlObsolete: "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411",
150 | XmlDsigGost3411UrlObsolete: "http://www.w3.org/2001/04/xmldsig-more#gostr3411"
151 | };
152 |
153 |
154 |
155 |
156 | if (typeof define === 'function' && typeof define.amd !== 'undefined') {
157 | define('CryptoConstant', CryptoConstant);
158 | }
159 |
160 | if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
161 | module.exports = CryptoConstant;
162 | }
163 | else {
164 | window.CryptoConstant = CryptoConstant;
165 | }
--------------------------------------------------------------------------------
/dev/CryptoMessage.js:
--------------------------------------------------------------------------------
1 | var CryptoMessage = {
2 |
3 | noCertificate: 'В хранилище нет ни одного сертификата',
4 |
5 | noHashCertificate: 'Не удалось найти сертификат в хранилище по Hash',
6 |
7 | noCertificatesStore: 'В хранилище не найдено ни одного сертификата',
8 |
9 | cantCreateSignature: 'Не получилось создать, подпись в формате Pkcs7 из за ошибки:',
10 |
11 | cantCreateSignatureXML: 'Не получилось создать, подпись в формате XML из за ошибки:',
12 |
13 | cantCreateSignatureHash: 'Не получилось создать, подпись Hash значения из за ошибки:',
14 |
15 | noPlugin: 'Не установлен браузер плагин или Крипто Про CSP',
16 |
17 | verifyPkcs7: 'Верификация подписи формата Pkcs7 не прошла из-из ошибки',
18 |
19 | verifyXML: 'Верификация подписи формата XML не прошла из-из ошибки',
20 |
21 | verifyHash: 'Верификация подписи Hash не прошла из-из ошибки:',
22 |
23 | noNativeBridge: 'Не найдена функция call_ru_cryptopro_npcades_10_native_bridge. Для корректной работы подключите файл nativeBridge.js'
24 | };
25 |
26 |
27 | if (typeof define === 'function' && typeof define.amd !== 'undefined') {
28 | define('CryptoMessage', CryptoMessage);
29 | }
30 |
31 | if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
32 | module.exports = CryptoMessage;
33 | }
34 | else {
35 | window.CryptoMessage = CryptoMessage;
36 | }
--------------------------------------------------------------------------------
/dev/CryptoPro.js:
--------------------------------------------------------------------------------
1 | var CryptoConstant = require('./CryptoConstant');
2 | var CryptoMessage = require('./CryptoMessage');
3 |
4 | window.CryptoPro = (function(crypto, constant, message) {
5 | 'use strict';
6 |
7 | if(Object.keys(crypto).length) {
8 | return crypto;
9 | }
10 | //Установлен и включен браузер плагин
11 | var _enablePlugin = false, _private;
12 |
13 | _private = {
14 | isIE:(navigator.userAgent.match(/msie/i) || navigator.userAgent.match(/Trident\/./i)),
15 | isApple: (navigator.userAgent.match(/ipod/i) || navigator.userAgent.match(/ipad/i) || navigator.userAgent.match(/iphone/i)),
16 |
17 | /*
18 | * Добавление object в DOM для работы с Crypto API
19 | *
20 | * @method init
21 | */
22 | init: function() {
23 | var o = document.createElement('object');
24 | o.id = 'cadesplugin';
25 | o.type = 'application/x-cades';
26 | o.className = 'hiddenObject';
27 | document.body.appendChild(o);
28 |
29 | if(!this.checkPlugin()) {
30 | throw new Error(message.noPlugin);
31 | }
32 | },
33 |
34 | /*
35 | * Проверка установлен и включен Браузер плагин с Крипто Про CSP
36 | *
37 | * @method checkPlugin
38 | * @returns {Boolean|String} Возвращает объект с информацией о Крипто Про CSP или false
39 | */
40 | checkPlugin: function() {
41 | try {
42 | var csp = this.createObject('CAdESCOM.About');
43 | return csp;
44 | }
45 | catch(e) {}
46 |
47 | return false;
48 | },
49 |
50 | /*
51 | * Создание объекта
52 | *
53 | * @method createObject
54 | * @param {String} name Имя создаваемого объекта
55 | * @returns {Boolean|String} Возвращает информацию о Крипто Про CSP или false
56 | */
57 | createObject:function(name){
58 | if(this.isApple) {
59 | if(call_ru_cryptopro_npcades_10_native_bridge
60 | && typeof call_ru_cryptopro_npcades_10_native_bridge === 'function') {
61 | return call_ru_cryptopro_npcades_10_native_bridge("CreateObject", [name]);
62 | }
63 | else {
64 | throw new Error(message.noNativeBridge);
65 | }
66 | }
67 |
68 | if(!this.isIE){
69 | var o = document.getElementById('cadesplugin');
70 | return o.CreateObject(name);
71 | }
72 | return new ActiveXObject(name);
73 | },
74 |
75 | /*
76 | * Преобразует дату для IE
77 | *
78 | * @method convertDate
79 | * @param {Date} data
80 | * @returns {Date} Возвращает дату
81 | */
82 | convertDate:function(date){
83 | if(!this.isIE){
84 | return date;
85 | }
86 | return date.getVarDate();
87 | },
88 |
89 | /*
90 | * Переворот строки
91 | *
92 | * @method reverse
93 | * @param {String} srt
94 | * @returns {String} Возвращает перевернутую строку
95 | */
96 | reverse: function (str) {
97 | var newStr = '', i;
98 | for (i = str.length - 1; i >= 0; i--) {
99 | newStr += str.charAt(i);
100 | }
101 | return newStr;
102 | },
103 |
104 | /*
105 | * Перевод строки в base64
106 | *
107 | * @method base64Encode
108 | * @param {String} srt Исходная строка
109 | * @returns {String} Возвращает base64
110 | */
111 | base64Encode: function (str) {
112 | str = JSON.stringify(str); //??
113 | str = unescape(encodeURIComponent(str));
114 |
115 | var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
116 | var out = "",
117 | i = 0,
118 | len = str.length,
119 | c1, c2, c3;
120 | while (i < len) {
121 | c1 = str.charCodeAt(i++) & 0xff;
122 | if (i == len) {
123 | out += CHARS.charAt(c1 >> 2);
124 | out += CHARS.charAt((c1 & 0x3) << 4);
125 | out += "==";
126 | break;
127 | }
128 | c2 = str.charCodeAt(i++);
129 | if (i == len) {
130 | out += CHARS.charAt(c1 >> 2);
131 | out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
132 | out += CHARS.charAt((c2 & 0xF) << 2);
133 | out += "=";
134 | break;
135 | }
136 | c3 = str.charCodeAt(i++);
137 | out += CHARS.charAt(c1 >> 2);
138 | out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
139 | out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
140 | out += CHARS.charAt(c3 & 0x3F);
141 | }
142 | return out;
143 | },
144 |
145 | /*
146 | * Проверка на массив
147 | *
148 | * @method isArray
149 | * @param {Array} x Массив
150 | * @returns {Boolean}
151 | */
152 | isArray: function (x) {
153 | return Object.prototype.toString.call(x) === '[object Array]';
154 | }
155 |
156 | };
157 |
158 | /*
159 | * Получение сертификата из хранища по хэшу
160 | *
161 | * @method getByHash
162 | * @param {String} hash Fingerprint сертификата для поиска в хранилище
163 | * @returns {Object} Возвращает найденый сертификат
164 | */
165 | crypto.getByHash = function(hash) {
166 |
167 | if (!(this instanceof crypto.getByHash)) {
168 | return new crypto.getByHash(hash);
169 | }
170 |
171 | var store, certificates;
172 |
173 | if(!_enablePlugin) {
174 | _private.init();
175 | }
176 |
177 | store = _private.createObject('CAPICOM.store');
178 |
179 | try {
180 | store.Open(constant.StoreLocation.CAPICOM_CURRENT_USER_STORE,
181 | constant.StoreNames.CAPICOM_MY_STORE,
182 | constant.StoreOpenMode.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);
183 |
184 | certificates = store.Certificates;
185 | if(certificates.Count === 0) {
186 | throw new Error(message.noCertificate);
187 | }
188 | else {
189 | certificates = certificates.Find(constant.CertFindType.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, hash);
190 | if(certificates.Count > 0)
191 | this.cetificate = certificates.Item(1);
192 | else
193 | throw new Error(message.noHashCertificate);
194 | }
195 |
196 | }
197 | catch (e){
198 | if (e.number !== -2138568446) // отказ от выбора сертификата
199 | throw new Error("Ошибка при получении сертификата: " + e);
200 | this.cetificate = null;
201 | }
202 | finally {
203 | store.Close();
204 | store = certificates = null;
205 | }
206 | };
207 |
208 |
209 | crypto.getByHash.prototype = {
210 | /*
211 | * Получение объекта сертификата
212 | *
213 | * @method get
214 | * @returns {Object} Возвращает найденый сертификат
215 | */
216 | get: function() {
217 | return this.cetificate;
218 | },
219 |
220 | /*
221 | * Получение OID сертификата
222 | *
223 | * @method getExtendedKeyUsage
224 | * @returns {Array} Возвращает массив OID (улучшенного ключа)
225 | */
226 | getExtendedKeyUsage: function () {
227 | var key = this.cetificate, count = key.ExtendedKeyUsage().EKUs.Count, OIDS = [];
228 |
229 | if (count > 0) {
230 | while (count > 0) {
231 | OIDS.push(key.ExtendedKeyUsage().EKUs.Item(count).OID);
232 | count--;
233 | }
234 | }
235 |
236 | return OIDS;
237 | },
238 |
239 | /*
240 | * Проверка наличия OID или группы OID в ключе
241 | *
242 | * @method hasKeyUsageOID
243 | * @param {String|Array} OID код OID или массив
244 | * @returns {Boolean|Object} Возвращает наличие OID в ключе или объект если их несколько
245 | */
246 | hasKeyUsageOID: function (OID) {
247 | if(_private.isArray(OID)) {
248 | var keys = this.getExtendedKeyUsage();
249 | var result = {}, count = OID.length-1;
250 |
251 | while(count > -1) {
252 | result[OID[count]] = !!~keys.indexOf(OID[count]);
253 | count--;
254 | }
255 |
256 | return result;
257 | }
258 | else{
259 | return !!~this.getExtendedKeyUsage().indexOf(OID);
260 | }
261 | },
262 |
263 | /*
264 | * Проверка валидный ключ или нет
265 | *
266 | * @method isKeyValid
267 | * @returns {Boolean}
268 | */
269 | isKeyValid: function() {
270 | return !!this.cetificate.IsValid().Result;
271 | },
272 |
273 | /*
274 | * Парсит SubjectName ключа по тегам
275 | *
276 | * @method getOwner
277 | * @returns {String} Возвращает структурированную информацию о владельце ключа
278 | */
279 | getOwner: function() {
280 | var subject = this.cetificate.SubjectName.split(', '),
281 | tags = {
282 | 'CN=' : 'Владелец',
283 | 'S=' : 'Регион/Город',
284 | 'STREET=' : 'Адрес',
285 | 'O=' : 'Компания',
286 | 'OU=' : 'Тип должности',
287 | 'T=' : 'Должность',
288 | 'ОГРН=' : 'ОГРН',
289 | 'СНИЛС=' : 'СНИЛС',
290 | 'ИНН=' : 'ИНН',
291 | 'E=' : 'Email',
292 | 'L=' : 'Город'
293 | };
294 |
295 | subject = subject.map(function(el){
296 | var tag = el.substring(0, el.indexOf('=')+1);
297 | if(tags[tag]) return el.replace(tag, tags[tag]+': ');
298 | }).filter(function(el){
299 | return !!el;
300 | });
301 |
302 | return subject.join('\n');
303 | },
304 |
305 | /*
306 | * Парсит IssuerName ключа по тегам
307 | *
308 | * @method getOwner
309 | * @returns {String} Возвращает структурированную информацию о издателе ключа
310 | */
311 | getIssuer: function() {
312 | var subject = this.cetificate.SubjectName.split(', '),
313 | tags = {
314 | 'CN=' : 'Удостоверяющий центр',
315 | 'S=' : 'Регион/Город',
316 | 'STREET=' : 'Адрес',
317 | 'O=' : 'Компания',
318 | 'OU=' : 'Тип',
319 | 'T=' : 'Должность',
320 | 'ОГРН=' : 'ОГРН',
321 | 'СНИЛС=' : 'СНИЛС',
322 | 'ИНН=' : 'ИНН',
323 | 'E=' : 'Email',
324 | 'L=' : 'Город'
325 | };
326 |
327 | subject = subject.map(function(el){
328 | var tag = el.substring(0, el.indexOf('=')+1);
329 | if(tags[tag]) return el.replace(tag, tags[tag]+': ');
330 | }).filter(function(el){
331 | return !!el;
332 | });
333 |
334 | return subject.join('\n');
335 | },
336 |
337 | /*
338 | * Вытаскивает информацию об алгоритме
339 | *
340 | * @method getAlgorithm
341 | * @returns {Object} Возвращает объект с информацией об алгоритме
342 | */
343 | getAlgorithm: function() {
344 | return {
345 | Algorithm: this.cetificate.PublicKey().Algorithm.FriendlyName,
346 | OID: this.cetificate.PublicKey().Algorithm.Value
347 | }
348 | }
349 | };
350 |
351 | /*
352 | * Получение списка всех сртификатов хранилища
353 | *
354 | * @method getList
355 | * @returns {Array} Возвращает массив с информацией об установленных ключах
356 | */
357 | crypto.getList = function() {
358 | var store, certificates;
359 |
360 | if(!_enablePlugin) {
361 | _private.init();
362 | }
363 |
364 | store = _private.createObject('CAPICOM.store');
365 |
366 | try {
367 | store.Open(constant.StoreLocation.CAPICOM_CURRENT_USER_STORE,
368 | constant.StoreNames.CAPICOM_MY_STORE,
369 | constant.StoreOpenMode.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);
370 |
371 | certificates = store.Certificates;
372 | if(certificates.Count === 0) {
373 | throw new Error(message.noCertificate)
374 | }
375 | else {
376 | var certificate, list = [], i;
377 | // Не рассматриваются сертификаты, в которых отсутствует закрытый ключ или не действительны на данный момент
378 | certificates = certificates.Find(constant.CertFindType.CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY, constant.PropId.CAPICOM_PROPID_KEY_PROV_INFO)
379 | .Find(constant.CertFindType.CAPICOM_CERTIFICATE_FIND_TIME_VALID);
380 |
381 | i = certificates.Count;
382 | if(i > 0) {
383 | while(i > 0) {
384 | certificate = certificates.Item(i);
385 |
386 | list.push(
387 | {
388 | thumbprint: certificate.Thumbprint,
389 | inform: certificate.GetInfo(0),
390 | validTo: certificate.ValidToDate,
391 | validFrom: certificate.ValidFromDate
392 | }
393 | );
394 | i--
395 | }
396 | }
397 | else {
398 | throw new Error(message.noCertificatesStore);
399 |
400 | }
401 | }
402 | }
403 | catch (e){
404 | if (e.number !== -2138568446) // отказ от выбора сертификата
405 | throw new Error("Ошибка при получении сертификата: "+ e.message);
406 | return;
407 | }
408 | finally {
409 | store.Close();
410 | store = certificates = null;
411 | }
412 |
413 | return list;
414 | };
415 |
416 | /*
417 | * Создание ЭП в формате Pkcs7
418 | *
419 | * @method SignPkcs7
420 | * @param {String} hash fingerprint сертификата для подписи
421 | * @param {String} signData Данные для подписи
422 | * @param {Boolean} signType Тип подписи открепленная/присоединенная
423 | * @returns {String} Возвращает строку в формате base64
424 | */
425 | crypto.SignPkcs7 = function(hash, signData, signType) {
426 | var signer, signedData, signedTime, time = new Date(), type = !!signType;
427 |
428 | signer = _private.createObject('CAdESCOM.CPSigner');
429 | signedData = _private.createObject('CAdESCOM.CadesSignedData');
430 | signedTime = _private.createObject('CADESCOM.CPAttribute');
431 |
432 | // Готовим метку времени создания подписи
433 | signedTime.Name = constant.Time.AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
434 | signedTime.Value = _private.convertDate(time);
435 |
436 | // Вытаскиваем нужный сертификат для создания подписи
437 | signer.Certificate = this.getByHash(hash).get();
438 | // Добавляем метку времени в подпись
439 | signer.AuthenticatedAttributes2.Add(signedTime);
440 | // Выставляем глубину проверки цепочки сертификатов
441 | signer.Options = constant.Chain.CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN;
442 | // Задаем тип преобразования данных
443 | signedData.ContentEncoding = constant.ContentEncoding.CADESCOM_BASE64_TO_BINARY;
444 | // Добавляем данные для подписи
445 | signedData.Content = (signType) ? signData :_private.base64Encode(signData);
446 |
447 | try {
448 | var signature = signedData.SignCades(signer, constant.CadesType.CADESCOM_CADES_BES, type);
449 | }
450 | catch (e) {
451 | throw new Error(message.cantCreateSignature+" " + e);
452 | }
453 | finally {
454 | signer = signedData = signedTime = null;
455 | }
456 |
457 | return signature;
458 | };
459 |
460 | /*
461 | * Создание ЭП в формате XML
462 | *
463 | * @method SignXML
464 | * @param {String} hash fingerprint сертификата для подписи
465 | * @param {String} signData Данные для подписи
466 | * @returns {String} Возвращает строку в виде XML с подписью
467 | */
468 | crypto.SignXML = function(hash, signData) {
469 | var signer, signerXML;
470 |
471 | signer = _private.createObject('CAdESCOM.CPSigner');
472 | signerXML = _private.createObject('CAdESCOM.SignedXML');
473 |
474 | // Вытаскиваем нужный сертификат для создания подписи
475 | signer.Certificate = this.getByHash(hash).get();
476 | // Добавляем данные для подписи
477 | signerXML.Content = signData;
478 | // Устанавливаем тип подписи
479 | signerXML.SignatureType = constant.SignatureType.CADESCOM_XML_SIGNATURE_TYPE_ENVELOPED;
480 | // Устанавливаем алгоритм подписи
481 | signerXML.SignatureMethod = constant.GostXmlDSigUrls.XmlDsigGost3410Url;
482 | // Устанавливаем алгоритм хэширования
483 | signerXML.DigestMethod = constant.GostXmlDSigUrls.XmlDsigGost3411Url;
484 |
485 | try {
486 | var signature = signerXML.Sign(signer)
487 | }
488 | catch(e) {
489 | throw new Error(message.cantCreateSignatureXML+" " + e);
490 | }
491 | finally {
492 | signer = signerXML = null;
493 | }
494 |
495 | return signature;
496 | };
497 |
498 | /*
499 | * Вычсление Hash значения данных или бинарных данных
500 | *
501 | * @method getHash
502 | * @param {String} str строка для вычисления hash значения
503 | * @param {Boolean} binary вычисления хеш бинарных данных
504 | * @returns {String} Возвращает hash строку
505 | */
506 | crypto.getHash = function (str, binary) {
507 | var hashData, hash;
508 | hashData = _private.createObject('CAdESCOM.HashedData');
509 |
510 | // Алгоритм хэширования нужно указать до того, как будут переданы данные
511 | hashData.Algorithm = constant.HashAlgorithm.CADESCOM_HASH_ALGORITHM_CP_GOST_3411;
512 | if(binary !== undefined && binary === true) {
513 | // Указываем кодировку данных
514 | // Кодировка должна быть указана до того, как будут переданы сами данные
515 | hashData.DataEncoding = constant.ContentEncoding.CADESCOM_BASE64_TO_BINARY;
516 |
517 | str = _private.base64Encode(str);
518 | }
519 |
520 | hashData.Hash(str);
521 |
522 | // Хэш-значение будет вычислено от данных в кодировке UCS2-LE
523 | // Для алгоритма SHA-1 хэш-значение будет совпадать с вычисленным при помощи CAPICOM
524 | hash = hashData.Value;
525 |
526 | hashData = null;
527 | return hash;
528 | };
529 |
530 | /*
531 | * Создание ЭП по хэш значению
532 | *
533 | * @method SignHash
534 | * @param {String} hash fingerprint сертификата для подписи
535 | * @param {String} hashValue хэш подписываемых данных
536 | * @param {Boolean} signType отсоединенная / присоединенная
537 | * @returns {String} Возвращает подпись
538 | */
539 | crypto.SignHash = function(hash, hashValue, signType) {
540 | var hashData, rawSignature, signature;
541 |
542 | if(signType === true) {
543 | var signer = _private.createObject('CAdESCOM.CPSigner');
544 | rawSignature = _private.createObject('CAdESCOM.CadesSignedData');
545 | signer.Certificate = this.getByHash(hash).get();
546 | }
547 | else{
548 | rawSignature = _private.createObject('CAdESCOM.RawSignature');
549 | var certificate = this.getByHash(hash).get();
550 | }
551 |
552 | hashData = _private.createObject('CAdESCOM.HashedData');
553 |
554 | // Инициализируем объект заранее вычисленным хэш-значением
555 | // Алгоритм хэширования нужно указать до того, как будет передано хэш-значение
556 | hashData.Algorithm = constant.HashAlgorithm.CADESCOM_HASH_ALGORITHM_CP_GOST_3411;
557 | hashData.SetHashValue(hashValue);
558 |
559 | try {
560 | if(signType === true)
561 | signature = rawSignature.SignHash(hashData, signer, constant.ContentEncoding.CADESCOM_BASE64_TO_BINARY);
562 | else
563 | signature = rawSignature.SignHash(hashData, certificate);
564 | }
565 | catch(e) {
566 | throw new Error(message.cantCreateSignatureHash+' '+e);
567 | }
568 |
569 | hashData = rawSignature = null;
570 |
571 | return signature;
572 | };
573 |
574 | /*
575 | * Верификация подписипо хэш значению
576 | *
577 | * @method VerifyHash
578 | * @param {String} hash fingerprint сертификата для подписи
579 | * @param {String} hashValue хэш подписываемых данных
580 | * @param {String} signature подпись
581 | * @param {Boolean} signType отсоединенная / присоединенная
582 | * @returns {Boolean}
583 | */
584 | crypto.VerifyHash = function (hash, hashValue, signature, signType) {
585 | var hashData, rawSignature, certificate;
586 |
587 | hashData = _private.createObject('CAdESCOM.HashedData');
588 | certificate = this.getByHash(hash).get();
589 |
590 | if(signType === true)
591 | rawSignature = _private.createObject('CAdESCOM.CadesSignedData');
592 | else
593 | rawSignature = _private.createObject('CAdESCOM.RawSignature');
594 |
595 | hashData.Algorithm = constant.HashAlgorithm.CADESCOM_HASH_ALGORITHM_CP_GOST_3411;
596 | hashData.SetHashValue(hashValue);
597 |
598 | try {
599 | if(signType === true)
600 | rawSignature.VerifyHash(hashData, signature, constant.ContentEncoding.CADESCOM_BASE64_TO_BINARY);
601 | else
602 | rawSignature.VerifyHash(hashData, certificate, signature);
603 | }
604 | catch (e) {
605 | throw new Error(message.verifyHash+' '+e);
606 | }
607 | finally {
608 | hashData = certificate = rawSignature = null
609 | }
610 |
611 | return true;
612 | };
613 |
614 | /*
615 | * Верификация подписи в формате Pkcs7
616 | *
617 | * @method VerifyPkcs7
618 | * @param {String} signature строка с подписью
619 | * @param {Boolean} signType Тип подписи открепленная/присоединенная
620 | * @returns {Boolean|String} Валидна или строку с ошибкой
621 | */
622 | crypto.VerifyPkcs7 = function (signature, signType){
623 | var signedData, type = !!signType;
624 |
625 | signedData = _private.createObject('CAdESCOM.CadesSignedData');
626 |
627 | try {
628 | signedData.VerifyCades(signature, constant.CadesType.CADESCOM_CADES_BES, type);
629 | }
630 | catch(e) {
631 | throw new Error(message.verifyPkcs7+" " + e);
632 | } finally {
633 | signedData = null;
634 | }
635 |
636 | return true;
637 | };
638 |
639 | /*
640 | * Верификация подписи в формате XML
641 | *
642 | * @method VerifyXML
643 | * @param {String} signature строка с подписью
644 | * @returns {Boolean|String} Валидна или строку с ошибкой
645 | */
646 | crypto.VerifyXML = function(signature){
647 | var signerXML = _private.createObject('CAdESCOM.SignedXML');
648 |
649 | try {
650 | signerXML.Verify(signature)
651 | }
652 | catch(e) {
653 | throw new Error(message.verifyXML+" " + e);
654 | }
655 | finally {
656 | signerXML = null;
657 | }
658 |
659 | return true;
660 | };
661 |
662 | return crypto;
663 |
664 | }(window['CryptoPro'] || {}, CryptoConstant, CryptoMessage));
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "CryptoProAPI",
3 | "version": "0.0.1",
4 | "description": "Простое API для работы с КриптоПро ЭЦП Browser plug-in",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/shanhaichik/CryptoProAPI.git"
8 | },
9 | "author": {
10 | "name": "Alexander Dukhovnyak",
11 | "email": "shanhaichik@gmail.com"
12 | },
13 | "license": "MIT",
14 | "main": "src/cryptoAPI.js",
15 | "scripts": {
16 | "watch": "watchify ./dev/CryptoPro.js -o dev/bundle.js -v -d",
17 | "browserify": "browserify ./dev/CryptoPro.js | uglifyjs -m > src/cryptoAPI.js",
18 | "build": "npm run browserify ",
19 | "start": "npm run watch"
20 | },
21 | "devDependencies": {
22 | "browserify": "~6.0.3",
23 | "uglify-js": "~2.4.15",
24 | "watchify": "~2.0.0"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/cryptoAPI.js:
--------------------------------------------------------------------------------
1 | (function e(t,_,C){function r(i,E){if(!_[i]){if(!t[i]){var A=typeof require=="function"&&require;if(!E&&A)return A(i,!0);if(n)return n(i,!0);var O=new Error("Cannot find module '"+i+"'");throw O.code="MODULE_NOT_FOUND",O}var I=_[i]={exports:{}};t[i][0].call(I.exports,function(e){var _=t[i][1][e];return r(_?_:e)},I,I.exports,e,t,_,C)}return _[i].exports}var n=typeof require=="function"&&require;for(var i=0;i=0;_--){t+=e.charAt(_)}return t},base64Encode:function(e){e=JSON.stringify(e);e=unescape(encodeURIComponent(e));var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var _="",C=0,r=e.length,n,i,E;while(C>2);_+=t.charAt((n&3)<<4);_+="==";break}i=e.charCodeAt(C++);if(C==r){_+=t.charAt(n>>2);_+=t.charAt((n&3)<<4|(i&240)>>4);_+=t.charAt((i&15)<<2);_+="=";break}E=e.charCodeAt(C++);_+=t.charAt(n>>2);_+=t.charAt((n&3)<<4|(i&240)>>4);_+=t.charAt((i&15)<<2|(E&192)>>6);_+=t.charAt(E&63)}return _},isArray:function(e){return Object.prototype.toString.call(e)==="[object Array]"}};e.getByHash=function(n){if(!(this instanceof e.getByHash)){return new e.getByHash(n)}var i,E;if(!C){r.init()}i=r.createObject("CAPICOM.store");try{i.Open(t.StoreLocation.CAPICOM_CURRENT_USER_STORE,t.StoreNames.CAPICOM_MY_STORE,t.StoreOpenMode.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);E=i.Certificates;if(E.Count===0){throw new Error(_.noCertificate)}else{E=E.Find(t.CertFindType.CAPICOM_CERTIFICATE_FIND_SHA1_HASH,n);if(E.Count>0)this.cetificate=E.Item(1);else throw new Error(_.noHashCertificate)}}catch(A){if(A.number!==-2138568446)throw new Error("Ошибка при получении сертификата: "+A);this.cetificate=null}finally{i.Close();i=E=null}};e.getByHash.prototype={get:function(){return this.cetificate},getExtendedKeyUsage:function(){var e=this.cetificate,t=e.ExtendedKeyUsage().EKUs.Count,_=[];if(t>0){while(t>0){_.push(e.ExtendedKeyUsage().EKUs.Item(t).OID);t--}}return _},hasKeyUsageOID:function(e){if(r.isArray(e)){var t=this.getExtendedKeyUsage();var _={},C=e.length-1;while(C>-1){_[e[C]]=!!~t.indexOf(e[C]);C--}return _}else{return!!~this.getExtendedKeyUsage().indexOf(e)}},isKeyValid:function(){return!!this.cetificate.IsValid().Result},getOwner:function(){var e=this.cetificate.SubjectName.split(", "),t={"CN=":"Владелец","S=":"Регион/Город","STREET=":"Адрес","O=":"Компания","OU=":"Тип должности","T=":"Должность","ОГРН=":"ОГРН","СНИЛС=":"СНИЛС","ИНН=":"ИНН","E=":"Email","L=":"Город"};e=e.map(function(e){var _=e.substring(0,e.indexOf("=")+1);if(t[_])return e.replace(_,t[_]+": ")}).filter(function(e){return!!e});return e.join("\n")},getIssuer:function(){var e=this.cetificate.SubjectName.split(", "),t={"CN=":"Удостоверяющий центр","S=":"Регион/Город","STREET=":"Адрес","O=":"Компания","OU=":"Тип","T=":"Должность","ОГРН=":"ОГРН","СНИЛС=":"СНИЛС","ИНН=":"ИНН","E=":"Email","L=":"Город"};e=e.map(function(e){var _=e.substring(0,e.indexOf("=")+1);if(t[_])return e.replace(_,t[_]+": ")}).filter(function(e){return!!e});return e.join("\n")},getAlgorithm:function(){return{Algorithm:this.cetificate.PublicKey().Algorithm.FriendlyName,OID:this.cetificate.PublicKey().Algorithm.Value}}};e.getList=function(){var e,n;if(!C){r.init()}e=r.createObject("CAPICOM.store");try{e.Open(t.StoreLocation.CAPICOM_CURRENT_USER_STORE,t.StoreNames.CAPICOM_MY_STORE,t.StoreOpenMode.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);n=e.Certificates;if(n.Count===0){throw new Error(_.noCertificate)}else{var i,E=[],A;n=n.Find(t.CertFindType.CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY,t.PropId.CAPICOM_PROPID_KEY_PROV_INFO).Find(t.CertFindType.CAPICOM_CERTIFICATE_FIND_TIME_VALID);A=n.Count;if(A>0){while(A>0){i=n.Item(A);E.push({thumbprint:i.Thumbprint,inform:i.GetInfo(0),validTo:i.ValidToDate,validFrom:i.ValidFromDate});A--}}else{throw new Error(_.noCertificatesStore)}}}catch(O){if(O.number!==-2138568446)throw new Error("Ошибка при получении сертификата: "+O.message);return}finally{e.Close();e=n=null}return E};e.SignPkcs7=function(e,C,n){var i,E,A,O=new Date,I=!!n;i=r.createObject("CAdESCOM.CPSigner");E=r.createObject("CAdESCOM.CadesSignedData");A=r.createObject("CADESCOM.CPAttribute");A.Name=t.Time.AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;A.Value=r.convertDate(O);i.Certificate=this.getByHash(e).get();i.AuthenticatedAttributes2.Add(A);i.Options=t.Chain.CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN;E.ContentEncoding=t.ContentEncoding.CADESCOM_BASE64_TO_BINARY;E.Content=n?C:r.base64Encode(C);try{var a=E.SignCades(i,t.CadesType.CADESCOM_CADES_BES,I)}catch(o){throw new Error(_.cantCreateSignature+" "+o)}finally{i=E=A=null}return a};e.SignXML=function(e,C){var n,i;n=r.createObject("CAdESCOM.CPSigner");i=r.createObject("CAdESCOM.SignedXML");n.Certificate=this.getByHash(e).get();i.Content=C;i.SignatureType=t.SignatureType.CADESCOM_XML_SIGNATURE_TYPE_ENVELOPED;i.SignatureMethod=t.GostXmlDSigUrls.XmlDsigGost3410Url;i.DigestMethod=t.GostXmlDSigUrls.XmlDsigGost3411Url;try{var E=i.Sign(n)}catch(A){throw new Error(_.cantCreateSignatureXML+" "+A)}finally{n=i=null}return E};e.getHash=function(e,_){var C,n;C=r.createObject("CAdESCOM.HashedData");C.Algorithm=t.HashAlgorithm.CADESCOM_HASH_ALGORITHM_CP_GOST_3411;if(_!==undefined&&_===true){C.DataEncoding=t.ContentEncoding.CADESCOM_BASE64_TO_BINARY;e=r.base64Encode(e)}C.Hash(e);n=C.Value;C=null;return n};e.SignHash=function(e,C,n){var i,E,A;if(n===true){var O=r.createObject("CAdESCOM.CPSigner");E=r.createObject("CAdESCOM.CadesSignedData");O.Certificate=this.getByHash(e).get()}else{E=r.createObject("CAdESCOM.RawSignature");var I=this.getByHash(e).get()}i=r.createObject("CAdESCOM.HashedData");i.Algorithm=t.HashAlgorithm.CADESCOM_HASH_ALGORITHM_CP_GOST_3411;i.SetHashValue(C);try{if(n===true)A=E.SignHash(i,O,t.ContentEncoding.CADESCOM_BASE64_TO_BINARY);else A=E.SignHash(i,I)}catch(a){throw new Error(_.cantCreateSignatureHash+" "+a)}i=E=null;return A};e.VerifyHash=function(e,C,n,i){var E,A,O;E=r.createObject("CAdESCOM.HashedData");O=this.getByHash(e).get();if(i===true)A=r.createObject("CAdESCOM.CadesSignedData");else A=r.createObject("CAdESCOM.RawSignature");E.Algorithm=t.HashAlgorithm.CADESCOM_HASH_ALGORITHM_CP_GOST_3411;E.SetHashValue(C);try{if(i===true)A.VerifyHash(E,n,t.ContentEncoding.CADESCOM_BASE64_TO_BINARY);else A.VerifyHash(E,O,n)}catch(I){throw new Error(_.verifyHash+" "+I)}finally{E=O=A=null}return true};e.VerifyPkcs7=function(e,C){var n,i=!!C;n=r.createObject("CAdESCOM.CadesSignedData");try{n.VerifyCades(e,t.CadesType.CADESCOM_CADES_BES,i)}catch(E){throw new Error(_.verifyPkcs7+" "+E)}finally{n=null}return true};e.VerifyXML=function(e){var t=r.createObject("CAdESCOM.SignedXML");try{t.Verify(e)}catch(C){throw new Error(_.verifyXML+" "+C)}finally{t=null}return true};return e}(window["CryptoPro"]||{},C,r)},{"./CryptoConstant":1,"./CryptoMessage":2}]},{},[3]);
--------------------------------------------------------------------------------
/src/nativeBridge.js:
--------------------------------------------------------------------------------
1 | var ru_cryptopro_npcades_10_native_bridge = {
2 | callbacksCount : 1,
3 | callbacks : {},
4 |
5 | // Automatically called by native layer when a result is available
6 | resultForCallback : function resultForCallback(callbackId, resultArray) {
7 | "use strict";
8 |
9 | var callback = ru_cryptopro_npcades_10_native_bridge.callbacks[callbackId];
10 | if (!callback) {
11 | return;
12 | } else {
13 | callback.apply(null, resultArray);
14 | }
15 | },
16 |
17 | // Use this in javascript to request native objective-c code
18 | // functionName : string (I think the name is explicit :p)
19 | // args : array of arguments
20 | // callback : function with n-arguments that is going to be called when the native code returned
21 | call : function call(functionName, args, callback) {
22 | "use strict";
23 |
24 | var hasCallback = callback && typeof callback === "function",
25 | callbackId = hasCallback ? ru_cryptopro_npcades_10_native_bridge.callbacksCount += 1 : 0,
26 | iframe = document.createElement("IFRAME"),
27 | arrObjs = ["_CPNP_handle"];
28 |
29 | if (hasCallback) {
30 | ru_cryptopro_npcades_10_native_bridge.callbacks[callbackId] = callback;
31 | }
32 |
33 | try {
34 | iframe.setAttribute("src", "cpnp-js-call:" + functionName + ":" + callbackId + ":" + encodeURIComponent(JSON.stringify(args, arrObjs)));
35 | } catch (e) {
36 | throw e;
37 | }
38 |
39 | document.documentElement.appendChild(iframe);
40 | iframe.parentNode.removeChild(iframe);
41 | iframe = null;
42 | }
43 | };
44 |
45 | function call_ru_cryptopro_npcades_10_native_bridge(functionName, array) {
46 | "use strict";
47 |
48 | var tmpobj,
49 | ex;
50 |
51 | try {
52 | ru_cryptopro_npcades_10_native_bridge.call(functionName, array, function (e, response) {
53 | var str = 'tmpobj=' + response;
54 | ex = e;
55 | eval(str);
56 | if (typeof (tmpobj) === "string") {
57 | tmpobj = tmpobj.replace(/\\\n/gm, "\n");
58 | tmpobj = tmpobj.replace(/\\\r/gm, "\r");
59 | }
60 | });
61 | if (ex) {
62 | throw ex;
63 | } else {
64 | return tmpobj;
65 | }
66 | } catch (e) {
67 | throw e;
68 | }
69 | }
--------------------------------------------------------------------------------