@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.
Files changed (173) hide show
  1. package/README.md +311 -239
  2. package/dist/lightweight/bn.interface.min.mjs +3 -0
  3. package/dist/lightweight/bn.interface.min.mjs.map +1 -0
  4. package/dist/lightweight/bn.interface.mjs +340 -0
  5. package/dist/lightweight/bn.min.mjs +3 -0
  6. package/dist/lightweight/bn.min.mjs.map +1 -0
  7. package/dist/lightweight/bn.mjs +3434 -0
  8. package/dist/lightweight/elliptic.min.mjs +3 -0
  9. package/dist/lightweight/elliptic.min.mjs.map +1 -0
  10. package/dist/lightweight/elliptic.mjs +4313 -0
  11. package/dist/lightweight/openpgp.min.mjs +3 -0
  12. package/dist/lightweight/openpgp.min.mjs.map +1 -0
  13. package/dist/lightweight/openpgp.mjs +31375 -0
  14. package/dist/lightweight/ponyfill.es6.min.mjs +3 -0
  15. package/dist/lightweight/ponyfill.es6.min.mjs.map +1 -0
  16. package/dist/lightweight/ponyfill.es6.mjs +3831 -0
  17. package/dist/lightweight/web-streams-adapter.min.mjs +17 -0
  18. package/dist/lightweight/web-streams-adapter.min.mjs.map +1 -0
  19. package/dist/lightweight/web-streams-adapter.mjs +561 -0
  20. package/dist/node/openpgp.js +43943 -0
  21. package/dist/node/openpgp.min.js +17 -0
  22. package/dist/node/openpgp.min.js.map +1 -0
  23. package/dist/node/openpgp.min.mjs +17 -0
  24. package/dist/node/openpgp.min.mjs.map +1 -0
  25. package/dist/node/openpgp.mjs +43880 -0
  26. package/dist/openpgp.js +41080 -41565
  27. package/dist/openpgp.min.js +17 -2
  28. package/dist/openpgp.min.js.map +1 -0
  29. package/dist/openpgp.min.mjs +17 -0
  30. package/dist/openpgp.min.mjs.map +1 -0
  31. package/dist/openpgp.mjs +43868 -0
  32. package/lightweight/package.json +5 -0
  33. package/openpgp.d.ts +889 -0
  34. package/package.json +63 -57
  35. package/dist/compat/openpgp.js +0 -61067
  36. package/dist/compat/openpgp.min.js +0 -2
  37. package/dist/compat/openpgp.worker.js +0 -173
  38. package/dist/compat/openpgp.worker.min.js +0 -2
  39. package/dist/lightweight/elliptic.min.js +0 -5
  40. package/dist/lightweight/openpgp.js +0 -40024
  41. package/dist/lightweight/openpgp.min.js +0 -2
  42. package/dist/lightweight/openpgp.worker.js +0 -173
  43. package/dist/lightweight/openpgp.worker.min.js +0 -2
  44. package/dist/openpgp.worker.js +0 -173
  45. package/dist/openpgp.worker.min.js +0 -2
  46. package/src/cleartext.js +0 -220
  47. package/src/config/config.js +0 -224
  48. package/src/config/index.js +0 -7
  49. package/src/config/localStorage.js +0 -35
  50. package/src/crypto/aes_kw.js +0 -153
  51. package/src/crypto/cfb.js +0 -169
  52. package/src/crypto/cipher/aes.js +0 -27
  53. package/src/crypto/cipher/blowfish.js +0 -398
  54. package/src/crypto/cipher/cast5.js +0 -610
  55. package/src/crypto/cipher/des.js +0 -476
  56. package/src/crypto/cipher/index.js +0 -91
  57. package/src/crypto/cipher/twofish.js +0 -346
  58. package/src/crypto/cmac.js +0 -98
  59. package/src/crypto/crypto.js +0 -394
  60. package/src/crypto/eax.js +0 -172
  61. package/src/crypto/gcm.js +0 -141
  62. package/src/crypto/hash/index.js +0 -163
  63. package/src/crypto/hash/md5.js +0 -205
  64. package/src/crypto/index.js +0 -57
  65. package/src/crypto/ocb.js +0 -274
  66. package/src/crypto/pkcs1.js +0 -170
  67. package/src/crypto/pkcs5.js +0 -55
  68. package/src/crypto/public_key/dsa.js +0 -188
  69. package/src/crypto/public_key/elgamal.js +0 -137
  70. package/src/crypto/public_key/elliptic/curves.js +0 -385
  71. package/src/crypto/public_key/elliptic/ecdh.js +0 -414
  72. package/src/crypto/public_key/elliptic/ecdsa.js +0 -348
  73. package/src/crypto/public_key/elliptic/eddsa.js +0 -119
  74. package/src/crypto/public_key/elliptic/index.js +0 -34
  75. package/src/crypto/public_key/elliptic/indutnyKey.js +0 -85
  76. package/src/crypto/public_key/index.js +0 -28
  77. package/src/crypto/public_key/prime.js +0 -275
  78. package/src/crypto/public_key/rsa.js +0 -597
  79. package/src/crypto/random.js +0 -145
  80. package/src/crypto/signature.js +0 -137
  81. package/src/encoding/armor.js +0 -433
  82. package/src/encoding/base64.js +0 -96
  83. package/src/enums.js +0 -493
  84. package/src/hkp.js +0 -89
  85. package/src/index.js +0 -161
  86. package/src/key/factory.js +0 -326
  87. package/src/key/helper.js +0 -363
  88. package/src/key/index.js +0 -32
  89. package/src/key/key.js +0 -890
  90. package/src/key/subkey.js +0 -187
  91. package/src/key/user.js +0 -230
  92. package/src/keyring/index.js +0 -12
  93. package/src/keyring/keyring.js +0 -229
  94. package/src/keyring/localstore.js +0 -119
  95. package/src/lightweight_helper.js +0 -26
  96. package/src/message.js +0 -825
  97. package/src/openpgp.js +0 -717
  98. package/src/packet/all_packets.js +0 -116
  99. package/src/packet/clone.js +0 -189
  100. package/src/packet/compressed.js +0 -194
  101. package/src/packet/index.js +0 -20
  102. package/src/packet/literal.js +0 -168
  103. package/src/packet/marker.js +0 -62
  104. package/src/packet/one_pass_signature.js +0 -156
  105. package/src/packet/packet.js +0 -300
  106. package/src/packet/packetlist.js +0 -232
  107. package/src/packet/public_key.js +0 -280
  108. package/src/packet/public_key_encrypted_session_key.js +0 -156
  109. package/src/packet/public_subkey.js +0 -44
  110. package/src/packet/secret_key.js +0 -448
  111. package/src/packet/secret_subkey.js +0 -41
  112. package/src/packet/signature.js +0 -782
  113. package/src/packet/sym_encrypted_aead_protected.js +0 -189
  114. package/src/packet/sym_encrypted_integrity_protected.js +0 -139
  115. package/src/packet/sym_encrypted_session_key.js +0 -204
  116. package/src/packet/symmetrically_encrypted.js +0 -118
  117. package/src/packet/trust.js +0 -35
  118. package/src/packet/user_attribute.js +0 -94
  119. package/src/packet/userid.js +0 -87
  120. package/src/polyfills.js +0 -64
  121. package/src/signature.js +0 -73
  122. package/src/type/ecdh_symkey.js +0 -69
  123. package/src/type/kdf_params.js +0 -114
  124. package/src/type/keyid.js +0 -110
  125. package/src/type/mpi.js +0 -138
  126. package/src/type/oid.js +0 -110
  127. package/src/type/s2k.js +0 -203
  128. package/src/util.js +0 -836
  129. package/src/wkd.js +0 -88
  130. package/src/worker/async_proxy.js +0 -190
  131. package/src/worker/worker.js +0 -167
  132. package/test/crypto/aes_kw.js +0 -57
  133. package/test/crypto/cipher/aes.js +0 -86
  134. package/test/crypto/cipher/blowfish.js +0 -58
  135. package/test/crypto/cipher/cast5.js +0 -25
  136. package/test/crypto/cipher/des.js +0 -143
  137. package/test/crypto/cipher/index.js +0 -7
  138. package/test/crypto/cipher/twofish.js +0 -71
  139. package/test/crypto/crypto.js +0 -383
  140. package/test/crypto/eax.js +0 -150
  141. package/test/crypto/ecdh.js +0 -359
  142. package/test/crypto/elliptic.js +0 -251
  143. package/test/crypto/elliptic_data.js +0 -102
  144. package/test/crypto/hash/index.js +0 -5
  145. package/test/crypto/hash/md5.js +0 -16
  146. package/test/crypto/hash/ripemd.js +0 -14
  147. package/test/crypto/hash/sha.js +0 -20
  148. package/test/crypto/index.js +0 -14
  149. package/test/crypto/ocb.js +0 -183
  150. package/test/crypto/pkcs5.js +0 -39
  151. package/test/crypto/random.js +0 -79
  152. package/test/crypto/rsa.js +0 -180
  153. package/test/crypto/validate.js +0 -387
  154. package/test/general/armor.js +0 -408
  155. package/test/general/brainpool.js +0 -360
  156. package/test/general/decompression.js +0 -60
  157. package/test/general/ecc_nist.js +0 -115
  158. package/test/general/ecc_secp256k1.js +0 -242
  159. package/test/general/forwarding.js +0 -43
  160. package/test/general/hkp.js +0 -165
  161. package/test/general/index.js +0 -20
  162. package/test/general/key.js +0 -3402
  163. package/test/general/keyring.js +0 -336
  164. package/test/general/oid.js +0 -39
  165. package/test/general/openpgp.js +0 -2542
  166. package/test/general/packet.js +0 -937
  167. package/test/general/signature.js +0 -1665
  168. package/test/general/streaming.js +0 -944
  169. package/test/general/testInputs.js +0 -18
  170. package/test/general/util.js +0 -183
  171. package/test/general/wkd.js +0 -48
  172. package/test/general/x25519.js +0 -556
  173. package/test/unittests.js +0 -64
