@protontech/openpgp 4.10.5 → 5.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +311 -239
- package/dist/lightweight/bn.interface.min.mjs +3 -0
- package/dist/lightweight/bn.interface.min.mjs.map +1 -0
- package/dist/lightweight/bn.interface.mjs +340 -0
- package/dist/lightweight/bn.min.mjs +3 -0
- package/dist/lightweight/bn.min.mjs.map +1 -0
- package/dist/lightweight/bn.mjs +3434 -0
- package/dist/lightweight/elliptic.min.mjs +3 -0
- package/dist/lightweight/elliptic.min.mjs.map +1 -0
- package/dist/lightweight/elliptic.mjs +4313 -0
- package/dist/lightweight/openpgp.min.mjs +3 -0
- package/dist/lightweight/openpgp.min.mjs.map +1 -0
- package/dist/lightweight/openpgp.mjs +31375 -0
- package/dist/lightweight/ponyfill.es6.min.mjs +3 -0
- package/dist/lightweight/ponyfill.es6.min.mjs.map +1 -0
- package/dist/lightweight/ponyfill.es6.mjs +3831 -0
- package/dist/lightweight/web-streams-adapter.min.mjs +17 -0
- package/dist/lightweight/web-streams-adapter.min.mjs.map +1 -0
- package/dist/lightweight/web-streams-adapter.mjs +561 -0
- package/dist/node/openpgp.js +43943 -0
- package/dist/node/openpgp.min.js +17 -0
- package/dist/node/openpgp.min.js.map +1 -0
- package/dist/node/openpgp.min.mjs +17 -0
- package/dist/node/openpgp.min.mjs.map +1 -0
- package/dist/node/openpgp.mjs +43880 -0
- package/dist/openpgp.js +41080 -41565
- package/dist/openpgp.min.js +17 -2
- package/dist/openpgp.min.js.map +1 -0
- package/dist/openpgp.min.mjs +17 -0
- package/dist/openpgp.min.mjs.map +1 -0
- package/dist/openpgp.mjs +43868 -0
- package/lightweight/package.json +5 -0
- package/openpgp.d.ts +889 -0
- package/package.json +63 -57
- package/dist/compat/openpgp.js +0 -61067
- package/dist/compat/openpgp.min.js +0 -2
- package/dist/compat/openpgp.worker.js +0 -173
- package/dist/compat/openpgp.worker.min.js +0 -2
- package/dist/lightweight/elliptic.min.js +0 -5
- package/dist/lightweight/openpgp.js +0 -40024
- package/dist/lightweight/openpgp.min.js +0 -2
- package/dist/lightweight/openpgp.worker.js +0 -173
- package/dist/lightweight/openpgp.worker.min.js +0 -2
- package/dist/openpgp.worker.js +0 -173
- package/dist/openpgp.worker.min.js +0 -2
- package/src/cleartext.js +0 -220
- package/src/config/config.js +0 -224
- package/src/config/index.js +0 -7
- package/src/config/localStorage.js +0 -35
- package/src/crypto/aes_kw.js +0 -153
- package/src/crypto/cfb.js +0 -169
- package/src/crypto/cipher/aes.js +0 -27
- package/src/crypto/cipher/blowfish.js +0 -398
- package/src/crypto/cipher/cast5.js +0 -610
- package/src/crypto/cipher/des.js +0 -476
- package/src/crypto/cipher/index.js +0 -91
- package/src/crypto/cipher/twofish.js +0 -346
- package/src/crypto/cmac.js +0 -98
- package/src/crypto/crypto.js +0 -394
- package/src/crypto/eax.js +0 -172
- package/src/crypto/gcm.js +0 -141
- package/src/crypto/hash/index.js +0 -163
- package/src/crypto/hash/md5.js +0 -205
- package/src/crypto/index.js +0 -57
- package/src/crypto/ocb.js +0 -274
- package/src/crypto/pkcs1.js +0 -170
- package/src/crypto/pkcs5.js +0 -55
- package/src/crypto/public_key/dsa.js +0 -188
- package/src/crypto/public_key/elgamal.js +0 -137
- package/src/crypto/public_key/elliptic/curves.js +0 -385
- package/src/crypto/public_key/elliptic/ecdh.js +0 -414
- package/src/crypto/public_key/elliptic/ecdsa.js +0 -348
- package/src/crypto/public_key/elliptic/eddsa.js +0 -119
- package/src/crypto/public_key/elliptic/index.js +0 -34
- package/src/crypto/public_key/elliptic/indutnyKey.js +0 -85
- package/src/crypto/public_key/index.js +0 -28
- package/src/crypto/public_key/prime.js +0 -275
- package/src/crypto/public_key/rsa.js +0 -597
- package/src/crypto/random.js +0 -145
- package/src/crypto/signature.js +0 -137
- package/src/encoding/armor.js +0 -433
- package/src/encoding/base64.js +0 -96
- package/src/enums.js +0 -493
- package/src/hkp.js +0 -89
- package/src/index.js +0 -161
- package/src/key/factory.js +0 -326
- package/src/key/helper.js +0 -363
- package/src/key/index.js +0 -32
- package/src/key/key.js +0 -890
- package/src/key/subkey.js +0 -187
- package/src/key/user.js +0 -230
- package/src/keyring/index.js +0 -12
- package/src/keyring/keyring.js +0 -229
- package/src/keyring/localstore.js +0 -119
- package/src/lightweight_helper.js +0 -26
- package/src/message.js +0 -825
- package/src/openpgp.js +0 -717
- package/src/packet/all_packets.js +0 -116
- package/src/packet/clone.js +0 -189
- package/src/packet/compressed.js +0 -194
- package/src/packet/index.js +0 -20
- package/src/packet/literal.js +0 -168
- package/src/packet/marker.js +0 -62
- package/src/packet/one_pass_signature.js +0 -156
- package/src/packet/packet.js +0 -300
- package/src/packet/packetlist.js +0 -232
- package/src/packet/public_key.js +0 -280
- package/src/packet/public_key_encrypted_session_key.js +0 -156
- package/src/packet/public_subkey.js +0 -44
- package/src/packet/secret_key.js +0 -448
- package/src/packet/secret_subkey.js +0 -41
- package/src/packet/signature.js +0 -782
- package/src/packet/sym_encrypted_aead_protected.js +0 -189
- package/src/packet/sym_encrypted_integrity_protected.js +0 -139
- package/src/packet/sym_encrypted_session_key.js +0 -204
- package/src/packet/symmetrically_encrypted.js +0 -118
- package/src/packet/trust.js +0 -35
- package/src/packet/user_attribute.js +0 -94
- package/src/packet/userid.js +0 -87
- package/src/polyfills.js +0 -64
- package/src/signature.js +0 -73
- package/src/type/ecdh_symkey.js +0 -69
- package/src/type/kdf_params.js +0 -114
- package/src/type/keyid.js +0 -110
- package/src/type/mpi.js +0 -138
- package/src/type/oid.js +0 -110
- package/src/type/s2k.js +0 -203
- package/src/util.js +0 -836
- package/src/wkd.js +0 -88
- package/src/worker/async_proxy.js +0 -190
- package/src/worker/worker.js +0 -167
- package/test/crypto/aes_kw.js +0 -57
- package/test/crypto/cipher/aes.js +0 -86
- package/test/crypto/cipher/blowfish.js +0 -58
- package/test/crypto/cipher/cast5.js +0 -25
- package/test/crypto/cipher/des.js +0 -143
- package/test/crypto/cipher/index.js +0 -7
- package/test/crypto/cipher/twofish.js +0 -71
- package/test/crypto/crypto.js +0 -383
- package/test/crypto/eax.js +0 -150
- package/test/crypto/ecdh.js +0 -359
- package/test/crypto/elliptic.js +0 -251
- package/test/crypto/elliptic_data.js +0 -102
- package/test/crypto/hash/index.js +0 -5
- package/test/crypto/hash/md5.js +0 -16
- package/test/crypto/hash/ripemd.js +0 -14
- package/test/crypto/hash/sha.js +0 -20
- package/test/crypto/index.js +0 -14
- package/test/crypto/ocb.js +0 -183
- package/test/crypto/pkcs5.js +0 -39
- package/test/crypto/random.js +0 -79
- package/test/crypto/rsa.js +0 -180
- package/test/crypto/validate.js +0 -387
- package/test/general/armor.js +0 -408
- package/test/general/brainpool.js +0 -360
- package/test/general/decompression.js +0 -60
- package/test/general/ecc_nist.js +0 -115
- package/test/general/ecc_secp256k1.js +0 -242
- package/test/general/forwarding.js +0 -43
- package/test/general/hkp.js +0 -165
- package/test/general/index.js +0 -20
- package/test/general/key.js +0 -3402
- package/test/general/keyring.js +0 -336
- package/test/general/oid.js +0 -39
- package/test/general/openpgp.js +0 -2542
- package/test/general/packet.js +0 -937
- package/test/general/signature.js +0 -1665
- package/test/general/streaming.js +0 -944
- package/test/general/testInputs.js +0 -18
- package/test/general/util.js +0 -183
- package/test/general/wkd.js +0 -48
- package/test/general/x25519.js +0 -556
- package/test/unittests.js +0 -64
|
@@ -1,597 +0,0 @@
|
|
|
1
|
-
// GPG4Browsers - An OpenPGP implementation in javascript
|
|
2
|
-
// Copyright (C) 2011 Recurity Labs GmbH
|
|
3
|
-
//
|
|
4
|
-
// This library is free software; you can redistribute it and/or
|
|
5
|
-
// modify it under the terms of the GNU Lesser General Public
|
|
6
|
-
// License as published by the Free Software Foundation; either
|
|
7
|
-
// version 3.0 of the License, or (at your option) any later version.
|
|
8
|
-
//
|
|
9
|
-
// This library is distributed in the hope that it will be useful,
|
|
10
|
-
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
-
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
12
|
-
// Lesser General Public License for more details.
|
|
13
|
-
//
|
|
14
|
-
// You should have received a copy of the GNU Lesser General Public
|
|
15
|
-
// License along with this library; if not, write to the Free Software
|
|
16
|
-
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @fileoverview RSA implementation
|
|
20
|
-
* @requires bn.js
|
|
21
|
-
* @requires crypto/public_key/prime
|
|
22
|
-
* @requires crypto/random
|
|
23
|
-
* @requires config
|
|
24
|
-
* @requires util
|
|
25
|
-
* @module crypto/public_key/rsa
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
import BN from 'bn.js';
|
|
29
|
-
import prime from './prime';
|
|
30
|
-
import random from '../random';
|
|
31
|
-
import config from '../../config';
|
|
32
|
-
import util from '../../util';
|
|
33
|
-
import pkcs1 from '../pkcs1';
|
|
34
|
-
import enums from '../../enums';
|
|
35
|
-
import type_mpi from '../../type/mpi';
|
|
36
|
-
|
|
37
|
-
const webCrypto = util.getWebCrypto();
|
|
38
|
-
const nodeCrypto = util.getNodeCrypto();
|
|
39
|
-
const asn1 = nodeCrypto ? require('asn1.js') : undefined;
|
|
40
|
-
|
|
41
|
-
// Helper for IE11 KeyOperation objects
|
|
42
|
-
function promisifyIE11Op(keyObj, err) {
|
|
43
|
-
if (typeof keyObj.then !== 'function') { // IE11 KeyOperation
|
|
44
|
-
return new Promise(function(resolve, reject) {
|
|
45
|
-
keyObj.onerror = function () {
|
|
46
|
-
reject(new Error(err));
|
|
47
|
-
};
|
|
48
|
-
keyObj.oncomplete = function (e) {
|
|
49
|
-
resolve(e.target.result);
|
|
50
|
-
};
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
return keyObj;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/* eslint-disable no-invalid-this */
|
|
57
|
-
const RSAPrivateKey = util.detectNode() ? asn1.define('RSAPrivateKey', function () {
|
|
58
|
-
this.seq().obj( // used for native NodeJS crypto
|
|
59
|
-
this.key('version').int(), // 0
|
|
60
|
-
this.key('modulus').int(), // n
|
|
61
|
-
this.key('publicExponent').int(), // e
|
|
62
|
-
this.key('privateExponent').int(), // d
|
|
63
|
-
this.key('prime1').int(), // p
|
|
64
|
-
this.key('prime2').int(), // q
|
|
65
|
-
this.key('exponent1').int(), // dp
|
|
66
|
-
this.key('exponent2').int(), // dq
|
|
67
|
-
this.key('coefficient').int() // u
|
|
68
|
-
);
|
|
69
|
-
}) : undefined;
|
|
70
|
-
|
|
71
|
-
const RSAPublicKey = util.detectNode() ? asn1.define('RSAPubliceKey', function () {
|
|
72
|
-
this.seq().obj( // used for native NodeJS crypto
|
|
73
|
-
this.key('modulus').int(), // n
|
|
74
|
-
this.key('publicExponent').int(), // e
|
|
75
|
-
);
|
|
76
|
-
}) : undefined;
|
|
77
|
-
/* eslint-enable no-invalid-this */
|
|
78
|
-
|
|
79
|
-
export default {
|
|
80
|
-
/** Create signature
|
|
81
|
-
* @param {module:enums.hash} hash_algo Hash algorithm
|
|
82
|
-
* @param {Uint8Array} data message
|
|
83
|
-
* @param {Uint8Array} n RSA public modulus
|
|
84
|
-
* @param {Uint8Array} e RSA public exponent
|
|
85
|
-
* @param {Uint8Array} d RSA private exponent
|
|
86
|
-
* @param {Uint8Array} p RSA private prime p
|
|
87
|
-
* @param {Uint8Array} q RSA private prime q
|
|
88
|
-
* @param {Uint8Array} u RSA private coefficient
|
|
89
|
-
* @param {Uint8Array} hashed hashed message
|
|
90
|
-
* @returns {Uint8Array} RSA Signature
|
|
91
|
-
* @async
|
|
92
|
-
*/
|
|
93
|
-
sign: async function(hash_algo, data, n, e, d, p, q, u, hashed) {
|
|
94
|
-
if (data && !util.isStream(data)) {
|
|
95
|
-
if (util.getWebCrypto()) {
|
|
96
|
-
try {
|
|
97
|
-
return await this.webSign(enums.read(enums.webHash, hash_algo), data, n, e, d, p, q, u);
|
|
98
|
-
} catch (err) {
|
|
99
|
-
util.print_debug_error(err);
|
|
100
|
-
}
|
|
101
|
-
} else if (util.getNodeCrypto()) {
|
|
102
|
-
return this.nodeSign(hash_algo, data, n, e, d, p, q, u);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return this.bnSign(hash_algo, n, d, hashed);
|
|
106
|
-
},
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Verify signature
|
|
110
|
-
* @param {module:enums.hash} hash_algo Hash algorithm
|
|
111
|
-
* @param {Uint8Array} data message
|
|
112
|
-
* @param {Uint8Array} s signature
|
|
113
|
-
* @param {Uint8Array} n RSA public modulus
|
|
114
|
-
* @param {Uint8Array} e RSA public exponent
|
|
115
|
-
* @param {Uint8Array} hashed hashed message
|
|
116
|
-
* @returns {Boolean}
|
|
117
|
-
* @async
|
|
118
|
-
*/
|
|
119
|
-
verify: async function(hash_algo, data, s, n, e, hashed) {
|
|
120
|
-
if (data && !util.isStream(data)) {
|
|
121
|
-
if (util.getWebCrypto()) {
|
|
122
|
-
try {
|
|
123
|
-
return await this.webVerify(enums.read(enums.webHash, hash_algo), data, s, n, e);
|
|
124
|
-
} catch (err) {
|
|
125
|
-
util.print_debug_error(err);
|
|
126
|
-
}
|
|
127
|
-
} else if (util.getNodeCrypto()) {
|
|
128
|
-
return this.nodeVerify(hash_algo, data, s, n, e);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return this.bnVerify(hash_algo, s, n, e, hashed);
|
|
132
|
-
},
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Encrypt message
|
|
136
|
-
* @param {Uint8Array} data message
|
|
137
|
-
* @param {Uint8Array} n RSA public modulus
|
|
138
|
-
* @param {Uint8Array} e RSA public exponent
|
|
139
|
-
* @returns {Uint8Array} RSA Ciphertext
|
|
140
|
-
* @async
|
|
141
|
-
*/
|
|
142
|
-
encrypt: async function(data, n, e) {
|
|
143
|
-
if (util.getNodeCrypto()) {
|
|
144
|
-
return this.nodeEncrypt(data, n, e);
|
|
145
|
-
}
|
|
146
|
-
return this.bnEncrypt(data, n, e);
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Decrypt RSA message
|
|
151
|
-
* @param {Uint8Array} m message
|
|
152
|
-
* @param {Uint8Array} n RSA public modulus
|
|
153
|
-
* @param {Uint8Array} e RSA public exponent
|
|
154
|
-
* @param {Uint8Array} d RSA private exponent
|
|
155
|
-
* @param {Uint8Array} p RSA private prime p
|
|
156
|
-
* @param {Uint8Array} q RSA private prime q
|
|
157
|
-
* @param {Uint8Array} u RSA private coefficient
|
|
158
|
-
* @returns {String} RSA Plaintext
|
|
159
|
-
* @async
|
|
160
|
-
*/
|
|
161
|
-
decrypt: async function(data, n, e, d, p, q, u) {
|
|
162
|
-
if (util.getNodeCrypto()) {
|
|
163
|
-
return this.nodeDecrypt(data, n, e, d, p, q, u);
|
|
164
|
-
}
|
|
165
|
-
return this.bnDecrypt(data, n, e, d, p, q, u);
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Generate a new random private key B bits long with public exponent E.
|
|
170
|
-
*
|
|
171
|
-
* When possible, webCrypto or nodeCrypto is used. Otherwise, primes are generated using
|
|
172
|
-
* 40 rounds of the Miller-Rabin probabilistic random prime generation algorithm.
|
|
173
|
-
* @see module:crypto/public_key/prime
|
|
174
|
-
* @param {Integer} B RSA bit length
|
|
175
|
-
* @param {String} E RSA public exponent in hex string
|
|
176
|
-
* @returns {{n: BN, e: BN, d: BN,
|
|
177
|
-
* p: BN, q: BN, u: BN}} RSA public modulus, RSA public exponent, RSA private exponent,
|
|
178
|
-
* RSA private prime p, RSA private prime q, u = q ** -1 mod p
|
|
179
|
-
* @async
|
|
180
|
-
*/
|
|
181
|
-
generate: async function(B, E) {
|
|
182
|
-
let key;
|
|
183
|
-
E = new BN(E, 16);
|
|
184
|
-
|
|
185
|
-
// Native RSA keygen using Web Crypto
|
|
186
|
-
if (util.getWebCrypto()) {
|
|
187
|
-
let keyPair;
|
|
188
|
-
let keyGenOpt;
|
|
189
|
-
if ((global.crypto && global.crypto.subtle) || global.msCrypto) {
|
|
190
|
-
// current standard spec
|
|
191
|
-
keyGenOpt = {
|
|
192
|
-
name: 'RSASSA-PKCS1-v1_5',
|
|
193
|
-
modulusLength: B, // the specified keysize in bits
|
|
194
|
-
publicExponent: E.toArrayLike(Uint8Array), // take three bytes (max 65537) for exponent
|
|
195
|
-
hash: {
|
|
196
|
-
name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify'
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
keyPair = webCrypto.generateKey(keyGenOpt, true, ['sign', 'verify']);
|
|
200
|
-
keyPair = await promisifyIE11Op(keyPair, 'Error generating RSA key pair.');
|
|
201
|
-
} else if (global.crypto && global.crypto.webkitSubtle) {
|
|
202
|
-
// outdated spec implemented by old Webkit
|
|
203
|
-
keyGenOpt = {
|
|
204
|
-
name: 'RSA-OAEP',
|
|
205
|
-
modulusLength: B, // the specified keysize in bits
|
|
206
|
-
publicExponent: E.toArrayLike(Uint8Array), // take three bytes (max 65537) for exponent
|
|
207
|
-
hash: {
|
|
208
|
-
name: 'SHA-1' // not required for actual RSA keys, but for crypto api 'sign' and 'verify'
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
keyPair = await webCrypto.generateKey(keyGenOpt, true, ['encrypt', 'decrypt']);
|
|
212
|
-
} else {
|
|
213
|
-
throw new Error('Unknown WebCrypto implementation');
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// export the generated keys as JsonWebKey (JWK)
|
|
217
|
-
// https://tools.ietf.org/html/draft-ietf-jose-json-web-key-33
|
|
218
|
-
let jwk = webCrypto.exportKey('jwk', keyPair.privateKey);
|
|
219
|
-
jwk = await promisifyIE11Op(jwk, 'Error exporting RSA key pair.');
|
|
220
|
-
|
|
221
|
-
// parse raw ArrayBuffer bytes to jwk/json (WebKit/Safari/IE11 quirk)
|
|
222
|
-
if (jwk instanceof ArrayBuffer) {
|
|
223
|
-
jwk = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(jwk)));
|
|
224
|
-
}
|
|
225
|
-
// map JWK parameters to BN
|
|
226
|
-
key = {};
|
|
227
|
-
key.n = new BN(util.b64_to_Uint8Array(jwk.n));
|
|
228
|
-
key.e = E;
|
|
229
|
-
key.d = new BN(util.b64_to_Uint8Array(jwk.d));
|
|
230
|
-
// switch p and q
|
|
231
|
-
key.p = new BN(util.b64_to_Uint8Array(jwk.q));
|
|
232
|
-
key.q = new BN(util.b64_to_Uint8Array(jwk.p));
|
|
233
|
-
// Since p and q are switched in places, we could keep u
|
|
234
|
-
key.u = new BN(util.b64_to_Uint8Array(jwk.qi));
|
|
235
|
-
return key;
|
|
236
|
-
} else if (util.getNodeCrypto() && nodeCrypto.generateKeyPair && RSAPrivateKey) {
|
|
237
|
-
const opts = {
|
|
238
|
-
modulusLength: Number(B.toString(10)),
|
|
239
|
-
publicExponent: Number(E.toString(10)),
|
|
240
|
-
publicKeyEncoding: { type: 'pkcs1', format: 'der' },
|
|
241
|
-
privateKeyEncoding: { type: 'pkcs1', format: 'der' }
|
|
242
|
-
};
|
|
243
|
-
const prv = await new Promise((resolve, reject) => nodeCrypto.generateKeyPair('rsa', opts, (err, _, der) => {
|
|
244
|
-
if (err) {
|
|
245
|
-
reject(err);
|
|
246
|
-
} else {
|
|
247
|
-
resolve(RSAPrivateKey.decode(der, 'der'));
|
|
248
|
-
}
|
|
249
|
-
}));
|
|
250
|
-
/** PGP spec differs from DER spec, DER: `(inverse of q) mod p`, PGP: `(inverse of p) mod q`.
|
|
251
|
-
* @link https://tools.ietf.org/html/rfc3447#section-3.2
|
|
252
|
-
* @link https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-08#section-5.6.1
|
|
253
|
-
*/
|
|
254
|
-
return {
|
|
255
|
-
n: prv.modulus,
|
|
256
|
-
e: prv.publicExponent,
|
|
257
|
-
d: prv.privateExponent,
|
|
258
|
-
// switch p and q
|
|
259
|
-
p: prv.prime2,
|
|
260
|
-
q: prv.prime1,
|
|
261
|
-
// Since p and q are switched in places, we could keep u
|
|
262
|
-
u: prv.coefficient // PGP type of u
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// RSA keygen fallback using 40 iterations of the Miller-Rabin test
|
|
267
|
-
// See https://stackoverflow.com/a/6330138 for justification
|
|
268
|
-
// Also see section C.3 here: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST
|
|
269
|
-
let q = await prime.randomProbablePrime(B - (B >> 1), E, 40);
|
|
270
|
-
let p = await prime.randomProbablePrime(B >> 1, E, 40);
|
|
271
|
-
|
|
272
|
-
if (q.cmp(p) < 0) {
|
|
273
|
-
[p, q] = [q, p];
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const phi = p.subn(1).mul(q.subn(1));
|
|
277
|
-
return {
|
|
278
|
-
n: p.mul(q),
|
|
279
|
-
e: E,
|
|
280
|
-
d: E.invm(phi),
|
|
281
|
-
p: p,
|
|
282
|
-
q: q,
|
|
283
|
-
// dp: d.mod(p.subn(1)),
|
|
284
|
-
// dq: d.mod(q.subn(1)),
|
|
285
|
-
u: p.invm(q)
|
|
286
|
-
};
|
|
287
|
-
},
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Validate RSA parameters
|
|
291
|
-
* @param {Uint8Array} n RSA public modulus
|
|
292
|
-
* @param {Uint8Array} e RSA public exponent
|
|
293
|
-
* @param {Uint8Array} d RSA private exponent
|
|
294
|
-
* @param {Uint8Array} p RSA private prime p
|
|
295
|
-
* @param {Uint8Array} q RSA private prime q
|
|
296
|
-
* @param {Uint8Array} u RSA inverse of p w.r.t. q
|
|
297
|
-
* @returns {Promise<Boolean>} whether params are valid
|
|
298
|
-
* @async
|
|
299
|
-
*/
|
|
300
|
-
validateParams: async function (n, e, d, p, q, u) {
|
|
301
|
-
n = new BN(n);
|
|
302
|
-
p = new BN(p);
|
|
303
|
-
q = new BN(q);
|
|
304
|
-
|
|
305
|
-
// expect pq = n
|
|
306
|
-
if (!p.mul(q).eq(n)) {
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const one = new BN(1);
|
|
311
|
-
const two = new BN(2);
|
|
312
|
-
// expect p*u = 1 mod q
|
|
313
|
-
u = new BN(u);
|
|
314
|
-
if (!p.mul(u).umod(q).eq(one)) {
|
|
315
|
-
return false;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
e = new BN(e);
|
|
319
|
-
d = new BN(d);
|
|
320
|
-
/**
|
|
321
|
-
* In RSA pkcs#1 the exponents (d, e) are inverses modulo lcm(p-1, q-1)
|
|
322
|
-
* We check that [de = 1 mod (p-1)] and [de = 1 mod (q-1)]
|
|
323
|
-
* By CRT on coprime factors of (p-1, q-1) it follows that [de = 1 mod lcm(p-1, q-1)]
|
|
324
|
-
*
|
|
325
|
-
* We blind the multiplication with r, and check that rde = r mod lcm(p-1, q-1)
|
|
326
|
-
*/
|
|
327
|
-
const r = await random.getRandomBN(two, two.shln(n.bitLength() / 3)); // r in [ 2, 2^{|n|/3} ) < p and q
|
|
328
|
-
const rde = r.mul(d).mul(e);
|
|
329
|
-
|
|
330
|
-
const areInverses = rde.umod(p.sub(one)).eq(r) && rde.umod(q.sub(one)).eq(r);
|
|
331
|
-
if (!areInverses) {
|
|
332
|
-
return false;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
return true;
|
|
336
|
-
},
|
|
337
|
-
|
|
338
|
-
bnSign: async function (hash_algo, n, d, hashed) {
|
|
339
|
-
n = new BN(n);
|
|
340
|
-
const m = new BN(await pkcs1.emsa.encode(hash_algo, hashed, n.byteLength()), 16);
|
|
341
|
-
d = new BN(d);
|
|
342
|
-
if (n.cmp(m) <= 0) {
|
|
343
|
-
throw new Error('Message size cannot exceed modulus size');
|
|
344
|
-
}
|
|
345
|
-
const nred = new BN.red(n);
|
|
346
|
-
return m.toRed(nred).redPow(d).toArrayLike(Uint8Array, 'be', n.byteLength());
|
|
347
|
-
},
|
|
348
|
-
|
|
349
|
-
webSign: async function (hash_name, data, n, e, d, p, q, u) {
|
|
350
|
-
/** OpenPGP keys require that p < q, and Safari Web Crypto requires that p > q.
|
|
351
|
-
* We swap them in privateToJwk, so it usually works out, but nevertheless,
|
|
352
|
-
* not all OpenPGP keys are compatible with this requirement.
|
|
353
|
-
* OpenPGP.js used to generate RSA keys the wrong way around (p > q), and still
|
|
354
|
-
* does if the underlying Web Crypto does so (e.g. old MS Edge 50% of the time).
|
|
355
|
-
*/
|
|
356
|
-
const jwk = privateToJwk(n, e, d, p, q, u);
|
|
357
|
-
const algo = {
|
|
358
|
-
name: "RSASSA-PKCS1-v1_5",
|
|
359
|
-
hash: { name: hash_name }
|
|
360
|
-
};
|
|
361
|
-
const key = await webCrypto.importKey("jwk", jwk, algo, false, ["sign"]);
|
|
362
|
-
// add hash field for ms edge support
|
|
363
|
-
return new Uint8Array(await webCrypto.sign({ "name": "RSASSA-PKCS1-v1_5", "hash": hash_name }, key, data));
|
|
364
|
-
},
|
|
365
|
-
|
|
366
|
-
nodeSign: async function (hash_algo, data, n, e, d, p, q, u) {
|
|
367
|
-
const pBNum = new BN(p);
|
|
368
|
-
const qBNum = new BN(q);
|
|
369
|
-
const dBNum = new BN(d);
|
|
370
|
-
const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1)
|
|
371
|
-
const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1)
|
|
372
|
-
const sign = nodeCrypto.createSign(enums.read(enums.hash, hash_algo));
|
|
373
|
-
sign.write(data);
|
|
374
|
-
sign.end();
|
|
375
|
-
const keyObject = {
|
|
376
|
-
version: 0,
|
|
377
|
-
modulus: new BN(n),
|
|
378
|
-
publicExponent: new BN(e),
|
|
379
|
-
privateExponent: new BN(d),
|
|
380
|
-
// switch p and q
|
|
381
|
-
prime1: new BN(q),
|
|
382
|
-
prime2: new BN(p),
|
|
383
|
-
// switch dp and dq
|
|
384
|
-
exponent1: dq,
|
|
385
|
-
exponent2: dp,
|
|
386
|
-
coefficient: new BN(u)
|
|
387
|
-
};
|
|
388
|
-
if (typeof nodeCrypto.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects
|
|
389
|
-
const der = RSAPrivateKey.encode(keyObject, 'der');
|
|
390
|
-
return new Uint8Array(sign.sign({ key: der, format: 'der', type: 'pkcs1' }));
|
|
391
|
-
}
|
|
392
|
-
const pem = RSAPrivateKey.encode(keyObject, 'pem', {
|
|
393
|
-
label: 'RSA PRIVATE KEY'
|
|
394
|
-
});
|
|
395
|
-
return new Uint8Array(sign.sign(pem));
|
|
396
|
-
},
|
|
397
|
-
|
|
398
|
-
bnVerify: async function (hash_algo, s, n, e, hashed) {
|
|
399
|
-
n = new BN(n);
|
|
400
|
-
s = new BN(s);
|
|
401
|
-
e = new BN(e);
|
|
402
|
-
if (n.cmp(s) <= 0) {
|
|
403
|
-
throw new Error('Signature size cannot exceed modulus size');
|
|
404
|
-
}
|
|
405
|
-
const nred = new BN.red(n);
|
|
406
|
-
const EM1 = s.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength());
|
|
407
|
-
const EM2 = await pkcs1.emsa.encode(hash_algo, hashed, n.byteLength());
|
|
408
|
-
return util.Uint8Array_to_hex(EM1) === EM2;
|
|
409
|
-
},
|
|
410
|
-
|
|
411
|
-
webVerify: async function (hash_name, data, s, n, e) {
|
|
412
|
-
const jwk = publicToJwk(n, e);
|
|
413
|
-
const key = await webCrypto.importKey("jwk", jwk, {
|
|
414
|
-
name: "RSASSA-PKCS1-v1_5",
|
|
415
|
-
hash: { name: hash_name }
|
|
416
|
-
}, false, ["verify"]);
|
|
417
|
-
// add hash field for ms edge support
|
|
418
|
-
return webCrypto.verify({ "name": "RSASSA-PKCS1-v1_5", "hash": hash_name }, key, s, data);
|
|
419
|
-
},
|
|
420
|
-
|
|
421
|
-
nodeVerify: async function (hash_algo, data, s, n, e) {
|
|
422
|
-
const verify = nodeCrypto.createVerify(enums.read(enums.hash, hash_algo));
|
|
423
|
-
verify.write(data);
|
|
424
|
-
verify.end();
|
|
425
|
-
const keyObject = {
|
|
426
|
-
modulus: new BN(n),
|
|
427
|
-
publicExponent: new BN(e)
|
|
428
|
-
};
|
|
429
|
-
let key;
|
|
430
|
-
if (typeof nodeCrypto.createPrivateKey !== 'undefined') { //from version 11.6.0 Node supports der encoded key objects
|
|
431
|
-
const der = RSAPublicKey.encode(keyObject, 'der');
|
|
432
|
-
key = { key: der, format: 'der', type: 'pkcs1' };
|
|
433
|
-
} else {
|
|
434
|
-
key = RSAPublicKey.encode(keyObject, 'pem', {
|
|
435
|
-
label: 'RSA PUBLIC KEY'
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
try {
|
|
439
|
-
return await verify.verify(key, s);
|
|
440
|
-
} catch (err) {
|
|
441
|
-
return false;
|
|
442
|
-
}
|
|
443
|
-
},
|
|
444
|
-
|
|
445
|
-
nodeEncrypt: async function (data, n, e) {
|
|
446
|
-
const keyObject = {
|
|
447
|
-
modulus: new BN(n),
|
|
448
|
-
publicExponent: new BN(e)
|
|
449
|
-
};
|
|
450
|
-
let key;
|
|
451
|
-
if (typeof nodeCrypto.createPrivateKey !== 'undefined') {
|
|
452
|
-
const der = RSAPublicKey.encode(keyObject, 'der');
|
|
453
|
-
key = { key: der, format: 'der', type: 'pkcs1', padding: nodeCrypto.constants.RSA_PKCS1_PADDING };
|
|
454
|
-
} else {
|
|
455
|
-
const pem = RSAPublicKey.encode(keyObject, 'pem', {
|
|
456
|
-
label: 'RSA PUBLIC KEY'
|
|
457
|
-
});
|
|
458
|
-
key = { key: pem, padding: nodeCrypto.constants.RSA_PKCS1_PADDING };
|
|
459
|
-
}
|
|
460
|
-
return new Uint8Array(nodeCrypto.publicEncrypt(key, data));
|
|
461
|
-
},
|
|
462
|
-
|
|
463
|
-
bnEncrypt: async function (data, n, e) {
|
|
464
|
-
n = new BN(n);
|
|
465
|
-
data = new type_mpi(await pkcs1.eme.encode(util.Uint8Array_to_str(data), n.byteLength()));
|
|
466
|
-
data = data.toBN();
|
|
467
|
-
e = new BN(e);
|
|
468
|
-
if (n.cmp(data) <= 0) {
|
|
469
|
-
throw new Error('Message size cannot exceed modulus size');
|
|
470
|
-
}
|
|
471
|
-
const nred = new BN.red(n);
|
|
472
|
-
return data.toRed(nred).redPow(e).toArrayLike(Uint8Array, 'be', n.byteLength());
|
|
473
|
-
},
|
|
474
|
-
|
|
475
|
-
nodeDecrypt: function (data, n, e, d, p, q, u) {
|
|
476
|
-
const pBNum = new BN(p);
|
|
477
|
-
const qBNum = new BN(q);
|
|
478
|
-
const dBNum = new BN(d);
|
|
479
|
-
const dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1)
|
|
480
|
-
const dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1)
|
|
481
|
-
const keyObject = {
|
|
482
|
-
version: 0,
|
|
483
|
-
modulus: new BN(n),
|
|
484
|
-
publicExponent: new BN(e),
|
|
485
|
-
privateExponent: new BN(d),
|
|
486
|
-
// switch p and q
|
|
487
|
-
prime1: new BN(q),
|
|
488
|
-
prime2: new BN(p),
|
|
489
|
-
// switch dp and dq
|
|
490
|
-
exponent1: dq,
|
|
491
|
-
exponent2: dp,
|
|
492
|
-
coefficient: new BN(u)
|
|
493
|
-
};
|
|
494
|
-
let key;
|
|
495
|
-
if (typeof nodeCrypto.createPrivateKey !== 'undefined') {
|
|
496
|
-
const der = RSAPrivateKey.encode(keyObject, 'der');
|
|
497
|
-
key = { key: der, format: 'der' , type: 'pkcs1', padding: nodeCrypto.constants.RSA_PKCS1_PADDING };
|
|
498
|
-
} else {
|
|
499
|
-
const pem = RSAPrivateKey.encode(keyObject, 'pem', {
|
|
500
|
-
label: 'RSA PRIVATE KEY'
|
|
501
|
-
});
|
|
502
|
-
key = { key: pem, padding: nodeCrypto.constants.RSA_PKCS1_PADDING };
|
|
503
|
-
}
|
|
504
|
-
return util.Uint8Array_to_str(nodeCrypto.privateDecrypt(key, data));
|
|
505
|
-
},
|
|
506
|
-
|
|
507
|
-
bnDecrypt: async function(data, n, e, d, p, q, u) {
|
|
508
|
-
data = new BN(data);
|
|
509
|
-
n = new BN(n);
|
|
510
|
-
e = new BN(e);
|
|
511
|
-
d = new BN(d);
|
|
512
|
-
p = new BN(p);
|
|
513
|
-
q = new BN(q);
|
|
514
|
-
u = new BN(u);
|
|
515
|
-
if (n.cmp(data) <= 0) {
|
|
516
|
-
throw new Error('Data too large.');
|
|
517
|
-
}
|
|
518
|
-
const dq = d.mod(q.subn(1)); // d mod (q-1)
|
|
519
|
-
const dp = d.mod(p.subn(1)); // d mod (p-1)
|
|
520
|
-
const pred = new BN.red(p);
|
|
521
|
-
const qred = new BN.red(q);
|
|
522
|
-
const nred = new BN.red(n);
|
|
523
|
-
|
|
524
|
-
let blinder;
|
|
525
|
-
let unblinder;
|
|
526
|
-
if (config.rsa_blinding) {
|
|
527
|
-
unblinder = (await random.getRandomBN(new BN(2), n)).toRed(nred);
|
|
528
|
-
blinder = unblinder.redInvm().redPow(e);
|
|
529
|
-
data = data.toRed(nred).redMul(blinder).fromRed();
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
const mp = data.toRed(pred).redPow(dp);
|
|
533
|
-
const mq = data.toRed(qred).redPow(dq);
|
|
534
|
-
const t = mq.redSub(mp.fromRed().toRed(qred));
|
|
535
|
-
const h = u.toRed(qred).redMul(t).fromRed();
|
|
536
|
-
|
|
537
|
-
let result = h.mul(p).add(mp).toRed(nred);
|
|
538
|
-
|
|
539
|
-
if (config.rsa_blinding) {
|
|
540
|
-
result = result.redMul(unblinder);
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
return pkcs1.eme.decode((new type_mpi(result)).toString());
|
|
544
|
-
},
|
|
545
|
-
|
|
546
|
-
prime: prime
|
|
547
|
-
};
|
|
548
|
-
|
|
549
|
-
/** Convert Openpgp private key params to jwk key according to
|
|
550
|
-
* @link https://tools.ietf.org/html/rfc7517
|
|
551
|
-
* @param {String} hash_algo
|
|
552
|
-
* @param {Uint8Array} n
|
|
553
|
-
* @param {Uint8Array} e
|
|
554
|
-
* @param {Uint8Array} d
|
|
555
|
-
* @param {Uint8Array} p
|
|
556
|
-
* @param {Uint8Array} q
|
|
557
|
-
* @param {Uint8Array} u
|
|
558
|
-
*/
|
|
559
|
-
function privateToJwk(n, e, d, p, q, u) {
|
|
560
|
-
const pBNum = new BN(p);
|
|
561
|
-
const qBNum = new BN(q);
|
|
562
|
-
const dBNum = new BN(d);
|
|
563
|
-
|
|
564
|
-
let dq = dBNum.mod(qBNum.subn(1)); // d mod (q-1)
|
|
565
|
-
let dp = dBNum.mod(pBNum.subn(1)); // d mod (p-1)
|
|
566
|
-
dp = dp.toArrayLike(Uint8Array);
|
|
567
|
-
dq = dq.toArrayLike(Uint8Array);
|
|
568
|
-
return {
|
|
569
|
-
kty: 'RSA',
|
|
570
|
-
n: util.Uint8Array_to_b64(n, true),
|
|
571
|
-
e: util.Uint8Array_to_b64(e, true),
|
|
572
|
-
d: util.Uint8Array_to_b64(d, true),
|
|
573
|
-
// switch p and q
|
|
574
|
-
p: util.Uint8Array_to_b64(q, true),
|
|
575
|
-
q: util.Uint8Array_to_b64(p, true),
|
|
576
|
-
// switch dp and dq
|
|
577
|
-
dp: util.Uint8Array_to_b64(dq, true),
|
|
578
|
-
dq: util.Uint8Array_to_b64(dp, true),
|
|
579
|
-
qi: util.Uint8Array_to_b64(u, true),
|
|
580
|
-
ext: true
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
/** Convert Openpgp key public params to jwk key according to
|
|
585
|
-
* @link https://tools.ietf.org/html/rfc7517
|
|
586
|
-
* @param {String} hash_algo
|
|
587
|
-
* @param {Uint8Array} n
|
|
588
|
-
* @param {Uint8Array} e
|
|
589
|
-
*/
|
|
590
|
-
function publicToJwk(n, e) {
|
|
591
|
-
return {
|
|
592
|
-
kty: 'RSA',
|
|
593
|
-
n: util.Uint8Array_to_b64(n, true),
|
|
594
|
-
e: util.Uint8Array_to_b64(e, true),
|
|
595
|
-
ext: true
|
|
596
|
-
};
|
|
597
|
-
}
|