package/src/openpgp.js DELETED
@@ -1,717 +0,0 @@
1
- // OpenPGP.js - An OpenPGP implementation in javascript
2
- // Copyright (C) 2016 Tankred Hase
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 The openpgp base module should provide all of the functionality
20
- * to consume the openpgp.js library. All additional classes are documented
21
- * for extending and developing on top of the base library.
22
- * @requires web-stream-tools
23
- * @requires message
24
- * @requires cleartext
25
- * @requires key
26
- * @requires config
27
- * @requires enums
28
- * @requires util
29
- * @requires polyfills
30
- * @requires worker/async_proxy
31
- * @module openpgp
32
- */
33
-
34
- // This file intentionally has two separate file overviews so that
35
- // a reference to this module appears at the end of doc/index.html.
36
-
37
- /**
38
- * @fileoverview To view the full API documentation, start from
39
- * {@link module:openpgp}
40
- */
41
-
42
- import stream from 'web-stream-tools';
43
- import * as messageLib from './message';
44
- import { CleartextMessage } from './cleartext';
45
- import { generate, reformat } from './key';
46
- import config from './config/config';
47
- import enums from './enums';
48
- import './polyfills';
49
- import util from './util';
50
- import AsyncProxy from './worker/async_proxy';
51
-
52
- //////////////////////////
53
- // //
54
- // Web Worker setup //
55
- // //
56
- //////////////////////////
57
-
58
-
59
- let asyncProxy; // instance of the asyncproxy
60
-
61
- /**
62
- * Set the path for the web worker script and create an instance of the async proxy
63
- * @param {String} path relative path to the worker scripts, default: 'openpgp.worker.js'
64
- * @param {Number} n number of workers to initialize
65
- * @param {Array<Object>} workers alternative to path parameter: web workers initialized with 'openpgp.worker.js'
66
- * @returns {Promise<Boolean>} returns a promise that resolves to true if all workers have succesfully finished loading
67
- * @async
68
- */
69
- export async function initWorker({ path = 'openpgp.worker.js', n = 1, workers = [] } = {}) {
70
- if (workers.length || (typeof global !== 'undefined' && global.Worker && global.MessageChannel)) {
71
- const proxy = new AsyncProxy({ path, n, workers, config });
72
- const loaded = await proxy.loaded();
73
- if (loaded) {
74
- asyncProxy = proxy;
75
- return true;
76
- }
77
- }
78
- return false;
79
- }
80
-
81
- /**
82
- * Returns a reference to the async proxy if the worker was initialized with openpgp.initWorker()
83
- * @returns {module:worker/async_proxy.AsyncProxy|null} the async proxy or null if not initialized
84
- */
85
- export function getWorker() {
86
- return asyncProxy;
87
- }
88
-
89
- /**
90
- * Cleanup the current instance of the web worker.
91
- */
92
- export async function destroyWorker() {
93
- const proxy = asyncProxy;
94
- asyncProxy = undefined;
95
- if (proxy) {
96
- await proxy.clearKeyCache();
97
- proxy.terminate();
98
- }
99
- }
100
-
101
-
102
- //////////////////////
103
- // //
104
- // Key handling //
105
- // //
106
- //////////////////////
107
-
108
-
109
- /**
110
- * Generates a new OpenPGP key pair. Supports RSA and ECC keys. Primary and subkey will be of same type.
111
- * @param {Array<Object>} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
112
- * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
113
- * @param {Number} rsaBits (optional) number of bits for RSA keys: 2048 or 4096.
114
- * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires
115
- * @param {String} curve (optional) elliptic curve for ECC keys:
116
- * curve25519, p256, p384, p521, secp256k1,
117
- * brainpoolP256r1, brainpoolP384r1, or brainpoolP512r1.
118
- * @param {Date} date (optional) override the creation date of the key and the key signatures
119
- * @param {Array<Object>} subkeys (optional) options for each subkey, default to main key options. e.g. [{sign: true, passphrase: '123'}]
120
- * sign parameter defaults to false, and indicates whether the subkey should sign rather than encrypt
121
- * @returns {Promise<Object>} The generated key object in the form:
122
- * { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String }
123
- * @async
124
- * @static
125
- */
126
-
127
- export function generateKey({ userIds = [], passphrase = "", numBits = 2048, rsaBits = numBits, keyExpirationTime = 0, curve = "", date = new Date(), subkeys = [{}] }) {
128
- userIds = toArray(userIds);
129
- const options = { userIds, passphrase, rsaBits, keyExpirationTime, curve, date, subkeys };
130
- if (util.getWebCryptoAll() && rsaBits < 2048) {
131
- throw new Error('rsaBits should be 2048 or 4096, found: ' + rsaBits);
132
- }
133
-
134
- if (!util.getWebCryptoAll() && asyncProxy) { // use web worker if web crypto apis are not supported
135
- return asyncProxy.delegate('generateKey', options);
136
- }
137
-
138
- return generate(options).then(async key => {
139
- const revocationCertificate = await key.getRevocationCertificate(date);
140
- key.revocationSignatures = [];
141
-
142
- return convertStreams({
143
-
144
- key: key,
145
- privateKeyArmored: key.armor(),
146
- publicKeyArmored: key.toPublic().armor(),
147
- revocationCertificate: revocationCertificate
148
-
149
- });
150
- }).catch(onError.bind(null, 'Error generating keypair'));
151
- }
152
-
153
- /**
154
- * Reformats signature packets for a key and rewraps key object.
155
- * @param {Key} privateKey private key to reformat
156
- * @param {Array<Object>} userIds array of user IDs e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
157
- * @param {String} passphrase (optional) The passphrase used to encrypt the resulting private key
158
- * @param {Number} keyExpirationTime (optional) The number of seconds after the key creation time that the key expires
159
- * @returns {Promise<Object>} The generated key object in the form:
160
- * { key:Key, privateKeyArmored:String, publicKeyArmored:String, revocationCertificate:String }
161
- * @async
162
- * @static
163
- */
164
- export function reformatKey({ privateKey, userIds = [], passphrase = "", keyExpirationTime = 0, date }) {
165
- userIds = toArray(userIds);
166
- const options = { privateKey, userIds, passphrase, keyExpirationTime, date };
167
- if (asyncProxy) {
168
- return asyncProxy.delegate('reformatKey', options);
169
- }
170
-
171
- return reformat(options).then(async key => {
172
- const revocationCertificate = await key.getRevocationCertificate(date);
173
- key.revocationSignatures = [];
174
-
175
- return convertStreams({
176
-
177
- key: key,
178
- privateKeyArmored: key.armor(),
179
- publicKeyArmored: key.toPublic().armor(),
180
- revocationCertificate: revocationCertificate
181
-
182
- });
183
- }).catch(onError.bind(null, 'Error reformatting keypair'));
184
- }
185
-
186
- /**
187
- * Revokes a key. Requires either a private key or a revocation certificate.
188
- * If a revocation certificate is passed, the reasonForRevocation parameters will be ignored.
189
- * @param {Key} key (optional) public or private key to revoke
190
- * @param {String} revocationCertificate (optional) revocation certificate to revoke the key with
191
- * @param {Object} reasonForRevocation (optional) object indicating the reason for revocation
192
- * @param {module:enums.reasonForRevocation} reasonForRevocation.flag (optional) flag indicating the reason for revocation
193
- * @param {String} reasonForRevocation.string (optional) string explaining the reason for revocation
194
- * @returns {Promise<Object>} The revoked key object in the form:
195
- * { privateKey:Key, privateKeyArmored:String, publicKey:Key, publicKeyArmored:String }
196
- * (if private key is passed) or { publicKey:Key, publicKeyArmored:String } (otherwise)
197
- * @static
198
- */
199
- export function revokeKey({
200
- key, revocationCertificate, reasonForRevocation
201
- } = {}) {
202
- const options = {
203
- key, revocationCertificate, reasonForRevocation
204
- };
205
-
206
- if (!util.getWebCryptoAll() && asyncProxy) { // use web worker if web crypto apis are not supported
207
- return asyncProxy.delegate('revokeKey', options);
208
- }
209
-
210
- return Promise.resolve().then(() => {
211
- if (revocationCertificate) {
212
- return key.applyRevocationCertificate(revocationCertificate);
213
- } else {
214
- return key.revoke(reasonForRevocation);
215
- }
216
- }).then(async key => {
217
- await convertStreams(key);
218
- if (key.isPrivate()) {
219
- const publicKey = key.toPublic();
220
- return {
221
- privateKey: key,
222
- privateKeyArmored: key.armor(),
223
- publicKey: publicKey,
224
- publicKeyArmored: publicKey.armor()
225
- };
226
- }
227
- return {
228
- publicKey: key,
229
- publicKeyArmored: key.armor()
230
- };
231
- }).catch(onError.bind(null, 'Error revoking key'));
232
- }
233
-
234
- /**
235
- * Unlock a private key with your passphrase.
236
- * @param {Key} privateKey the private key that is to be decrypted
237
- * @param {String|Array<String>} passphrase the user's passphrase(s) chosen during key generation
238
- * @returns {Promise<Object>} the unlocked key object in the form: { key:Key }
239
- * @async
240
- */
241
- export function decryptKey({ privateKey, passphrase }) {
242
- if (asyncProxy) { // use web worker if available
243
- return asyncProxy.delegate('decryptKey', { privateKey, passphrase });
244
- }
245
-
246
- return Promise.resolve().then(async function() {
247
- await privateKey.decrypt(passphrase);
248
-
249
- return {
250
- key: privateKey
251
- };
252
- }).catch(onError.bind(null, 'Error decrypting private key'));
253
- }
254
-
255
- /**
256
- * Lock a private key with your passphrase.
257
- * @param {Key} privateKey the private key that is to be decrypted
258
- * @param {String|Array<String>} passphrase the user's passphrase(s) chosen during key generation
259
- * @returns {Promise<Object>} the locked key object in the form: { key:Key }
260
- * @async
261
- */
262
- export function encryptKey({ privateKey, passphrase }) {
263
- if (asyncProxy) { // use web worker if available
264
- return asyncProxy.delegate('encryptKey', { privateKey, passphrase });
265
- }
266
-
267
- return Promise.resolve().then(async function() {
268
- await privateKey.encrypt(passphrase);
269
-
270
- return {
271
- key: privateKey
272
- };
273
- }).catch(onError.bind(null, 'Error decrypting private key'));
274
- }
275
-
276
-
277
- ///////////////////////////////////////////
278
- // //
279
- // Message encryption and decryption //
280
- // //
281
- ///////////////////////////////////////////
282
-
283
-
284
- /**
285
- * Encrypts message text/data with public keys, passwords or both at once. At least either public keys or passwords
286
- * must be specified. If private keys are specified, those will be used to sign the message.
287
- * @param {Message} message message to be encrypted as created by openpgp.message.fromText or openpgp.message.fromBinary
288
- * @param {Key|Array<Key>} publicKeys (optional) array of keys or single key, used to encrypt the message
289
- * @param {Key|Array<Key>} privateKeys (optional) private keys for signing. If omitted message will not be signed
290
- * @param {String|Array<String>} passwords (optional) array of passwords or a single password to encrypt the message
291
- * @param {Object} sessionKey (optional) session key in the form: { data:Uint8Array, algorithm:String }
292
- * @param {module:enums.compression} compression (optional) which compression algorithm to compress the message with, defaults to what is specified in config
293
- * @param {Boolean} armor (optional) if the return values should be ascii armored or the message/signature objects
294
- * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
295
- * @param {Boolean} detached (optional) if the signature should be detached (if true, signature will be added to returned object)
296
- * @param {Signature} signature (optional) a detached signature to add to the encrypted message
297
- * @param {Boolean} returnSessionKey (optional) if the unencrypted session key should be added to returned object
298
- * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
299
- * @param {Date} date (optional) override the creation date of the message signature
300
- * @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
301
- * @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Robert Receiver', email:'robert@openpgp.org' }]
302
- * @returns {Promise<Object>} Object containing encrypted (and optionally signed) message in the form:
303
- *
304
- * {
305
- * data: String|ReadableStream<String>|NodeStream, (if `armor` was true, the default)
306
- * message: Message, (if `armor` was false)
307
- * signature: String|ReadableStream<String>|NodeStream, (if `detached` was true and `armor` was true)
308
- * signature: Signature (if `detached` was true and `armor` was false)
309
- * sessionKey: { data, algorithm, aeadAlgorithm } (if `returnSessionKey` was true)
310
- * }
311
- * @async
312
- * @static
313
- */
314
- export function encrypt({ message, publicKeys, privateKeys, passwords, sessionKey, compression = config.compression, armor = true, streaming = message && message.fromStream, detached = false, signature = null, returnSessionKey = false, wildcard = false, date = new Date(), fromUserIds = [], toUserIds = [] }) {
315
- checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); fromUserIds = toArray(fromUserIds); toUserIds = toArray(toUserIds);
316
-
317
- if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
318
- return asyncProxy.delegate('encrypt', { message, publicKeys, privateKeys, passwords, sessionKey, compression, armor, streaming, detached, signature, returnSessionKey, wildcard, date, fromUserIds, toUserIds });
319
- }
320
- const result = {};
321
- return Promise.resolve().then(async function() {
322
- if (!privateKeys) {
323
- privateKeys = [];
324
- }
325
- if (privateKeys.length || signature) { // sign the message only if private keys or signature is specified
326
- if (detached) {
327
- const detachedSignature = await message.signDetached(privateKeys, signature, date, fromUserIds, message.fromStream);
328
- result.signature = armor ? detachedSignature.armor() : detachedSignature;
329
- } else {
330
- message = await message.sign(privateKeys, signature, date, fromUserIds, message.fromStream);
331
- }
332
- }
333
- message = message.compress(compression);
334
- return message.encrypt(publicKeys, passwords, sessionKey, wildcard, date, toUserIds, streaming);
335
-
336
- }).then(async encrypted => {
337
- if (armor) {
338
- result.data = encrypted.message.armor();
339
- } else {
340
- result.message = encrypted.message;
341
- }
342
- if (returnSessionKey) {
343
- result.sessionKey = encrypted.sessionKey;
344
- }
345
- return convertStreams(result, streaming, armor ? ['signature', 'data'] : []);
346
- }).catch(onError.bind(null, 'Error encrypting message'));
347
- }
348
-
349
- /**
350
- * Decrypts a message with the user's private key, a session key or a password. Either a private key,
351
- * a session key or a password must be specified.
352
- * @param {Message} message the message object with the encrypted data
353
- * @param {Key|Array<Key>} privateKeys (optional) private keys with decrypted secret key data or session key
354
- * @param {String|Array<String>} passwords (optional) passwords to decrypt the message
355
- * @param {Object|Array<Object>} sessionKeys (optional) session keys in the form: { data:Uint8Array, algorithm:String }
356
- * @param {Key|Array<Key>} publicKeys (optional) array of public keys or single key, to verify signatures
357
- * @param {'utf8'|'binary'} format (optional) whether to return data as a string(Stream) or Uint8Array(Stream). If 'utf8' (the default), also normalize newlines.
358
- * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
359
- * @param {Signature} signature (optional) detached signature for verification
360
- * @param {Date} date (optional) use the given date for verification instead of the current time
361
- * @returns {Promise<Object>} Object containing decrypted and verified message in the form:
362
- *
363
- * {
364
- * data: String|ReadableStream<String>|NodeStream, (if format was 'utf8', the default)
365
- * data: Uint8Array|ReadableStream<Uint8Array>|NodeStream, (if format was 'binary')
366
- * filename: String,
367
- * signatures: [
368
- * {
369
- * keyid: module:type/keyid,
370
- * verified: Promise<Boolean>,
371
- * valid: Boolean (if streaming was false)
372
- * }, ...
373
- * ]
374
- * }
375
- * @async
376
- * @static
377
- */
378
- export function decrypt({ message, privateKeys, passwords, sessionKeys, publicKeys, format = 'utf8', streaming = message && message.fromStream, signature = null, date = new Date() }) {
379
- checkMessage(message); publicKeys = toArray(publicKeys); privateKeys = toArray(privateKeys); passwords = toArray(passwords); sessionKeys = toArray(sessionKeys);
380
-
381
- if (!nativeAEAD() && asyncProxy) { // use web worker if web crypto apis are not supported
382
- return asyncProxy.delegate('decrypt', { message, privateKeys, passwords, sessionKeys, publicKeys, format, streaming, signature, date });
383
- }
384
-
385
- return message.decrypt(privateKeys, passwords, sessionKeys, streaming).then(async function(decrypted) {
386
- if (!publicKeys) {
387
- publicKeys = [];
388
- }
389
-
390
- const result = {};
391
- result.signatures = signature ? await decrypted.verifyDetached(signature, publicKeys, date, streaming) : await decrypted.verify(publicKeys, date, streaming);
392
- result.data = format === 'binary' ? decrypted.getLiteralData() : decrypted.getText();
393
- result.filename = decrypted.getFilename();
394
- if (streaming) linkStreams(result, message);
395
- result.data = await convertStream(result.data, streaming);
396
- if (!streaming) await prepareSignatures(result.signatures);
397
- return result;
398
- }).catch(onError.bind(null, 'Error decrypting message'));
399
- }
400
-
401
-
402
- //////////////////////////////////////////
403
- // //
404
- // Message signing and verification //
405
- // //
406
- //////////////////////////////////////////
407
-
408
-
409
- /**
410
- * Signs a cleartext message.
411
- * @param {CleartextMessage|Message} message (cleartext) message to be signed
412
- * @param {Key|Array<Key>} privateKeys array of keys or single key with decrypted secret key data to sign cleartext
413
- * @param {Boolean} armor (optional) if the return value should be ascii armored or the message object
414
- * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
415
- * @param {Boolean} detached (optional) if the return value should contain a detached signature
416
- * @param {Date} date (optional) override the creation date of the signature
417
- * @param {Array} fromUserIds (optional) array of user IDs to sign with, one per key in `privateKeys`, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
418
- * @returns {Promise<Object>} Object containing signed message in the form:
419
- *
420
- * {
421
- * data: String|ReadableStream<String>|NodeStream, (if `armor` was true, the default)
422
- * message: Message (if `armor` was false)
423
- * }
424
- *
425
- * Or, if `detached` was true:
426
- *
427
- * {
428
- * signature: String|ReadableStream<String>|NodeStream, (if `armor` was true, the default)
429
- * signature: Signature (if `armor` was false)
430
- * }
431
- * @async
432
- * @static
433
- */
434
- export function sign({ message, privateKeys, armor = true, streaming = message && message.fromStream, detached = false, date = new Date(), fromUserIds = [] }) {
435
- checkCleartextOrMessage(message);
436
- privateKeys = toArray(privateKeys); fromUserIds = toArray(fromUserIds);
437
- if (asyncProxy) { // use web worker if available
438
- return asyncProxy.delegate('sign', {
439
- message, privateKeys, armor, streaming, detached, date, fromUserIds
440
- });
441
- }
442
-
443
- const result = {};
444
- return Promise.resolve().then(async function() {
445
- if (detached) {
446
- const signature = await message.signDetached(privateKeys, undefined, date, fromUserIds, message.fromStream);
447
- result.signature = armor ? signature.armor() : signature;
448
- if (message.packets) {
449
- result.signature = stream.transformPair(message.packets.write(), async (readable, writable) => {
450
- await Promise.all([
451
- stream.pipe(result.signature, writable),
452
- stream.readToEnd(readable).catch(() => {})
453
- ]);
454
- });
455
- }
456
- } else {
457
- message = await message.sign(privateKeys, undefined, date, fromUserIds, message.fromStream);
458
- if (armor) {
459
- result.data = message.armor();
460
- } else {
461
- result.message = message;
462
- }
463
- }
464
- return convertStreams(result, streaming, armor ? ['signature', 'data'] : []);
465
- }).catch(onError.bind(null, 'Error signing cleartext message'));
466
- }
467
-
468
- /**
469
- * Verifies signatures of cleartext signed message
470
- * @param {Key|Array<Key>} publicKeys array of publicKeys or single key, to verify signatures
471
- * @param {CleartextMessage|Message} message (cleartext) message object with signatures
472
- * @param {'web'|'node'|false} streaming (optional) whether to return data as a stream. Defaults to the type of stream `message` was created from, if any.
473
- * @param {Signature} signature (optional) detached signature for verification
474
- * @param {Date} date (optional) use the given date for verification instead of the current time
475
- * @returns {Promise<Object>} Object containing verified message in the form:
476
- *
477
- * {
478
- * data: String|ReadableStream<String>|NodeStream, (if `message` was a CleartextMessage)
479
- * data: Uint8Array|ReadableStream<Uint8Array>|NodeStream, (if `message` was a Message)
480
- * signatures: [
481
- * {
482
- * keyid: module:type/keyid,
483
- * verified: Promise<Boolean>,
484
- * valid: Boolean (if `streaming` was false)
485
- * }, ...
486
- * ]
487
- * }
488
- * @async
489
- * @static
490
- */
491
- export function verify({ message, publicKeys, streaming = message && message.fromStream, signature = null, date = new Date() }) {
492
- checkCleartextOrMessage(message);
493
- publicKeys = toArray(publicKeys);
494
-
495
- if (asyncProxy) { // use web worker if available
496
- return asyncProxy.delegate('verify', { message, publicKeys, streaming, signature, date });
497
- }
498
-
499
- return Promise.resolve().then(async function() {
500
- const result = {};
501
- result.signatures = signature ? await message.verifyDetached(signature, publicKeys, date, streaming) : await message.verify(publicKeys, date, streaming);
502
- result.data = message instanceof CleartextMessage ? message.getText() : message.getLiteralData();
503
- if (streaming) linkStreams(result, message);
504
- result.data = await convertStream(result.data, streaming);
505
- if (!streaming) await prepareSignatures(result.signatures);
506
- return result;
507
- }).catch(onError.bind(null, 'Error verifying cleartext signed message'));
508
- }
509
-
510
-
511
- ///////////////////////////////////////////////
512
- // //
513
- // Session key encryption and decryption //
514
- // //
515
- ///////////////////////////////////////////////
516
-
517
-
518
- /**
519
- * Encrypt a symmetric session key with public keys, passwords, or both at once. At least either public keys
520
- * or passwords must be specified.
521
- * @param {Uint8Array} data the session key to be encrypted e.g. 16 random bytes (for aes128)
522
- * @param {String} algorithm algorithm of the symmetric session key e.g. 'aes128' or 'aes256'
523
- * @param {String} aeadAlgorithm (optional) aead algorithm, e.g. 'eax' or 'ocb'
524
- * @param {Key|Array<Key>} publicKeys (optional) array of public keys or single key, used to encrypt the key
525
- * @param {String|Array<String>} passwords (optional) passwords for the message
526
- * @param {Boolean} wildcard (optional) use a key ID of 0 instead of the public key IDs
527
- * @param {Date} date (optional) override the date
528
- * @param {Array} toUserIds (optional) array of user IDs to encrypt for, one per key in `publicKeys`, e.g. [{ name:'Phil Zimmermann', email:'phil@openpgp.org' }]
529
- * @returns {Promise<Message>} the encrypted session key packets contained in a message object
530
- * @async
531
- * @static
532
- */
533
- export function encryptSessionKey({ data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard = false, date = new Date(), toUserIds = [] }) {
534
- checkBinary(data); checkString(algorithm, 'algorithm'); publicKeys = toArray(publicKeys); passwords = toArray(passwords); toUserIds = toArray(toUserIds);
535
-
536
- if (asyncProxy) { // use web worker if available
537
- return asyncProxy.delegate('encryptSessionKey', { data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds });
538
- }
539
-
540
- return Promise.resolve().then(async function() {
541
-
542
- return { message: await messageLib.encryptSessionKey(data, algorithm, aeadAlgorithm, publicKeys, passwords, wildcard, date, toUserIds) };
543
-
544
- }).catch(onError.bind(null, 'Error encrypting session key'));
545
- }
546
-
547
- /**
548
- * Decrypt symmetric session keys with a private key or password. Either a private key or
549
- * a password must be specified.
550
- * @param {Message} message a message object containing the encrypted session key packets
551
- * @param {Key|Array<Key>} privateKeys (optional) private keys with decrypted secret key data
552
- * @param {String|Array<String>} passwords (optional) passwords to decrypt the session key
553
- * @returns {Promise<Object|undefined>} Array of decrypted session key, algorithm pairs in form:
554
- * { data:Uint8Array, algorithm:String }
555
- * or 'undefined' if no key packets found
556
- * @async
557
- * @static
558
- */
559
- export function decryptSessionKeys({ message, privateKeys, passwords }) {
560
- checkMessage(message); privateKeys = toArray(privateKeys); passwords = toArray(passwords);
561
-
562
- if (asyncProxy) { // use web worker if available
563
- return asyncProxy.delegate('decryptSessionKeys', { message, privateKeys, passwords });
564
- }
565
-
566
- return Promise.resolve().then(async function() {
567
-
568
- return message.decryptSessionKeys(privateKeys, passwords);
569
-
570
- }).catch(onError.bind(null, 'Error decrypting session keys'));
571
- }
572
-
573
-
574
- //////////////////////////
575
- // //
576
- // Helper functions //
577
- // //
578
- //////////////////////////
579
-
580
-
581
- /**
582
- * Input validation
583
- */
584
- function checkString(data, name) {
585
- if (!util.isString(data)) {
586
- throw new Error('Parameter [' + (name || 'data') + '] must be of type String');
587
- }
588
- }
589
- function checkBinary(data, name) {
590
- if (!util.isUint8Array(data)) {
591
- throw new Error('Parameter [' + (name || 'data') + '] must be of type Uint8Array');
592
- }
593
- }
594
- function checkMessage(message) {
595
- if (!(message instanceof messageLib.Message)) {
596
- throw new Error('Parameter [message] needs to be of type Message');
597
- }
598
- }
599
- function checkCleartextOrMessage(message) {
600
- if (!(message instanceof CleartextMessage) && !(message instanceof messageLib.Message)) {
601
- throw new Error('Parameter [message] needs to be of type Message or CleartextMessage');
602
- }
603
- }
604
-
605
- /**
606
- * Normalize parameter to an array if it is not undefined.
607
- * @param {Object} param the parameter to be normalized
608
- * @returns {Array<Object>|undefined} the resulting array or undefined
609
- */
610
- function toArray(param) {
611
- if (param && !util.isArray(param)) {
612
- param = [param];
613
- }
614
- return param;
615
- }
616
-
617
- /**
618
- * Convert data to or from Stream
619
- * @param {Object} data the data to convert
620
- * @param {'web'|'node'|false} streaming (optional) whether to return a ReadableStream
621
- * @returns {Object} the data in the respective format
622
- */
623
- async function convertStream(data, streaming) {
624
- if (!streaming && util.isStream(data)) {
625
- return stream.readToEnd(data);
626
- }
627
- if (streaming && !util.isStream(data)) {
628
- data = new ReadableStream({
629
- start(controller) {
630
- controller.enqueue(data);
631
- controller.close();
632
- }
633
- });
634
- }
635
- if (streaming === 'node') {
636
- data = stream.webToNode(data);
637
- }
638
- return data;
639
- }
640
-
641
- /**
642
- * Convert object properties from Stream
643
- * @param {Object} obj the data to convert
644
- * @param {'web'|'node'|false} streaming (optional) whether to return ReadableStreams
645
- * @param {Array<String>} keys (optional) which keys to return as streams, if possible
646
- * @returns {Object} the data in the respective format
647
- */
648
- async function convertStreams(obj, streaming, keys = []) {
649
- if (Object.prototype.isPrototypeOf(obj) && !Uint8Array.prototype.isPrototypeOf(obj)) {
650
- await Promise.all(Object.entries(obj).map(async ([key, value]) => { // recursively search all children
651
- if (util.isStream(value) || keys.includes(key)) {
652
- obj[key] = await convertStream(value, streaming);
653
- } else {
654
- await convertStreams(obj[key], streaming);
655
- }
656
- }));
657
- }
658
- return obj;
659
- }
660
-
661
- /**
662
- * Link result.data to the message stream for cancellation.
663
- * @param {Object} result the data to convert
664
- * @param {Message} message message object
665
- * @returns {Object}
666
- */
667
- function linkStreams(result, message) {
668
- result.data = stream.transformPair(message.packets.stream, async (readable, writable) => {
669
- await stream.pipe(result.data, writable);
670
- });
671
- }
672
-
673
- /**
674
- * Wait until signature objects have been verified
675
- * @param {Object} signatures list of signatures
676
- */
677
- async function prepareSignatures(signatures) {
678
- await Promise.all(signatures.map(async signature => {
679
- signature.signature = await signature.signature;
680
- try {
681
- signature.valid = await signature.verified;
682
- } catch (e) {
683
- signature.valid = false;
684
- signature.error = e;
685
- util.print_debug_error(e);
686
- }
687
- }));
688
- }
689
-
690
-
691
- /**
692
- * Global error handler that logs the stack trace and rethrows a high lvl error message.
693
- * @param {String} message A human readable high level error Message
694
- * @param {Error} error The internal error that caused the failure
695
- */
696
- function onError(message, error) {
697
- // log the stack trace
698
- util.print_debug_error(error);
699
-
700
- // update error message
701
- try {
702
- error.message = message + ': ' + error.message;
703
- } catch (e) {}
704
-
705
- throw error;
706
- }
707
-
708
- /**
709
- * Check for native AEAD support and configuration by the user. Only
710
- * browsers that implement the current WebCrypto specification support
711
- * native GCM. Native EAX is built on CTR and CBC, which current
712
- * browsers support. OCB and CFB are not natively supported.
713
- * @returns {Boolean} If authenticated encryption should be used
714
- */
715
- function nativeAEAD() {
716
- return config.aead_protect && (config.aead_mode === enums.aead.eax || config.aead_mode === enums.aead.experimental_gcm) && util.getWebCrypto();
717
- }