@protontech/openpgp 6.0.0-beta.3.patch.0 → 6.0.0
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 +34 -37
- package/dist/lightweight/argon2id.min.mjs +1 -1
- package/dist/lightweight/argon2id.min.mjs.map +1 -1
- package/dist/lightweight/argon2id.mjs +1 -1
- package/dist/lightweight/legacy_ciphers.min.mjs +1 -1
- package/dist/lightweight/legacy_ciphers.min.mjs.map +1 -1
- package/dist/lightweight/legacy_ciphers.mjs +1 -1
- package/dist/lightweight/noble_curves.min.mjs +1 -1
- package/dist/lightweight/noble_curves.min.mjs.map +1 -1
- package/dist/lightweight/noble_curves.mjs +1 -1
- package/dist/lightweight/noble_hashes.min.mjs +1 -1
- package/dist/lightweight/noble_hashes.min.mjs.map +1 -1
- package/dist/lightweight/noble_hashes.mjs +1 -1
- package/dist/lightweight/openpgp.min.mjs +4 -4
- package/dist/lightweight/openpgp.min.mjs.map +1 -1
- package/dist/lightweight/openpgp.mjs +276 -1048
- package/dist/lightweight/seek-bzip.min.mjs +3 -0
- package/dist/lightweight/seek-bzip.min.mjs.map +1 -0
- package/dist/lightweight/seek-bzip.mjs +866 -0
- package/dist/lightweight/sha3.min.mjs +1 -1
- package/dist/lightweight/sha3.min.mjs.map +1 -1
- package/dist/lightweight/sha3.mjs +1 -1
- package/dist/node/openpgp.cjs +2801 -2711
- package/dist/node/openpgp.min.cjs +14 -14
- package/dist/node/openpgp.min.cjs.map +1 -1
- package/dist/node/openpgp.min.mjs +14 -14
- package/dist/node/openpgp.min.mjs.map +1 -1
- package/dist/node/openpgp.mjs +11372 -11282
- package/dist/openpgp.js +12424 -12334
- package/dist/openpgp.min.js +14 -14
- package/dist/openpgp.min.js.map +1 -1
- package/dist/openpgp.min.mjs +14 -14
- package/dist/openpgp.min.mjs.map +1 -1
- package/dist/openpgp.mjs +12424 -12334
- package/package.json +24 -24
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! OpenPGP.js v6.0.0
|
|
1
|
+
/*! OpenPGP.js v6.0.0 - 2024-11-06 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
|
|
2
2
|
const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
3
3
|
|
|
4
4
|
const doneWritingPromise = Symbol('doneWritingPromise');
|
|
@@ -1455,7 +1455,7 @@ var config = {
|
|
|
1455
1455
|
* @memberof module:config
|
|
1456
1456
|
* @property {Integer} preferredHashAlgorithm Default hash algorithm {@link module:enums.hash}
|
|
1457
1457
|
*/
|
|
1458
|
-
preferredHashAlgorithm: enums.hash.
|
|
1458
|
+
preferredHashAlgorithm: enums.hash.sha512,
|
|
1459
1459
|
/**
|
|
1460
1460
|
* @memberof module:config
|
|
1461
1461
|
* @property {Integer} preferredSymmetricAlgorithm Default encryption cipher {@link module:enums.symmetric}
|
|
@@ -1682,7 +1682,7 @@ var config = {
|
|
|
1682
1682
|
* @memberof module:config
|
|
1683
1683
|
* @property {String} versionString A version string to be included in armored messages
|
|
1684
1684
|
*/
|
|
1685
|
-
versionString: 'OpenPGP.js 6.0.0
|
|
1685
|
+
versionString: 'OpenPGP.js 6.0.0',
|
|
1686
1686
|
/**
|
|
1687
1687
|
* @memberof module:config
|
|
1688
1688
|
* @property {String} commentString A comment string to be included in armored messages
|
|
@@ -1883,6 +1883,9 @@ const util = {
|
|
|
1883
1883
|
* @returns {Uint8Array} Padded bytes.
|
|
1884
1884
|
*/
|
|
1885
1885
|
leftPad(bytes, length) {
|
|
1886
|
+
if (bytes.length > length) {
|
|
1887
|
+
throw new Error('Input array too long');
|
|
1888
|
+
}
|
|
1886
1889
|
const padded = new Uint8Array(length);
|
|
1887
1890
|
const offset = length - bytes.length;
|
|
1888
1891
|
padded.set(bytes, offset);
|
|
@@ -2458,7 +2461,7 @@ function encode$1(data) {
|
|
|
2458
2461
|
* @returns {Uint8Array | ReadableStream<Uint8Array>} Binary array version of input string.
|
|
2459
2462
|
* @static
|
|
2460
2463
|
*/
|
|
2461
|
-
function decode$
|
|
2464
|
+
function decode$1(data) {
|
|
2462
2465
|
let buf = '';
|
|
2463
2466
|
return transform(data, value => {
|
|
2464
2467
|
buf += value;
|
|
@@ -2494,7 +2497,7 @@ function decode$2(data) {
|
|
|
2494
2497
|
* @returns {Uint8Array} An array of 8-bit integers.
|
|
2495
2498
|
*/
|
|
2496
2499
|
function b64ToUint8Array(base64) {
|
|
2497
|
-
return decode$
|
|
2500
|
+
return decode$1(base64.replace(/-/g, '+').replace(/_/g, '/'));
|
|
2498
2501
|
}
|
|
2499
2502
|
|
|
2500
2503
|
/**
|
|
@@ -2747,7 +2750,7 @@ function unarmor(input) {
|
|
|
2747
2750
|
let headersDone;
|
|
2748
2751
|
let text = [];
|
|
2749
2752
|
let textDone;
|
|
2750
|
-
const data = decode$
|
|
2753
|
+
const data = decode$1(transformPair(input, async (readable, writable) => {
|
|
2751
2754
|
const reader = getReader(readable);
|
|
2752
2755
|
try {
|
|
2753
2756
|
while (true) {
|
|
@@ -4004,14 +4007,14 @@ function validatePCKS(data, pcks5) {
|
|
|
4004
4007
|
return data;
|
|
4005
4008
|
const len = data.length;
|
|
4006
4009
|
if (!len)
|
|
4007
|
-
throw new Error(
|
|
4010
|
+
throw new Error('aes/pcks5: empty ciphertext not allowed');
|
|
4008
4011
|
const lastByte = data[len - 1];
|
|
4009
4012
|
if (lastByte <= 0 || lastByte > 16)
|
|
4010
|
-
throw new Error(
|
|
4013
|
+
throw new Error('aes/pcks5: wrong padding');
|
|
4011
4014
|
const out = data.subarray(0, -lastByte);
|
|
4012
4015
|
for (let i = 0; i < lastByte; i++)
|
|
4013
4016
|
if (data[len - i - 1] !== lastByte)
|
|
4014
|
-
throw new Error(
|
|
4017
|
+
throw new Error('aes/pcks5: wrong padding');
|
|
4015
4018
|
return out;
|
|
4016
4019
|
}
|
|
4017
4020
|
function padPCKS(left) {
|
|
@@ -4152,17 +4155,21 @@ function computeTag(fn, isLE, key, data, AAD) {
|
|
|
4152
4155
|
}
|
|
4153
4156
|
/**
|
|
4154
4157
|
* GCM: Galois/Counter Mode.
|
|
4155
|
-
*
|
|
4158
|
+
* Modern, parallel version of CTR, with MAC.
|
|
4156
4159
|
* Be careful: MACs can be forged.
|
|
4160
|
+
* Unsafe to use random nonces under the same key, due to collision chance.
|
|
4161
|
+
* As for nonce size, prefer 12-byte, instead of 8-byte.
|
|
4157
4162
|
*/
|
|
4158
4163
|
const gcm = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, function gcm(key, nonce, AAD) {
|
|
4159
4164
|
bytes(key);
|
|
4160
4165
|
bytes(nonce);
|
|
4161
4166
|
if (AAD !== undefined)
|
|
4162
4167
|
bytes(AAD);
|
|
4163
|
-
//
|
|
4164
|
-
|
|
4165
|
-
|
|
4168
|
+
// NIST 800-38d doesn't enforce minimum nonce length.
|
|
4169
|
+
// We enforce 8 bytes for compat with openssl.
|
|
4170
|
+
// 12 bytes are recommended. More than 12 bytes would be converted into 12.
|
|
4171
|
+
if (nonce.length < 8)
|
|
4172
|
+
throw new Error('aes/gcm: invalid nonce length');
|
|
4166
4173
|
const tagLength = 16;
|
|
4167
4174
|
function _computeTag(authKey, tagMask, data) {
|
|
4168
4175
|
const tag = computeTag(ghash, false, authKey, data, AAD);
|
|
@@ -4175,12 +4182,11 @@ const gcm = wrapCipher({ blockSize: 16, nonceLength: 12, tagLength: 16 }, functi
|
|
|
4175
4182
|
const authKey = EMPTY_BLOCK.slice();
|
|
4176
4183
|
const counter = EMPTY_BLOCK.slice();
|
|
4177
4184
|
ctr32(xk, false, counter, counter, authKey);
|
|
4185
|
+
// NIST 800-38d, page 15: different behavior for 96-bit and non-96-bit nonces
|
|
4178
4186
|
if (nonce.length === 12) {
|
|
4179
4187
|
counter.set(nonce);
|
|
4180
4188
|
}
|
|
4181
4189
|
else {
|
|
4182
|
-
// Spec (NIST 800-38d) supports variable size nonce.
|
|
4183
|
-
// Not supported for now, but can be useful.
|
|
4184
4190
|
const nonceLen = EMPTY_BLOCK.slice();
|
|
4185
4191
|
const view = createView(nonceLen);
|
|
4186
4192
|
setBigUint64(view, 8, BigInt(nonce.length * 8), false);
|
|
@@ -4331,7 +4337,7 @@ const aeskw = wrapCipher({ blockSize: 8 }, (kek) => ({
|
|
|
4331
4337
|
encrypt(plaintext) {
|
|
4332
4338
|
bytes(plaintext);
|
|
4333
4339
|
if (!plaintext.length || plaintext.length % 8 !== 0)
|
|
4334
|
-
throw new Error('plaintext length
|
|
4340
|
+
throw new Error('invalid plaintext length');
|
|
4335
4341
|
if (plaintext.length === 8)
|
|
4336
4342
|
throw new Error('8-byte keys not allowed in AESKW, use AESKWP instead');
|
|
4337
4343
|
const out = concatBytes$1(AESKW_IV, plaintext);
|
|
@@ -4340,10 +4346,11 @@ const aeskw = wrapCipher({ blockSize: 8 }, (kek) => ({
|
|
|
4340
4346
|
},
|
|
4341
4347
|
decrypt(ciphertext) {
|
|
4342
4348
|
bytes(ciphertext);
|
|
4349
|
+
// ciphertext must be at least 24 bytes and a multiple of 8 bytes
|
|
4343
4350
|
// 24 because should have at least two block (1 iv + 2).
|
|
4344
4351
|
// Replace with 16 to enable '8-byte keys'
|
|
4345
4352
|
if (ciphertext.length % 8 !== 0 || ciphertext.length < 3 * 8)
|
|
4346
|
-
throw new Error('ciphertext
|
|
4353
|
+
throw new Error('invalid ciphertext length');
|
|
4347
4354
|
const out = copyBytes(ciphertext);
|
|
4348
4355
|
AESW.decrypt(kek, out);
|
|
4349
4356
|
if (!equalBytes$1(out.subarray(0, 8), AESKW_IV))
|
|
@@ -5617,16 +5624,13 @@ const nodeCrypto$6 = util.getNodeCrypto();
|
|
|
5617
5624
|
* @returns {Uint8Array} Random byte array.
|
|
5618
5625
|
*/
|
|
5619
5626
|
function getRandomBytes(length) {
|
|
5620
|
-
const
|
|
5621
|
-
if (
|
|
5622
|
-
const
|
|
5623
|
-
|
|
5624
|
-
} else if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
|
|
5625
|
-
crypto.getRandomValues(buf);
|
|
5627
|
+
const webcrypto = typeof crypto !== 'undefined' ? crypto : nodeCrypto$6?.webcrypto;
|
|
5628
|
+
if (webcrypto?.getRandomValues) {
|
|
5629
|
+
const buf = new Uint8Array(length);
|
|
5630
|
+
return webcrypto.getRandomValues(buf);
|
|
5626
5631
|
} else {
|
|
5627
5632
|
throw new Error('No secure random number generator available.');
|
|
5628
5633
|
}
|
|
5629
|
-
return buf;
|
|
5630
5634
|
}
|
|
5631
5635
|
|
|
5632
5636
|
/**
|
|
@@ -6092,6 +6096,14 @@ const _1n$3 = BigInt(1);
|
|
|
6092
6096
|
* @async
|
|
6093
6097
|
*/
|
|
6094
6098
|
async function sign$7(hashAlgo, data, n, e, d, p, q, u, hashed) {
|
|
6099
|
+
if (hash.getHashByteLength(hashAlgo) >= n.length) {
|
|
6100
|
+
// Throw here instead of `emsaEncode` below, to provide a clearer and consistent error
|
|
6101
|
+
// e.g. if a 512-bit RSA key is used with a SHA-512 digest.
|
|
6102
|
+
// The size limit is actually slightly different but here we only care about throwing
|
|
6103
|
+
// on common key sizes.
|
|
6104
|
+
throw new Error('Digest size cannot exceed key modulus size');
|
|
6105
|
+
}
|
|
6106
|
+
|
|
6095
6107
|
if (data && !util.isStream(data)) {
|
|
6096
6108
|
if (util.getWebCrypto()) {
|
|
6097
6109
|
try {
|
|
@@ -6311,9 +6323,6 @@ async function bnSign(hashAlgo, n, d, hashed) {
|
|
|
6311
6323
|
n = uint8ArrayToBigInt(n);
|
|
6312
6324
|
const m = uint8ArrayToBigInt(emsaEncode(hashAlgo, hashed, byteLength(n)));
|
|
6313
6325
|
d = uint8ArrayToBigInt(d);
|
|
6314
|
-
if (m >= n) {
|
|
6315
|
-
throw new Error('Message size cannot exceed modulus size');
|
|
6316
|
-
}
|
|
6317
6326
|
return bigIntToUint8Array(modExp(m, d, n), 'be', byteLength(n));
|
|
6318
6327
|
}
|
|
6319
6328
|
|
|
@@ -9280,13 +9289,16 @@ async function generate$4(algo) {
|
|
|
9280
9289
|
*/
|
|
9281
9290
|
async function sign$6(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
9282
9291
|
if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
9292
|
+
// Enforce digest sizes:
|
|
9293
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
9294
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
9283
9295
|
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
9284
9296
|
}
|
|
9285
9297
|
switch (algo) {
|
|
9286
9298
|
case enums.publicKey.ed25519:
|
|
9287
9299
|
try {
|
|
9288
9300
|
const webCrypto = util.getWebCrypto();
|
|
9289
|
-
const jwk = privateKeyToJWK
|
|
9301
|
+
const jwk = privateKeyToJWK(algo, publicKey, privateKey);
|
|
9290
9302
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['sign']);
|
|
9291
9303
|
|
|
9292
9304
|
const signature = new Uint8Array(
|
|
@@ -9327,13 +9339,16 @@ async function sign$6(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9327
9339
|
*/
|
|
9328
9340
|
async function verify$6(algo, hashAlgo, { RS }, m, publicKey, hashed) {
|
|
9329
9341
|
if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
9342
|
+
// Enforce digest sizes:
|
|
9343
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
9344
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
9330
9345
|
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
9331
9346
|
}
|
|
9332
9347
|
switch (algo) {
|
|
9333
9348
|
case enums.publicKey.ed25519:
|
|
9334
9349
|
try {
|
|
9335
9350
|
const webCrypto = util.getWebCrypto();
|
|
9336
|
-
const jwk = publicKeyToJWK
|
|
9351
|
+
const jwk = publicKeyToJWK(algo, publicKey);
|
|
9337
9352
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['verify']);
|
|
9338
9353
|
const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
|
|
9339
9354
|
return verified;
|
|
@@ -9408,7 +9423,7 @@ function getPreferredHashAlgo$2(algo) {
|
|
|
9408
9423
|
}
|
|
9409
9424
|
}
|
|
9410
9425
|
|
|
9411
|
-
const publicKeyToJWK
|
|
9426
|
+
const publicKeyToJWK = (algo, publicKey) => {
|
|
9412
9427
|
switch (algo) {
|
|
9413
9428
|
case enums.publicKey.ed25519: {
|
|
9414
9429
|
const jwk = {
|
|
@@ -9424,10 +9439,10 @@ const publicKeyToJWK$1 = (algo, publicKey) => {
|
|
|
9424
9439
|
}
|
|
9425
9440
|
};
|
|
9426
9441
|
|
|
9427
|
-
const privateKeyToJWK
|
|
9442
|
+
const privateKeyToJWK = (algo, publicKey, privateKey) => {
|
|
9428
9443
|
switch (algo) {
|
|
9429
9444
|
case enums.publicKey.ed25519: {
|
|
9430
|
-
const jwk = publicKeyToJWK
|
|
9445
|
+
const jwk = publicKeyToJWK(algo, publicKey);
|
|
9431
9446
|
jwk.d = uint8ArrayToB64(privateKey);
|
|
9432
9447
|
return jwk;
|
|
9433
9448
|
}
|
|
@@ -9576,27 +9591,12 @@ const HKDF_INFO = {
|
|
|
9576
9591
|
*/
|
|
9577
9592
|
async function generate$3(algo) {
|
|
9578
9593
|
switch (algo) {
|
|
9579
|
-
case enums.publicKey.x25519:
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
9586
|
-
|
|
9587
|
-
return {
|
|
9588
|
-
A: new Uint8Array(b64ToUint8Array(publicKey.x)),
|
|
9589
|
-
k: b64ToUint8Array(privateKey.d, true)
|
|
9590
|
-
};
|
|
9591
|
-
} catch (err) {
|
|
9592
|
-
if (err.name !== 'NotSupportedError') {
|
|
9593
|
-
throw err;
|
|
9594
|
-
}
|
|
9595
|
-
// k stays in little-endian, unlike legacy ECDH over curve25519
|
|
9596
|
-
const k = getRandomBytes(32);
|
|
9597
|
-
const { publicKey: A } = nacl.box.keyPair.fromSecretKey(k);
|
|
9598
|
-
return { A, k };
|
|
9599
|
-
}
|
|
9594
|
+
case enums.publicKey.x25519: {
|
|
9595
|
+
// k stays in little-endian, unlike legacy ECDH over curve25519
|
|
9596
|
+
const k = getRandomBytes(32);
|
|
9597
|
+
const { publicKey: A } = nacl.box.keyPair.fromSecretKey(k);
|
|
9598
|
+
return { A, k };
|
|
9599
|
+
}
|
|
9600
9600
|
|
|
9601
9601
|
case enums.publicKey.x448: {
|
|
9602
9602
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
@@ -9738,36 +9738,18 @@ function getPayloadSize(algo) {
|
|
|
9738
9738
|
*/
|
|
9739
9739
|
async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
9740
9740
|
switch (algo) {
|
|
9741
|
-
case enums.publicKey.x25519:
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
9745
|
-
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
{ name: 'X25519', public: recipientPublicKey },
|
|
9749
|
-
ephemeralKeyPair.privateKey,
|
|
9750
|
-
getPayloadSize(algo) * 8 // in bits
|
|
9751
|
-
);
|
|
9752
|
-
const ephemeralPublicKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.publicKey);
|
|
9753
|
-
return {
|
|
9754
|
-
sharedSecret: new Uint8Array(sharedSecretBuffer),
|
|
9755
|
-
ephemeralPublicKey: new Uint8Array(b64ToUint8Array(ephemeralPublicKeyJwt.x))
|
|
9756
|
-
};
|
|
9757
|
-
} catch (err) {
|
|
9758
|
-
if (err.name !== 'NotSupportedError') {
|
|
9759
|
-
throw err;
|
|
9760
|
-
}
|
|
9761
|
-
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
|
|
9762
|
-
const sharedSecret = nacl.scalarMult(ephemeralSecretKey, recipientA);
|
|
9763
|
-
const { publicKey: ephemeralPublicKey } = nacl.box.keyPair.fromSecretKey(ephemeralSecretKey);
|
|
9764
|
-
|
|
9765
|
-
return { ephemeralPublicKey, sharedSecret };
|
|
9766
|
-
}
|
|
9741
|
+
case enums.publicKey.x25519: {
|
|
9742
|
+
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
|
|
9743
|
+
const sharedSecret = nacl.scalarMult(ephemeralSecretKey, recipientA);
|
|
9744
|
+
assertNonZeroArray(sharedSecret);
|
|
9745
|
+
const { publicKey: ephemeralPublicKey } = nacl.box.keyPair.fromSecretKey(ephemeralSecretKey);
|
|
9746
|
+
return { ephemeralPublicKey, sharedSecret };
|
|
9747
|
+
}
|
|
9767
9748
|
case enums.publicKey.x448: {
|
|
9768
9749
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
9769
9750
|
const ephemeralSecretKey = x448.utils.randomPrivateKey();
|
|
9770
9751
|
const sharedSecret = x448.getSharedSecret(ephemeralSecretKey, recipientA);
|
|
9752
|
+
assertNonZeroArray(sharedSecret);
|
|
9771
9753
|
const ephemeralPublicKey = x448.getPublicKey(ephemeralSecretKey);
|
|
9772
9754
|
return { ephemeralPublicKey, sharedSecret };
|
|
9773
9755
|
}
|
|
@@ -9778,28 +9760,15 @@ async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
|
9778
9760
|
|
|
9779
9761
|
async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
|
|
9780
9762
|
switch (algo) {
|
|
9781
|
-
case enums.publicKey.x25519:
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
const privateKey = await webCrypto.importKey('jwk', privateKeyJWK, 'X25519', false, ['deriveKey', 'deriveBits']);
|
|
9787
|
-
const ephemeralPublicKeyReference = await webCrypto.importKey('jwk', ephemeralPublicKeyJWK, 'X25519', false, []);
|
|
9788
|
-
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
9789
|
-
{ name: 'X25519', public: ephemeralPublicKeyReference },
|
|
9790
|
-
privateKey,
|
|
9791
|
-
getPayloadSize(algo) * 8 // in bits
|
|
9792
|
-
);
|
|
9793
|
-
return new Uint8Array(sharedSecretBuffer);
|
|
9794
|
-
} catch (err) {
|
|
9795
|
-
if (err.name !== 'NotSupportedError') {
|
|
9796
|
-
throw err;
|
|
9797
|
-
}
|
|
9798
|
-
return nacl.scalarMult(k, ephemeralPublicKey);
|
|
9799
|
-
}
|
|
9763
|
+
case enums.publicKey.x25519: {
|
|
9764
|
+
const sharedSecret = nacl.scalarMult(k, ephemeralPublicKey);
|
|
9765
|
+
assertNonZeroArray(sharedSecret);
|
|
9766
|
+
return sharedSecret;
|
|
9767
|
+
}
|
|
9800
9768
|
case enums.publicKey.x448: {
|
|
9801
9769
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
9802
9770
|
const sharedSecret = x448.getSharedSecret(k, ephemeralPublicKey);
|
|
9771
|
+
assertNonZeroArray(sharedSecret);
|
|
9803
9772
|
return sharedSecret;
|
|
9804
9773
|
}
|
|
9805
9774
|
default:
|
|
@@ -9807,32 +9776,19 @@ async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
|
|
|
9807
9776
|
}
|
|
9808
9777
|
}
|
|
9809
9778
|
|
|
9810
|
-
|
|
9811
|
-
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
return jwk;
|
|
9821
|
-
}
|
|
9822
|
-
default:
|
|
9823
|
-
throw new Error('Unsupported ECDH algorithm');
|
|
9779
|
+
/**
|
|
9780
|
+
* x25519 and x448 produce an all-zero value when given as input a point with small order.
|
|
9781
|
+
* This does not lead to a security issue in the context of ECDH, but it is still unexpected,
|
|
9782
|
+
* hence we throw.
|
|
9783
|
+
* @param {Uint8Array} sharedSecret
|
|
9784
|
+
*/
|
|
9785
|
+
function assertNonZeroArray(sharedSecret) {
|
|
9786
|
+
let acc = 0;
|
|
9787
|
+
for (let i = 0; i < sharedSecret.length; i++) {
|
|
9788
|
+
acc |= sharedSecret[i];
|
|
9824
9789
|
}
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
function privateKeyToJWK(algo, publicKey, privateKey) {
|
|
9828
|
-
switch (algo) {
|
|
9829
|
-
case enums.publicKey.x25519: {
|
|
9830
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
9831
|
-
jwk.d = uint8ArrayToB64(privateKey);
|
|
9832
|
-
return jwk;
|
|
9833
|
-
}
|
|
9834
|
-
default:
|
|
9835
|
-
throw new Error('Unsupported ECDH algorithm');
|
|
9790
|
+
if (acc === 0) {
|
|
9791
|
+
throw new Error('Unexpected low order point');
|
|
9836
9792
|
}
|
|
9837
9793
|
}
|
|
9838
9794
|
|
|
@@ -10544,7 +10500,9 @@ async function sign$4(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
10544
10500
|
const curve = new CurveWithOID(oid);
|
|
10545
10501
|
checkPublicPointEnconding(curve, publicKey);
|
|
10546
10502
|
if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) {
|
|
10503
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
10547
10504
|
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
10505
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
10548
10506
|
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
10549
10507
|
}
|
|
10550
10508
|
const { RS: signature } = await sign$6(enums.publicKey.ed25519, hashAlgo, message, publicKey.subarray(1), privateKey, hashed);
|
|
@@ -10571,6 +10529,9 @@ async function verify$4(oid, hashAlgo, { r, s }, m, publicKey, hashed) {
|
|
|
10571
10529
|
const curve = new CurveWithOID(oid);
|
|
10572
10530
|
checkPublicPointEnconding(curve, publicKey);
|
|
10573
10531
|
if (hash.getHashByteLength(hashAlgo) < hash.getHashByteLength(enums.hash.sha256)) {
|
|
10532
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
10533
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
10534
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
10574
10535
|
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
10575
10536
|
}
|
|
10576
10537
|
const RS = util.concatUint8Array([r, s]);
|
|
@@ -10649,7 +10610,7 @@ function encode(message) {
|
|
|
10649
10610
|
* @param {Uint8Array} message - message to remove padding from
|
|
10650
10611
|
* @returns {Uint8Array} Message without padding.
|
|
10651
10612
|
*/
|
|
10652
|
-
function decode
|
|
10613
|
+
function decode(message) {
|
|
10653
10614
|
const len = message.length;
|
|
10654
10615
|
if (len > 0) {
|
|
10655
10616
|
const c = message[len - 1];
|
|
@@ -10666,7 +10627,7 @@ function decode$1(message) {
|
|
|
10666
10627
|
|
|
10667
10628
|
var pkcs5 = /*#__PURE__*/Object.freeze({
|
|
10668
10629
|
__proto__: null,
|
|
10669
|
-
decode: decode
|
|
10630
|
+
decode: decode,
|
|
10670
10631
|
encode: encode
|
|
10671
10632
|
});
|
|
10672
10633
|
|
|
@@ -10859,7 +10820,7 @@ async function decrypt$1(oid, kdfParams, V, C, Q, d, fingerprint) {
|
|
|
10859
10820
|
try {
|
|
10860
10821
|
// Work around old go crypto bug and old OpenPGP.js bug, respectively.
|
|
10861
10822
|
const Z = await kdf(kdfParams.hash, sharedKey, keySize, param, i === 1, i === 2);
|
|
10862
|
-
return decode
|
|
10823
|
+
return decode(await unwrap(kdfParams.cipher, Z, C));
|
|
10863
10824
|
} catch (e) {
|
|
10864
10825
|
err = e;
|
|
10865
10826
|
}
|
|
@@ -11406,6 +11367,8 @@ function parseSignatureParams(algo, signature) {
|
|
|
11406
11367
|
case enums.publicKey.dsa:
|
|
11407
11368
|
case enums.publicKey.ecdsa:
|
|
11408
11369
|
{
|
|
11370
|
+
// If the signature payload sizes are unexpected, we will throw on verification,
|
|
11371
|
+
// where we also have access to the OID curve from the key.
|
|
11409
11372
|
const r = util.readMPI(signature.subarray(read)); read += r.length + 2;
|
|
11410
11373
|
const s = util.readMPI(signature.subarray(read)); read += s.length + 2;
|
|
11411
11374
|
return { read, signatureParams: { r, s } };
|
|
@@ -11414,12 +11377,11 @@ function parseSignatureParams(algo, signature) {
|
|
|
11414
11377
|
// - MPI of an EC point r.
|
|
11415
11378
|
// - EdDSA value s, in MPI, in the little endian representation
|
|
11416
11379
|
case enums.publicKey.eddsaLegacy: {
|
|
11417
|
-
//
|
|
11418
|
-
//
|
|
11419
|
-
|
|
11420
|
-
r = util.
|
|
11421
|
-
|
|
11422
|
-
s = util.leftPad(s, 32);
|
|
11380
|
+
// Only Curve25519Legacy is supported (no Curve448Legacy), but the relevant checks are done on key parsing and signature
|
|
11381
|
+
// verification: if the signature payload sizes are unexpected, we will throw on verification,
|
|
11382
|
+
// where we also have access to the OID curve from the key.
|
|
11383
|
+
const r = util.readMPI(signature.subarray(read)); read += r.length + 2;
|
|
11384
|
+
const s = util.readMPI(signature.subarray(read)); read += s.length + 2;
|
|
11423
11385
|
return { read, signatureParams: { r, s } };
|
|
11424
11386
|
}
|
|
11425
11387
|
// Algorithm-Specific Fields for Ed25519 signatures:
|
|
@@ -11480,8 +11442,12 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
11480
11442
|
}
|
|
11481
11443
|
case enums.publicKey.eddsaLegacy: {
|
|
11482
11444
|
const { oid, Q } = publicParams;
|
|
11483
|
-
|
|
11484
|
-
|
|
11445
|
+
const curveSize = new publicKey.elliptic.CurveWithOID(oid).payloadSize;
|
|
11446
|
+
// When dealing little-endian MPI data, we always need to left-pad it, as done with big-endian values:
|
|
11447
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-rfc4880bis-10.html#section-3.2-9
|
|
11448
|
+
const r = util.leftPad(signature.r, curveSize);
|
|
11449
|
+
const s = util.leftPad(signature.s, curveSize);
|
|
11450
|
+
return publicKey.elliptic.eddsaLegacy.verify(oid, hashAlgo, { r, s }, data, Q, hashed);
|
|
11485
11451
|
}
|
|
11486
11452
|
case enums.publicKey.ed25519:
|
|
11487
11453
|
case enums.publicKey.ed448: {
|
|
@@ -12536,13 +12502,25 @@ class Argon2S2K {
|
|
|
12536
12502
|
const { passes, parallelism, memoryExponent } = config$1.s2kArgon2Params;
|
|
12537
12503
|
|
|
12538
12504
|
this.type = 'argon2';
|
|
12539
|
-
/**
|
|
12505
|
+
/**
|
|
12506
|
+
* 16 bytes of salt
|
|
12507
|
+
* @type {Uint8Array}
|
|
12508
|
+
*/
|
|
12540
12509
|
this.salt = null;
|
|
12541
|
-
/**
|
|
12510
|
+
/**
|
|
12511
|
+
* number of passes
|
|
12512
|
+
* @type {Integer}
|
|
12513
|
+
*/
|
|
12542
12514
|
this.t = passes;
|
|
12543
|
-
/**
|
|
12515
|
+
/**
|
|
12516
|
+
* degree of parallelism (lanes)
|
|
12517
|
+
* @type {Integer}
|
|
12518
|
+
*/
|
|
12544
12519
|
this.p = parallelism;
|
|
12545
|
-
/**
|
|
12520
|
+
/**
|
|
12521
|
+
* exponent indicating memory size
|
|
12522
|
+
* @type {Integer}
|
|
12523
|
+
*/
|
|
12546
12524
|
this.encodedM = memoryExponent;
|
|
12547
12525
|
}
|
|
12548
12526
|
|
|
@@ -13734,849 +13712,6 @@ try {
|
|
|
13734
13712
|
}
|
|
13735
13713
|
catch (e) { }
|
|
13736
13714
|
|
|
13737
|
-
/*
|
|
13738
|
-
node-bzip - a pure-javascript Node.JS module for decoding bzip2 data
|
|
13739
|
-
|
|
13740
|
-
Copyright (C) 2012 Eli Skeggs
|
|
13741
|
-
|
|
13742
|
-
This library is free software; you can redistribute it and/or
|
|
13743
|
-
modify it under the terms of the GNU Lesser General Public
|
|
13744
|
-
License as published by the Free Software Foundation; either
|
|
13745
|
-
version 2.1 of the License, or (at your option) any later version.
|
|
13746
|
-
|
|
13747
|
-
This library is distributed in the hope that it will be useful,
|
|
13748
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13749
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13750
|
-
Lesser General Public License for more details.
|
|
13751
|
-
|
|
13752
|
-
You should have received a copy of the GNU Lesser General Public
|
|
13753
|
-
License along with this library; if not, see
|
|
13754
|
-
http://www.gnu.org/licenses/lgpl-2.1.html
|
|
13755
|
-
|
|
13756
|
-
Adapted from bzip2.js, copyright 2011 antimatter15 (antimatter15@gmail.com).
|
|
13757
|
-
|
|
13758
|
-
Based on micro-bunzip by Rob Landley (rob@landley.net).
|
|
13759
|
-
|
|
13760
|
-
Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
|
|
13761
|
-
which also acknowledges contributions by Mike Burrows, David Wheeler,
|
|
13762
|
-
Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
|
|
13763
|
-
Robert Sedgewick, and Jon L. Bentley.
|
|
13764
|
-
*/
|
|
13765
|
-
|
|
13766
|
-
var BITMASK = [0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF];
|
|
13767
|
-
|
|
13768
|
-
// offset in bytes
|
|
13769
|
-
var BitReader$1 = function(stream) {
|
|
13770
|
-
this.stream = stream;
|
|
13771
|
-
this.bitOffset = 0;
|
|
13772
|
-
this.curByte = 0;
|
|
13773
|
-
this.hasByte = false;
|
|
13774
|
-
};
|
|
13775
|
-
|
|
13776
|
-
BitReader$1.prototype._ensureByte = function() {
|
|
13777
|
-
if (!this.hasByte) {
|
|
13778
|
-
this.curByte = this.stream.readByte();
|
|
13779
|
-
this.hasByte = true;
|
|
13780
|
-
}
|
|
13781
|
-
};
|
|
13782
|
-
|
|
13783
|
-
// reads bits from the buffer
|
|
13784
|
-
BitReader$1.prototype.read = function(bits) {
|
|
13785
|
-
var result = 0;
|
|
13786
|
-
while (bits > 0) {
|
|
13787
|
-
this._ensureByte();
|
|
13788
|
-
var remaining = 8 - this.bitOffset;
|
|
13789
|
-
// if we're in a byte
|
|
13790
|
-
if (bits >= remaining) {
|
|
13791
|
-
result <<= remaining;
|
|
13792
|
-
result |= BITMASK[remaining] & this.curByte;
|
|
13793
|
-
this.hasByte = false;
|
|
13794
|
-
this.bitOffset = 0;
|
|
13795
|
-
bits -= remaining;
|
|
13796
|
-
} else {
|
|
13797
|
-
result <<= bits;
|
|
13798
|
-
var shift = remaining - bits;
|
|
13799
|
-
result |= (this.curByte & (BITMASK[bits] << shift)) >> shift;
|
|
13800
|
-
this.bitOffset += bits;
|
|
13801
|
-
bits = 0;
|
|
13802
|
-
}
|
|
13803
|
-
}
|
|
13804
|
-
return result;
|
|
13805
|
-
};
|
|
13806
|
-
|
|
13807
|
-
// seek to an arbitrary point in the buffer (expressed in bits)
|
|
13808
|
-
BitReader$1.prototype.seek = function(pos) {
|
|
13809
|
-
var n_bit = pos % 8;
|
|
13810
|
-
var n_byte = (pos - n_bit) / 8;
|
|
13811
|
-
this.bitOffset = n_bit;
|
|
13812
|
-
this.stream.seek(n_byte);
|
|
13813
|
-
this.hasByte = false;
|
|
13814
|
-
};
|
|
13815
|
-
|
|
13816
|
-
// reads 6 bytes worth of data using the read method
|
|
13817
|
-
BitReader$1.prototype.pi = function() {
|
|
13818
|
-
var buf = new Uint8Array(6), i;
|
|
13819
|
-
for (i = 0; i < buf.length; i++) {
|
|
13820
|
-
buf[i] = this.read(8);
|
|
13821
|
-
}
|
|
13822
|
-
return bufToHex(buf);
|
|
13823
|
-
};
|
|
13824
|
-
|
|
13825
|
-
function bufToHex(buf) {
|
|
13826
|
-
return Array.prototype.map.call(buf, x => ('00' + x.toString(16)).slice(-2)).join('');
|
|
13827
|
-
}
|
|
13828
|
-
|
|
13829
|
-
var bitreader = BitReader$1;
|
|
13830
|
-
|
|
13831
|
-
/* very simple input/output stream interface */
|
|
13832
|
-
|
|
13833
|
-
var Stream$1 = function() {
|
|
13834
|
-
};
|
|
13835
|
-
|
|
13836
|
-
// input streams //////////////
|
|
13837
|
-
/** Returns the next byte, or -1 for EOF. */
|
|
13838
|
-
Stream$1.prototype.readByte = function() {
|
|
13839
|
-
throw new Error("abstract method readByte() not implemented");
|
|
13840
|
-
};
|
|
13841
|
-
/** Attempts to fill the buffer; returns number of bytes read, or
|
|
13842
|
-
* -1 for EOF. */
|
|
13843
|
-
Stream$1.prototype.read = function(buffer, bufOffset, length) {
|
|
13844
|
-
var bytesRead = 0;
|
|
13845
|
-
while (bytesRead < length) {
|
|
13846
|
-
var c = this.readByte();
|
|
13847
|
-
if (c < 0) { // EOF
|
|
13848
|
-
return (bytesRead===0) ? -1 : bytesRead;
|
|
13849
|
-
}
|
|
13850
|
-
buffer[bufOffset++] = c;
|
|
13851
|
-
bytesRead++;
|
|
13852
|
-
}
|
|
13853
|
-
return bytesRead;
|
|
13854
|
-
};
|
|
13855
|
-
Stream$1.prototype.seek = function(new_pos) {
|
|
13856
|
-
throw new Error("abstract method seek() not implemented");
|
|
13857
|
-
};
|
|
13858
|
-
|
|
13859
|
-
// output streams ///////////
|
|
13860
|
-
Stream$1.prototype.writeByte = function(_byte) {
|
|
13861
|
-
throw new Error("abstract method readByte() not implemented");
|
|
13862
|
-
};
|
|
13863
|
-
Stream$1.prototype.write = function(buffer, bufOffset, length) {
|
|
13864
|
-
var i;
|
|
13865
|
-
for (i=0; i<length; i++) {
|
|
13866
|
-
this.writeByte(buffer[bufOffset++]);
|
|
13867
|
-
}
|
|
13868
|
-
return length;
|
|
13869
|
-
};
|
|
13870
|
-
Stream$1.prototype.flush = function() {
|
|
13871
|
-
};
|
|
13872
|
-
|
|
13873
|
-
var stream = Stream$1;
|
|
13874
|
-
|
|
13875
|
-
/* CRC32, used in Bzip2 implementation.
|
|
13876
|
-
* This is a port of CRC32.java from the jbzip2 implementation at
|
|
13877
|
-
* https://code.google.com/p/jbzip2
|
|
13878
|
-
* which is:
|
|
13879
|
-
* Copyright (c) 2011 Matthew Francis
|
|
13880
|
-
*
|
|
13881
|
-
* Permission is hereby granted, free of charge, to any person
|
|
13882
|
-
* obtaining a copy of this software and associated documentation
|
|
13883
|
-
* files (the "Software"), to deal in the Software without
|
|
13884
|
-
* restriction, including without limitation the rights to use,
|
|
13885
|
-
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13886
|
-
* copies of the Software, and to permit persons to whom the
|
|
13887
|
-
* Software is furnished to do so, subject to the following
|
|
13888
|
-
* conditions:
|
|
13889
|
-
*
|
|
13890
|
-
* The above copyright notice and this permission notice shall be
|
|
13891
|
-
* included in all copies or substantial portions of the Software.
|
|
13892
|
-
*
|
|
13893
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
13894
|
-
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
13895
|
-
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
13896
|
-
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
13897
|
-
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
13898
|
-
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
13899
|
-
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
13900
|
-
* OTHER DEALINGS IN THE SOFTWARE.
|
|
13901
|
-
* This JavaScript implementation is:
|
|
13902
|
-
* Copyright (c) 2013 C. Scott Ananian
|
|
13903
|
-
* with the same licensing terms as Matthew Francis' original implementation.
|
|
13904
|
-
*/
|
|
13905
|
-
|
|
13906
|
-
var crc32 = (function() {
|
|
13907
|
-
|
|
13908
|
-
/**
|
|
13909
|
-
* A static CRC lookup table
|
|
13910
|
-
*/
|
|
13911
|
-
var crc32Lookup = new Uint32Array([
|
|
13912
|
-
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
|
13913
|
-
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
|
13914
|
-
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
|
13915
|
-
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
|
13916
|
-
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
|
13917
|
-
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
|
13918
|
-
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
|
13919
|
-
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
|
13920
|
-
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
|
13921
|
-
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
|
13922
|
-
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
|
13923
|
-
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
|
13924
|
-
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
|
13925
|
-
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
|
13926
|
-
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
|
13927
|
-
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
|
13928
|
-
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
|
13929
|
-
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
|
13930
|
-
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
|
13931
|
-
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
|
13932
|
-
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
|
13933
|
-
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
|
13934
|
-
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
|
13935
|
-
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
|
13936
|
-
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
|
13937
|
-
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
|
13938
|
-
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
|
13939
|
-
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
|
13940
|
-
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
|
13941
|
-
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
|
13942
|
-
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
|
13943
|
-
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
|
13944
|
-
]);
|
|
13945
|
-
|
|
13946
|
-
var CRC32 = function() {
|
|
13947
|
-
/**
|
|
13948
|
-
* The current CRC
|
|
13949
|
-
*/
|
|
13950
|
-
var crc = 0xffffffff;
|
|
13951
|
-
|
|
13952
|
-
/**
|
|
13953
|
-
* @return The current CRC
|
|
13954
|
-
*/
|
|
13955
|
-
this.getCRC = function() {
|
|
13956
|
-
return (~crc) >>> 0; // return an unsigned value
|
|
13957
|
-
};
|
|
13958
|
-
|
|
13959
|
-
/**
|
|
13960
|
-
* Update the CRC with a single byte
|
|
13961
|
-
* @param value The value to update the CRC with
|
|
13962
|
-
*/
|
|
13963
|
-
this.updateCRC = function(value) {
|
|
13964
|
-
crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff];
|
|
13965
|
-
};
|
|
13966
|
-
|
|
13967
|
-
/**
|
|
13968
|
-
* Update the CRC with a sequence of identical bytes
|
|
13969
|
-
* @param value The value to update the CRC with
|
|
13970
|
-
* @param count The number of bytes
|
|
13971
|
-
*/
|
|
13972
|
-
this.updateCRCRun = function(value, count) {
|
|
13973
|
-
while (count-- > 0) {
|
|
13974
|
-
crc = (crc << 8) ^ crc32Lookup[((crc >>> 24) ^ value) & 0xff];
|
|
13975
|
-
}
|
|
13976
|
-
};
|
|
13977
|
-
};
|
|
13978
|
-
return CRC32;
|
|
13979
|
-
})();
|
|
13980
|
-
|
|
13981
|
-
/*
|
|
13982
|
-
seek-bzip - a pure-javascript module for seeking within bzip2 data
|
|
13983
|
-
|
|
13984
|
-
Copyright (C) 2013 C. Scott Ananian
|
|
13985
|
-
Copyright (C) 2012 Eli Skeggs
|
|
13986
|
-
Copyright (C) 2011 Kevin Kwok
|
|
13987
|
-
|
|
13988
|
-
This library is free software; you can redistribute it and/or
|
|
13989
|
-
modify it under the terms of the GNU Lesser General Public
|
|
13990
|
-
License as published by the Free Software Foundation; either
|
|
13991
|
-
version 2.1 of the License, or (at your option) any later version.
|
|
13992
|
-
|
|
13993
|
-
This library is distributed in the hope that it will be useful,
|
|
13994
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13995
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13996
|
-
Lesser General Public License for more details.
|
|
13997
|
-
|
|
13998
|
-
You should have received a copy of the GNU Lesser General Public
|
|
13999
|
-
License along with this library; if not, see
|
|
14000
|
-
http://www.gnu.org/licenses/lgpl-2.1.html
|
|
14001
|
-
|
|
14002
|
-
Adapted from node-bzip, copyright 2012 Eli Skeggs.
|
|
14003
|
-
Adapted from bzip2.js, copyright 2011 Kevin Kwok (antimatter15@gmail.com).
|
|
14004
|
-
|
|
14005
|
-
Based on micro-bunzip by Rob Landley (rob@landley.net).
|
|
14006
|
-
|
|
14007
|
-
Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
|
|
14008
|
-
which also acknowledges contributions by Mike Burrows, David Wheeler,
|
|
14009
|
-
Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten,
|
|
14010
|
-
Robert Sedgewick, and Jon L. Bentley.
|
|
14011
|
-
*/
|
|
14012
|
-
|
|
14013
|
-
var BitReader = bitreader;
|
|
14014
|
-
var Stream = stream;
|
|
14015
|
-
var CRC32 = crc32;
|
|
14016
|
-
|
|
14017
|
-
var MAX_HUFCODE_BITS = 20;
|
|
14018
|
-
var MAX_SYMBOLS = 258;
|
|
14019
|
-
var SYMBOL_RUNA = 0;
|
|
14020
|
-
var SYMBOL_RUNB = 1;
|
|
14021
|
-
var MIN_GROUPS = 2;
|
|
14022
|
-
var MAX_GROUPS = 6;
|
|
14023
|
-
var GROUP_SIZE = 50;
|
|
14024
|
-
|
|
14025
|
-
var WHOLEPI = "314159265359";
|
|
14026
|
-
var SQRTPI = "177245385090";
|
|
14027
|
-
|
|
14028
|
-
var mtf = function(array, index) {
|
|
14029
|
-
var src = array[index], i;
|
|
14030
|
-
for (i = index; i > 0; i--) {
|
|
14031
|
-
array[i] = array[i-1];
|
|
14032
|
-
}
|
|
14033
|
-
array[0] = src;
|
|
14034
|
-
return src;
|
|
14035
|
-
};
|
|
14036
|
-
|
|
14037
|
-
var Err = {
|
|
14038
|
-
OK: 0,
|
|
14039
|
-
LAST_BLOCK: -1,
|
|
14040
|
-
NOT_BZIP_DATA: -2,
|
|
14041
|
-
UNEXPECTED_INPUT_EOF: -3,
|
|
14042
|
-
UNEXPECTED_OUTPUT_EOF: -4,
|
|
14043
|
-
DATA_ERROR: -5,
|
|
14044
|
-
OUT_OF_MEMORY: -6,
|
|
14045
|
-
OBSOLETE_INPUT: -7,
|
|
14046
|
-
END_OF_BLOCK: -8
|
|
14047
|
-
};
|
|
14048
|
-
var ErrorMessages = {};
|
|
14049
|
-
ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum";
|
|
14050
|
-
ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data";
|
|
14051
|
-
ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF";
|
|
14052
|
-
ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF";
|
|
14053
|
-
ErrorMessages[Err.DATA_ERROR] = "Data error";
|
|
14054
|
-
ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory";
|
|
14055
|
-
ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported.";
|
|
14056
|
-
|
|
14057
|
-
var _throw = function(status, optDetail) {
|
|
14058
|
-
var msg = ErrorMessages[status] || 'unknown error';
|
|
14059
|
-
if (optDetail) { msg += ': '+optDetail; }
|
|
14060
|
-
var e = new TypeError(msg);
|
|
14061
|
-
e.errorCode = status;
|
|
14062
|
-
throw e;
|
|
14063
|
-
};
|
|
14064
|
-
|
|
14065
|
-
var Bunzip = function(inputStream, outputStream) {
|
|
14066
|
-
this.writePos = this.writeCurrent = this.writeCount = 0;
|
|
14067
|
-
|
|
14068
|
-
this._start_bunzip(inputStream, outputStream);
|
|
14069
|
-
};
|
|
14070
|
-
Bunzip.prototype._init_block = function() {
|
|
14071
|
-
var moreBlocks = this._get_next_block();
|
|
14072
|
-
if ( !moreBlocks ) {
|
|
14073
|
-
this.writeCount = -1;
|
|
14074
|
-
return false; /* no more blocks */
|
|
14075
|
-
}
|
|
14076
|
-
this.blockCRC = new CRC32();
|
|
14077
|
-
return true;
|
|
14078
|
-
};
|
|
14079
|
-
/* XXX micro-bunzip uses (inputStream, inputBuffer, len) as arguments */
|
|
14080
|
-
Bunzip.prototype._start_bunzip = function(inputStream, outputStream) {
|
|
14081
|
-
/* Ensure that file starts with "BZh['1'-'9']." */
|
|
14082
|
-
var buf = new Uint8Array(4);
|
|
14083
|
-
if (inputStream.read(buf, 0, 4) !== 4 ||
|
|
14084
|
-
String.fromCharCode(buf[0], buf[1], buf[2]) !== 'BZh')
|
|
14085
|
-
_throw(Err.NOT_BZIP_DATA, 'bad magic');
|
|
14086
|
-
|
|
14087
|
-
var level = buf[3] - 0x30;
|
|
14088
|
-
if (level < 1 || level > 9)
|
|
14089
|
-
_throw(Err.NOT_BZIP_DATA, 'level out of range');
|
|
14090
|
-
|
|
14091
|
-
this.reader = new BitReader(inputStream);
|
|
14092
|
-
|
|
14093
|
-
/* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of
|
|
14094
|
-
uncompressed data. Allocate intermediate buffer for block. */
|
|
14095
|
-
this.dbufSize = 100000 * level;
|
|
14096
|
-
this.nextoutput = 0;
|
|
14097
|
-
this.outputStream = outputStream;
|
|
14098
|
-
this.streamCRC = 0;
|
|
14099
|
-
};
|
|
14100
|
-
Bunzip.prototype._get_next_block = function() {
|
|
14101
|
-
var i, j, k;
|
|
14102
|
-
var reader = this.reader;
|
|
14103
|
-
// this is get_next_block() function from micro-bunzip:
|
|
14104
|
-
/* Read in header signature and CRC, then validate signature.
|
|
14105
|
-
(last block signature means CRC is for whole file, return now) */
|
|
14106
|
-
var h = reader.pi();
|
|
14107
|
-
if (h === SQRTPI) { // last block
|
|
14108
|
-
return false; /* no more blocks */
|
|
14109
|
-
}
|
|
14110
|
-
if (h !== WHOLEPI)
|
|
14111
|
-
_throw(Err.NOT_BZIP_DATA);
|
|
14112
|
-
this.targetBlockCRC = reader.read(32) >>> 0; // (convert to unsigned)
|
|
14113
|
-
this.streamCRC = (this.targetBlockCRC ^
|
|
14114
|
-
((this.streamCRC << 1) | (this.streamCRC>>>31))) >>> 0;
|
|
14115
|
-
/* We can add support for blockRandomised if anybody complains. There was
|
|
14116
|
-
some code for this in busybox 1.0.0-pre3, but nobody ever noticed that
|
|
14117
|
-
it didn't actually work. */
|
|
14118
|
-
if (reader.read(1))
|
|
14119
|
-
_throw(Err.OBSOLETE_INPUT);
|
|
14120
|
-
var origPointer = reader.read(24);
|
|
14121
|
-
if (origPointer > this.dbufSize)
|
|
14122
|
-
_throw(Err.DATA_ERROR, 'initial position out of bounds');
|
|
14123
|
-
/* mapping table: if some byte values are never used (encoding things
|
|
14124
|
-
like ascii text), the compression code removes the gaps to have fewer
|
|
14125
|
-
symbols to deal with, and writes a sparse bitfield indicating which
|
|
14126
|
-
values were present. We make a translation table to convert the symbols
|
|
14127
|
-
back to the corresponding bytes. */
|
|
14128
|
-
var t = reader.read(16);
|
|
14129
|
-
var symToByte = new Uint8Array(256), symTotal = 0;
|
|
14130
|
-
for (i = 0; i < 16; i++) {
|
|
14131
|
-
if (t & (1 << (0xF - i))) {
|
|
14132
|
-
var o = i * 16;
|
|
14133
|
-
k = reader.read(16);
|
|
14134
|
-
for (j = 0; j < 16; j++)
|
|
14135
|
-
if (k & (1 << (0xF - j)))
|
|
14136
|
-
symToByte[symTotal++] = o + j;
|
|
14137
|
-
}
|
|
14138
|
-
}
|
|
14139
|
-
|
|
14140
|
-
/* How many different huffman coding groups does this block use? */
|
|
14141
|
-
var groupCount = reader.read(3);
|
|
14142
|
-
if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS)
|
|
14143
|
-
_throw(Err.DATA_ERROR);
|
|
14144
|
-
/* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding
|
|
14145
|
-
group. Read in the group selector list, which is stored as MTF encoded
|
|
14146
|
-
bit runs. (MTF=Move To Front, as each value is used it's moved to the
|
|
14147
|
-
start of the list.) */
|
|
14148
|
-
var nSelectors = reader.read(15);
|
|
14149
|
-
if (nSelectors === 0)
|
|
14150
|
-
_throw(Err.DATA_ERROR);
|
|
14151
|
-
|
|
14152
|
-
var mtfSymbol = new Uint8Array(256);
|
|
14153
|
-
for (i = 0; i < groupCount; i++)
|
|
14154
|
-
mtfSymbol[i] = i;
|
|
14155
|
-
|
|
14156
|
-
var selectors = new Uint8Array(nSelectors); // was 32768...
|
|
14157
|
-
|
|
14158
|
-
for (i = 0; i < nSelectors; i++) {
|
|
14159
|
-
/* Get next value */
|
|
14160
|
-
for (j = 0; reader.read(1); j++)
|
|
14161
|
-
if (j >= groupCount) _throw(Err.DATA_ERROR);
|
|
14162
|
-
/* Decode MTF to get the next selector */
|
|
14163
|
-
selectors[i] = mtf(mtfSymbol, j);
|
|
14164
|
-
}
|
|
14165
|
-
|
|
14166
|
-
/* Read the huffman coding tables for each group, which code for symTotal
|
|
14167
|
-
literal symbols, plus two run symbols (RUNA, RUNB) */
|
|
14168
|
-
var symCount = symTotal + 2;
|
|
14169
|
-
var groups = [], hufGroup;
|
|
14170
|
-
for (j = 0; j < groupCount; j++) {
|
|
14171
|
-
var length = new Uint8Array(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1);
|
|
14172
|
-
/* Read huffman code lengths for each symbol. They're stored in
|
|
14173
|
-
a way similar to mtf; record a starting value for the first symbol,
|
|
14174
|
-
and an offset from the previous value for everys symbol after that. */
|
|
14175
|
-
t = reader.read(5); // lengths
|
|
14176
|
-
for (i = 0; i < symCount; i++) {
|
|
14177
|
-
for (;;) {
|
|
14178
|
-
if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR);
|
|
14179
|
-
/* If first bit is 0, stop. Else second bit indicates whether
|
|
14180
|
-
to increment or decrement the value. */
|
|
14181
|
-
if(!reader.read(1))
|
|
14182
|
-
break;
|
|
14183
|
-
if(!reader.read(1))
|
|
14184
|
-
t++;
|
|
14185
|
-
else
|
|
14186
|
-
t--;
|
|
14187
|
-
}
|
|
14188
|
-
length[i] = t;
|
|
14189
|
-
}
|
|
14190
|
-
|
|
14191
|
-
/* Find largest and smallest lengths in this group */
|
|
14192
|
-
var minLen, maxLen;
|
|
14193
|
-
minLen = maxLen = length[0];
|
|
14194
|
-
for (i = 1; i < symCount; i++) {
|
|
14195
|
-
if (length[i] > maxLen)
|
|
14196
|
-
maxLen = length[i];
|
|
14197
|
-
else if (length[i] < minLen)
|
|
14198
|
-
minLen = length[i];
|
|
14199
|
-
}
|
|
14200
|
-
|
|
14201
|
-
/* Calculate permute[], base[], and limit[] tables from length[].
|
|
14202
|
-
*
|
|
14203
|
-
* permute[] is the lookup table for converting huffman coded symbols
|
|
14204
|
-
* into decoded symbols. base[] is the amount to subtract from the
|
|
14205
|
-
* value of a huffman symbol of a given length when using permute[].
|
|
14206
|
-
*
|
|
14207
|
-
* limit[] indicates the largest numerical value a symbol with a given
|
|
14208
|
-
* number of bits can have. This is how the huffman codes can vary in
|
|
14209
|
-
* length: each code with a value>limit[length] needs another bit.
|
|
14210
|
-
*/
|
|
14211
|
-
hufGroup = {};
|
|
14212
|
-
groups.push(hufGroup);
|
|
14213
|
-
hufGroup.permute = new Uint16Array(MAX_SYMBOLS);
|
|
14214
|
-
hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2);
|
|
14215
|
-
hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1);
|
|
14216
|
-
hufGroup.minLen = minLen;
|
|
14217
|
-
hufGroup.maxLen = maxLen;
|
|
14218
|
-
/* Calculate permute[]. Concurently, initialize temp[] and limit[]. */
|
|
14219
|
-
var pp = 0;
|
|
14220
|
-
for (i = minLen; i <= maxLen; i++) {
|
|
14221
|
-
temp[i] = hufGroup.limit[i] = 0;
|
|
14222
|
-
for (t = 0; t < symCount; t++)
|
|
14223
|
-
if (length[t] === i)
|
|
14224
|
-
hufGroup.permute[pp++] = t;
|
|
14225
|
-
}
|
|
14226
|
-
/* Count symbols coded for at each bit length */
|
|
14227
|
-
for (i = 0; i < symCount; i++)
|
|
14228
|
-
temp[length[i]]++;
|
|
14229
|
-
/* Calculate limit[] (the largest symbol-coding value at each bit
|
|
14230
|
-
* length, which is (previous limit<<1)+symbols at this level), and
|
|
14231
|
-
* base[] (number of symbols to ignore at each bit length, which is
|
|
14232
|
-
* limit minus the cumulative count of symbols coded for already). */
|
|
14233
|
-
pp = t = 0;
|
|
14234
|
-
for (i = minLen; i < maxLen; i++) {
|
|
14235
|
-
pp += temp[i];
|
|
14236
|
-
/* We read the largest possible symbol size and then unget bits
|
|
14237
|
-
after determining how many we need, and those extra bits could
|
|
14238
|
-
be set to anything. (They're noise from future symbols.) At
|
|
14239
|
-
each level we're really only interested in the first few bits,
|
|
14240
|
-
so here we set all the trailing to-be-ignored bits to 1 so they
|
|
14241
|
-
don't affect the value>limit[length] comparison. */
|
|
14242
|
-
hufGroup.limit[i] = pp - 1;
|
|
14243
|
-
pp <<= 1;
|
|
14244
|
-
t += temp[i];
|
|
14245
|
-
hufGroup.base[i + 1] = pp - t;
|
|
14246
|
-
}
|
|
14247
|
-
hufGroup.limit[maxLen + 1] = Number.MAX_VALUE; /* Sentinal value for reading next sym. */
|
|
14248
|
-
hufGroup.limit[maxLen] = pp + temp[maxLen] - 1;
|
|
14249
|
-
hufGroup.base[minLen] = 0;
|
|
14250
|
-
}
|
|
14251
|
-
/* We've finished reading and digesting the block header. Now read this
|
|
14252
|
-
block's huffman coded symbols from the file and undo the huffman coding
|
|
14253
|
-
and run length encoding, saving the result into dbuf[dbufCount++]=uc */
|
|
14254
|
-
|
|
14255
|
-
/* Initialize symbol occurrence counters and symbol Move To Front table */
|
|
14256
|
-
var byteCount = new Uint32Array(256);
|
|
14257
|
-
for (i = 0; i < 256; i++)
|
|
14258
|
-
mtfSymbol[i] = i;
|
|
14259
|
-
/* Loop through compressed symbols. */
|
|
14260
|
-
var runPos = 0, dbufCount = 0, selector = 0, uc;
|
|
14261
|
-
var dbuf = this.dbuf = new Uint32Array(this.dbufSize);
|
|
14262
|
-
symCount = 0;
|
|
14263
|
-
for (;;) {
|
|
14264
|
-
/* Determine which huffman coding group to use. */
|
|
14265
|
-
if (!(symCount--)) {
|
|
14266
|
-
symCount = GROUP_SIZE - 1;
|
|
14267
|
-
if (selector >= nSelectors) { _throw(Err.DATA_ERROR); }
|
|
14268
|
-
hufGroup = groups[selectors[selector++]];
|
|
14269
|
-
}
|
|
14270
|
-
/* Read next huffman-coded symbol. */
|
|
14271
|
-
i = hufGroup.minLen;
|
|
14272
|
-
j = reader.read(i);
|
|
14273
|
-
for (;;i++) {
|
|
14274
|
-
if (i > hufGroup.maxLen) { _throw(Err.DATA_ERROR); }
|
|
14275
|
-
if (j <= hufGroup.limit[i])
|
|
14276
|
-
break;
|
|
14277
|
-
j = (j << 1) | reader.read(1);
|
|
14278
|
-
}
|
|
14279
|
-
/* Huffman decode value to get nextSym (with bounds checking) */
|
|
14280
|
-
j -= hufGroup.base[i];
|
|
14281
|
-
if (j < 0 || j >= MAX_SYMBOLS) { _throw(Err.DATA_ERROR); }
|
|
14282
|
-
var nextSym = hufGroup.permute[j];
|
|
14283
|
-
/* We have now decoded the symbol, which indicates either a new literal
|
|
14284
|
-
byte, or a repeated run of the most recent literal byte. First,
|
|
14285
|
-
check if nextSym indicates a repeated run, and if so loop collecting
|
|
14286
|
-
how many times to repeat the last literal. */
|
|
14287
|
-
if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) {
|
|
14288
|
-
/* If this is the start of a new run, zero out counter */
|
|
14289
|
-
if (!runPos){
|
|
14290
|
-
runPos = 1;
|
|
14291
|
-
t = 0;
|
|
14292
|
-
}
|
|
14293
|
-
/* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at
|
|
14294
|
-
each bit position, add 1 or 2 instead. For example,
|
|
14295
|
-
1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2.
|
|
14296
|
-
You can make any bit pattern that way using 1 less symbol than
|
|
14297
|
-
the basic or 0/1 method (except all bits 0, which would use no
|
|
14298
|
-
symbols, but a run of length 0 doesn't mean anything in this
|
|
14299
|
-
context). Thus space is saved. */
|
|
14300
|
-
if (nextSym === SYMBOL_RUNA)
|
|
14301
|
-
t += runPos;
|
|
14302
|
-
else
|
|
14303
|
-
t += 2 * runPos;
|
|
14304
|
-
runPos <<= 1;
|
|
14305
|
-
continue;
|
|
14306
|
-
}
|
|
14307
|
-
/* When we hit the first non-run symbol after a run, we now know
|
|
14308
|
-
how many times to repeat the last literal, so append that many
|
|
14309
|
-
copies to our buffer of decoded symbols (dbuf) now. (The last
|
|
14310
|
-
literal used is the one at the head of the mtfSymbol array.) */
|
|
14311
|
-
if (runPos){
|
|
14312
|
-
runPos = 0;
|
|
14313
|
-
if (dbufCount + t > this.dbufSize) { _throw(Err.DATA_ERROR); }
|
|
14314
|
-
uc = symToByte[mtfSymbol[0]];
|
|
14315
|
-
byteCount[uc] += t;
|
|
14316
|
-
while (t--)
|
|
14317
|
-
dbuf[dbufCount++] = uc;
|
|
14318
|
-
}
|
|
14319
|
-
/* Is this the terminating symbol? */
|
|
14320
|
-
if (nextSym > symTotal)
|
|
14321
|
-
break;
|
|
14322
|
-
/* At this point, nextSym indicates a new literal character. Subtract
|
|
14323
|
-
one to get the position in the MTF array at which this literal is
|
|
14324
|
-
currently to be found. (Note that the result can't be -1 or 0,
|
|
14325
|
-
because 0 and 1 are RUNA and RUNB. But another instance of the
|
|
14326
|
-
first symbol in the mtf array, position 0, would have been handled
|
|
14327
|
-
as part of a run above. Therefore 1 unused mtf position minus
|
|
14328
|
-
2 non-literal nextSym values equals -1.) */
|
|
14329
|
-
if (dbufCount >= this.dbufSize) { _throw(Err.DATA_ERROR); }
|
|
14330
|
-
i = nextSym - 1;
|
|
14331
|
-
uc = mtf(mtfSymbol, i);
|
|
14332
|
-
uc = symToByte[uc];
|
|
14333
|
-
/* We have our literal byte. Save it into dbuf. */
|
|
14334
|
-
byteCount[uc]++;
|
|
14335
|
-
dbuf[dbufCount++] = uc;
|
|
14336
|
-
}
|
|
14337
|
-
/* At this point, we've read all the huffman-coded symbols (and repeated
|
|
14338
|
-
runs) for this block from the input stream, and decoded them into the
|
|
14339
|
-
intermediate buffer. There are dbufCount many decoded bytes in dbuf[].
|
|
14340
|
-
Now undo the Burrows-Wheeler transform on dbuf.
|
|
14341
|
-
See http://dogma.net/markn/articles/bwt/bwt.htm
|
|
14342
|
-
*/
|
|
14343
|
-
if (origPointer < 0 || origPointer >= dbufCount) { _throw(Err.DATA_ERROR); }
|
|
14344
|
-
/* Turn byteCount into cumulative occurrence counts of 0 to n-1. */
|
|
14345
|
-
j = 0;
|
|
14346
|
-
for (i = 0; i < 256; i++) {
|
|
14347
|
-
k = j + byteCount[i];
|
|
14348
|
-
byteCount[i] = j;
|
|
14349
|
-
j = k;
|
|
14350
|
-
}
|
|
14351
|
-
/* Figure out what order dbuf would be in if we sorted it. */
|
|
14352
|
-
for (i = 0; i < dbufCount; i++) {
|
|
14353
|
-
uc = dbuf[i] & 0xff;
|
|
14354
|
-
dbuf[byteCount[uc]] |= (i << 8);
|
|
14355
|
-
byteCount[uc]++;
|
|
14356
|
-
}
|
|
14357
|
-
/* Decode first byte by hand to initialize "previous" byte. Note that it
|
|
14358
|
-
doesn't get output, and if the first three characters are identical
|
|
14359
|
-
it doesn't qualify as a run (hence writeRunCountdown=5). */
|
|
14360
|
-
var pos = 0, current = 0, run = 0;
|
|
14361
|
-
if (dbufCount) {
|
|
14362
|
-
pos = dbuf[origPointer];
|
|
14363
|
-
current = (pos & 0xff);
|
|
14364
|
-
pos >>= 8;
|
|
14365
|
-
run = -1;
|
|
14366
|
-
}
|
|
14367
|
-
this.writePos = pos;
|
|
14368
|
-
this.writeCurrent = current;
|
|
14369
|
-
this.writeCount = dbufCount;
|
|
14370
|
-
this.writeRun = run;
|
|
14371
|
-
|
|
14372
|
-
return true; /* more blocks to come */
|
|
14373
|
-
};
|
|
14374
|
-
/* Undo burrows-wheeler transform on intermediate buffer to produce output.
|
|
14375
|
-
If start_bunzip was initialized with out_fd=-1, then up to len bytes of
|
|
14376
|
-
data are written to outbuf. Return value is number of bytes written or
|
|
14377
|
-
error (all errors are negative numbers). If out_fd!=-1, outbuf and len
|
|
14378
|
-
are ignored, data is written to out_fd and return is RETVAL_OK or error.
|
|
14379
|
-
*/
|
|
14380
|
-
Bunzip.prototype._read_bunzip = function(outputBuffer, len) {
|
|
14381
|
-
var copies, previous, outbyte;
|
|
14382
|
-
/* james@jamestaylor.org: writeCount goes to -1 when the buffer is fully
|
|
14383
|
-
decoded, which results in this returning RETVAL_LAST_BLOCK, also
|
|
14384
|
-
equal to -1... Confusing, I'm returning 0 here to indicate no
|
|
14385
|
-
bytes written into the buffer */
|
|
14386
|
-
if (this.writeCount < 0) { return 0; }
|
|
14387
|
-
var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent;
|
|
14388
|
-
var dbufCount = this.writeCount; this.outputsize;
|
|
14389
|
-
var run = this.writeRun;
|
|
14390
|
-
|
|
14391
|
-
while (dbufCount) {
|
|
14392
|
-
dbufCount--;
|
|
14393
|
-
previous = current;
|
|
14394
|
-
pos = dbuf[pos];
|
|
14395
|
-
current = pos & 0xff;
|
|
14396
|
-
pos >>= 8;
|
|
14397
|
-
if (run++ === 3){
|
|
14398
|
-
copies = current;
|
|
14399
|
-
outbyte = previous;
|
|
14400
|
-
current = -1;
|
|
14401
|
-
} else {
|
|
14402
|
-
copies = 1;
|
|
14403
|
-
outbyte = current;
|
|
14404
|
-
}
|
|
14405
|
-
this.blockCRC.updateCRCRun(outbyte, copies);
|
|
14406
|
-
while (copies--) {
|
|
14407
|
-
this.outputStream.writeByte(outbyte);
|
|
14408
|
-
this.nextoutput++;
|
|
14409
|
-
}
|
|
14410
|
-
if (current != previous)
|
|
14411
|
-
run = 0;
|
|
14412
|
-
}
|
|
14413
|
-
this.writeCount = dbufCount;
|
|
14414
|
-
// check CRC
|
|
14415
|
-
if (this.blockCRC.getCRC() !== this.targetBlockCRC) {
|
|
14416
|
-
_throw(Err.DATA_ERROR, "Bad block CRC "+
|
|
14417
|
-
"(got "+this.blockCRC.getCRC().toString(16)+
|
|
14418
|
-
" expected "+this.targetBlockCRC.toString(16)+")");
|
|
14419
|
-
}
|
|
14420
|
-
return this.nextoutput;
|
|
14421
|
-
};
|
|
14422
|
-
|
|
14423
|
-
var coerceInputStream = function(input) {
|
|
14424
|
-
if ('readByte' in input) { return input; }
|
|
14425
|
-
var inputStream = new Stream();
|
|
14426
|
-
inputStream.pos = 0;
|
|
14427
|
-
inputStream.readByte = function() { return input[this.pos++]; };
|
|
14428
|
-
inputStream.seek = function(pos) { this.pos = pos; };
|
|
14429
|
-
inputStream.eof = function() { return this.pos >= input.length; };
|
|
14430
|
-
return inputStream;
|
|
14431
|
-
};
|
|
14432
|
-
var coerceOutputStream = function(output) {
|
|
14433
|
-
var outputStream = new Stream();
|
|
14434
|
-
var resizeOk = true;
|
|
14435
|
-
if (output) {
|
|
14436
|
-
if (typeof(output)==='number') {
|
|
14437
|
-
outputStream.buffer = new Uint8Array(output);
|
|
14438
|
-
resizeOk = false;
|
|
14439
|
-
} else if ('writeByte' in output) {
|
|
14440
|
-
return output;
|
|
14441
|
-
} else {
|
|
14442
|
-
outputStream.buffer = output;
|
|
14443
|
-
resizeOk = false;
|
|
14444
|
-
}
|
|
14445
|
-
} else {
|
|
14446
|
-
outputStream.buffer = new Uint8Array(16384);
|
|
14447
|
-
}
|
|
14448
|
-
outputStream.pos = 0;
|
|
14449
|
-
outputStream.writeByte = function(_byte) {
|
|
14450
|
-
if (resizeOk && this.pos >= this.buffer.length) {
|
|
14451
|
-
var newBuffer = new Uint8Array(this.buffer.length*2);
|
|
14452
|
-
newBuffer.set(this.buffer);
|
|
14453
|
-
this.buffer = newBuffer;
|
|
14454
|
-
}
|
|
14455
|
-
this.buffer[this.pos++] = _byte;
|
|
14456
|
-
};
|
|
14457
|
-
outputStream.getBuffer = function() {
|
|
14458
|
-
// trim buffer
|
|
14459
|
-
if (this.pos !== this.buffer.length) {
|
|
14460
|
-
if (!resizeOk)
|
|
14461
|
-
throw new TypeError('outputsize does not match decoded input');
|
|
14462
|
-
var newBuffer = new Uint8Array(this.pos);
|
|
14463
|
-
newBuffer.set(this.buffer.subarray(0, this.pos));
|
|
14464
|
-
this.buffer = newBuffer;
|
|
14465
|
-
}
|
|
14466
|
-
return this.buffer;
|
|
14467
|
-
};
|
|
14468
|
-
outputStream._coerced = true;
|
|
14469
|
-
return outputStream;
|
|
14470
|
-
};
|
|
14471
|
-
|
|
14472
|
-
/* Static helper functions */
|
|
14473
|
-
// 'input' can be a stream or a buffer
|
|
14474
|
-
// 'output' can be a stream or a buffer or a number (buffer size)
|
|
14475
|
-
const decode = function(input, output, multistream) {
|
|
14476
|
-
// make a stream from a buffer, if necessary
|
|
14477
|
-
var inputStream = coerceInputStream(input);
|
|
14478
|
-
var outputStream = coerceOutputStream(output);
|
|
14479
|
-
|
|
14480
|
-
var bz = new Bunzip(inputStream, outputStream);
|
|
14481
|
-
while (true) {
|
|
14482
|
-
if ('eof' in inputStream && inputStream.eof()) break;
|
|
14483
|
-
if (bz._init_block()) {
|
|
14484
|
-
bz._read_bunzip();
|
|
14485
|
-
} else {
|
|
14486
|
-
var targetStreamCRC = bz.reader.read(32) >>> 0; // (convert to unsigned)
|
|
14487
|
-
if (targetStreamCRC !== bz.streamCRC) {
|
|
14488
|
-
_throw(Err.DATA_ERROR, "Bad stream CRC "+
|
|
14489
|
-
"(got "+bz.streamCRC.toString(16)+
|
|
14490
|
-
" expected "+targetStreamCRC.toString(16)+")");
|
|
14491
|
-
}
|
|
14492
|
-
if (multistream &&
|
|
14493
|
-
'eof' in inputStream &&
|
|
14494
|
-
!inputStream.eof()) {
|
|
14495
|
-
// note that start_bunzip will also resync the bit reader to next byte
|
|
14496
|
-
bz._start_bunzip(inputStream, outputStream);
|
|
14497
|
-
} else break;
|
|
14498
|
-
}
|
|
14499
|
-
}
|
|
14500
|
-
if ('getBuffer' in outputStream)
|
|
14501
|
-
return outputStream.getBuffer();
|
|
14502
|
-
};
|
|
14503
|
-
const decodeBlock = function(input, pos, output) {
|
|
14504
|
-
// make a stream from a buffer, if necessary
|
|
14505
|
-
var inputStream = coerceInputStream(input);
|
|
14506
|
-
var outputStream = coerceOutputStream(output);
|
|
14507
|
-
var bz = new Bunzip(inputStream, outputStream);
|
|
14508
|
-
bz.reader.seek(pos);
|
|
14509
|
-
/* Fill the decode buffer for the block */
|
|
14510
|
-
var moreBlocks = bz._get_next_block();
|
|
14511
|
-
if (moreBlocks) {
|
|
14512
|
-
/* Init the CRC for writing */
|
|
14513
|
-
bz.blockCRC = new CRC32();
|
|
14514
|
-
|
|
14515
|
-
/* Zero this so the current byte from before the seek is not written */
|
|
14516
|
-
bz.writeCopies = 0;
|
|
14517
|
-
|
|
14518
|
-
/* Decompress the block and write to stdout */
|
|
14519
|
-
bz._read_bunzip();
|
|
14520
|
-
// XXX keep writing?
|
|
14521
|
-
}
|
|
14522
|
-
if ('getBuffer' in outputStream)
|
|
14523
|
-
return outputStream.getBuffer();
|
|
14524
|
-
};
|
|
14525
|
-
/* Reads bzip2 file from stream or buffer `input`, and invoke
|
|
14526
|
-
* `callback(position, size)` once for each bzip2 block,
|
|
14527
|
-
* where position gives the starting position (in *bits*)
|
|
14528
|
-
* and size gives uncompressed size of the block (in *bytes*). */
|
|
14529
|
-
const table = function(input, callback, multistream) {
|
|
14530
|
-
// make a stream from a buffer, if necessary
|
|
14531
|
-
var inputStream = new Stream();
|
|
14532
|
-
inputStream.delegate = coerceInputStream(input);
|
|
14533
|
-
inputStream.pos = 0;
|
|
14534
|
-
inputStream.readByte = function() {
|
|
14535
|
-
this.pos++;
|
|
14536
|
-
return this.delegate.readByte();
|
|
14537
|
-
};
|
|
14538
|
-
if (inputStream.delegate.eof) {
|
|
14539
|
-
inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate);
|
|
14540
|
-
}
|
|
14541
|
-
var outputStream = new Stream();
|
|
14542
|
-
outputStream.pos = 0;
|
|
14543
|
-
outputStream.writeByte = function() { this.pos++; };
|
|
14544
|
-
|
|
14545
|
-
var bz = new Bunzip(inputStream, outputStream);
|
|
14546
|
-
var blockSize = bz.dbufSize;
|
|
14547
|
-
while (true) {
|
|
14548
|
-
if ('eof' in inputStream && inputStream.eof()) break;
|
|
14549
|
-
|
|
14550
|
-
var position = inputStream.pos*8 + bz.reader.bitOffset;
|
|
14551
|
-
if (bz.reader.hasByte) { position -= 8; }
|
|
14552
|
-
|
|
14553
|
-
if (bz._init_block()) {
|
|
14554
|
-
var start = outputStream.pos;
|
|
14555
|
-
bz._read_bunzip();
|
|
14556
|
-
callback(position, outputStream.pos - start);
|
|
14557
|
-
} else {
|
|
14558
|
-
bz.reader.read(32); // (but we ignore the crc)
|
|
14559
|
-
if (multistream &&
|
|
14560
|
-
'eof' in inputStream &&
|
|
14561
|
-
!inputStream.eof()) {
|
|
14562
|
-
// note that start_bunzip will also resync the bit reader to next byte
|
|
14563
|
-
bz._start_bunzip(inputStream, outputStream);
|
|
14564
|
-
console.assert(bz.dbufSize === blockSize,
|
|
14565
|
-
"shouldn't change block size within multistream file");
|
|
14566
|
-
} else break;
|
|
14567
|
-
}
|
|
14568
|
-
}
|
|
14569
|
-
};
|
|
14570
|
-
|
|
14571
|
-
var lib = {
|
|
14572
|
-
Bunzip,
|
|
14573
|
-
Stream,
|
|
14574
|
-
Err,
|
|
14575
|
-
decode,
|
|
14576
|
-
decodeBlock,
|
|
14577
|
-
table
|
|
14578
|
-
};
|
|
14579
|
-
|
|
14580
13715
|
// GPG4Browsers - An OpenPGP implementation in javascript
|
|
14581
13716
|
// Copyright (C) 2011 Recurity Labs GmbH
|
|
14582
13717
|
//
|
|
@@ -16229,12 +15364,12 @@ class CompressedDataPacket {
|
|
|
16229
15364
|
*/
|
|
16230
15365
|
async decompress(config$1 = config) {
|
|
16231
15366
|
const compressionName = enums.read(enums.compression, this.algorithm);
|
|
16232
|
-
const decompressionFn = decompress_fns[compressionName];
|
|
15367
|
+
const decompressionFn = decompress_fns[compressionName]; // bzip decompression is async
|
|
16233
15368
|
if (!decompressionFn) {
|
|
16234
15369
|
throw new Error(`${compressionName} decompression not supported`);
|
|
16235
15370
|
}
|
|
16236
15371
|
|
|
16237
|
-
this.packets = await PacketList.fromBinary(decompressionFn(this.compressed), allowedPackets$5, config$1);
|
|
15372
|
+
this.packets = await PacketList.fromBinary(await decompressionFn(this.compressed), allowedPackets$5, config$1);
|
|
16238
15373
|
}
|
|
16239
15374
|
|
|
16240
15375
|
/**
|
|
@@ -16321,9 +15456,10 @@ function zlib(compressionStreamInstantiator, ZlibStreamedConstructor) {
|
|
|
16321
15456
|
};
|
|
16322
15457
|
}
|
|
16323
15458
|
|
|
16324
|
-
function
|
|
16325
|
-
return function(data) {
|
|
16326
|
-
|
|
15459
|
+
function bzip2Decompress() {
|
|
15460
|
+
return async function(data) {
|
|
15461
|
+
const { decode: bunzipDecode } = await import('./seek-bzip.mjs').then(function (n) { return n.i; });
|
|
15462
|
+
return fromAsync(async () => bunzipDecode(await readToEnd(data)));
|
|
16327
15463
|
};
|
|
16328
15464
|
}
|
|
16329
15465
|
|
|
@@ -16348,7 +15484,7 @@ const decompress_fns = {
|
|
|
16348
15484
|
uncompressed: data => data,
|
|
16349
15485
|
zip: /*#__PURE__*/ zlib(getCompressionStreamInstantiators('deflate-raw').decompressor, Inflate),
|
|
16350
15486
|
zlib: /*#__PURE__*/ zlib(getCompressionStreamInstantiators('deflate').decompressor, Unzlib),
|
|
16351
|
-
bzip2: /*#__PURE__*/
|
|
15487
|
+
bzip2: /*#__PURE__*/ bzip2Decompress() // NB: async due to dynamic lib import
|
|
16352
15488
|
};
|
|
16353
15489
|
|
|
16354
15490
|
// GPG4Browsers - An OpenPGP implementation in javascript
|
|
@@ -16468,6 +15604,16 @@ class SymEncryptedIntegrityProtectedDataPacket {
|
|
|
16468
15604
|
* @async
|
|
16469
15605
|
*/
|
|
16470
15606
|
async encrypt(sessionKeyAlgorithm, key, config$1 = config) {
|
|
15607
|
+
// We check that the session key size matches the one expected by the symmetric algorithm.
|
|
15608
|
+
// This is especially important for SEIPDv2 session keys, as a key derivation step is run where the resulting key will always match the expected cipher size,
|
|
15609
|
+
// but we want to ensure that the input key isn't e.g. too short.
|
|
15610
|
+
// The check is done here, instead of on encrypted session key (ESK) encryption, because v6 ESK packets do not store the session key algorithm,
|
|
15611
|
+
// which is instead included in the SEIPDv2 data.
|
|
15612
|
+
const { blockSize, keySize } = mod.getCipherParams(sessionKeyAlgorithm);
|
|
15613
|
+
if (key.length !== keySize) {
|
|
15614
|
+
throw new Error('Unexpected session key size');
|
|
15615
|
+
}
|
|
15616
|
+
|
|
16471
15617
|
let bytes = this.packets.write();
|
|
16472
15618
|
if (isArrayStream(bytes)) bytes = await readToEnd(bytes);
|
|
16473
15619
|
|
|
@@ -16478,8 +15624,6 @@ class SymEncryptedIntegrityProtectedDataPacket {
|
|
|
16478
15624
|
this.chunkSizeByte = config$1.aeadChunkSizeByte;
|
|
16479
15625
|
this.encrypted = await runAEAD(this, 'encrypt', key, bytes);
|
|
16480
15626
|
} else {
|
|
16481
|
-
const { blockSize } = mod.getCipherParams(sessionKeyAlgorithm);
|
|
16482
|
-
|
|
16483
15627
|
const prefix = await mod.getPrefixRandom(sessionKeyAlgorithm);
|
|
16484
15628
|
const mdc = new Uint8Array([0xD3, 0x14]); // modification detection code packet
|
|
16485
15629
|
|
|
@@ -16502,11 +15646,24 @@ class SymEncryptedIntegrityProtectedDataPacket {
|
|
|
16502
15646
|
* @async
|
|
16503
15647
|
*/
|
|
16504
15648
|
async decrypt(sessionKeyAlgorithm, key, config$1 = config) {
|
|
15649
|
+
// We check that the session key size matches the one expected by the symmetric algorithm.
|
|
15650
|
+
// This is especially important for SEIPDv2 session keys, as a key derivation step is run where the resulting key will always match the expected cipher size,
|
|
15651
|
+
// but we want to ensure that the input key isn't e.g. too short.
|
|
15652
|
+
// The check is done here, instead of on encrypted session key (ESK) decryption, because v6 ESK packets do not store the session key algorithm,
|
|
15653
|
+
// which is instead included in the SEIPDv2 data.
|
|
15654
|
+
if (key.length !== mod.getCipherParams(sessionKeyAlgorithm).keySize) {
|
|
15655
|
+
throw new Error('Unexpected session key size');
|
|
15656
|
+
}
|
|
15657
|
+
|
|
16505
15658
|
let encrypted = clone(this.encrypted);
|
|
16506
15659
|
if (isArrayStream(encrypted)) encrypted = await readToEnd(encrypted);
|
|
16507
15660
|
|
|
16508
15661
|
let packetbytes;
|
|
16509
15662
|
if (this.version === 2) {
|
|
15663
|
+
if (this.cipherAlgorithm !== sessionKeyAlgorithm) {
|
|
15664
|
+
// sanity check
|
|
15665
|
+
throw new Error('Unexpected session key algorithm');
|
|
15666
|
+
}
|
|
16510
15667
|
packetbytes = await runAEAD(this, 'decrypt', key, encrypted);
|
|
16511
15668
|
} else {
|
|
16512
15669
|
const { blockSize } = mod.getCipherParams(sessionKeyAlgorithm);
|
|
@@ -16974,11 +16131,14 @@ class PublicKeyEncryptedSessionKeyPacket {
|
|
|
16974
16131
|
|
|
16975
16132
|
const { sessionKey, sessionKeyAlgorithm } = decodeSessionKey(this.version, this.publicKeyAlgorithm, decryptedData, randomSessionKey);
|
|
16976
16133
|
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
this.publicKeyAlgorithm !== enums.publicKey.x25519 && this.publicKeyAlgorithm !== enums.publicKey.x448
|
|
16980
|
-
|
|
16981
|
-
|
|
16134
|
+
if (this.version === 3) {
|
|
16135
|
+
// v3 Montgomery curves have cleartext cipher algo
|
|
16136
|
+
const hasEncryptedAlgo = this.publicKeyAlgorithm !== enums.publicKey.x25519 && this.publicKeyAlgorithm !== enums.publicKey.x448;
|
|
16137
|
+
this.sessionKeyAlgorithm = hasEncryptedAlgo ? sessionKeyAlgorithm : this.sessionKeyAlgorithm;
|
|
16138
|
+
|
|
16139
|
+
if (sessionKey.length !== mod.getCipherParams(this.sessionKeyAlgorithm).keySize) {
|
|
16140
|
+
throw new Error('Unexpected session key size');
|
|
16141
|
+
}
|
|
16982
16142
|
}
|
|
16983
16143
|
this.sessionKey = sessionKey;
|
|
16984
16144
|
}
|
|
@@ -17108,7 +16268,7 @@ class SymEncryptedSessionKeyPacket {
|
|
|
17108
16268
|
* Algorithm to encrypt the message with
|
|
17109
16269
|
* @type {enums.symmetric}
|
|
17110
16270
|
*/
|
|
17111
|
-
this.sessionKeyAlgorithm =
|
|
16271
|
+
this.sessionKeyAlgorithm = null;
|
|
17112
16272
|
/**
|
|
17113
16273
|
* AEAD mode to encrypt the session key with (if AEAD protection is enabled)
|
|
17114
16274
|
* @type {enums.aead}
|
|
@@ -17229,7 +16389,11 @@ class SymEncryptedSessionKeyPacket {
|
|
|
17229
16389
|
|
|
17230
16390
|
this.sessionKeyAlgorithm = enums.write(enums.symmetric, decrypted[0]);
|
|
17231
16391
|
this.sessionKey = decrypted.subarray(1, decrypted.length);
|
|
16392
|
+
if (this.sessionKey.length !== mod.getCipherParams(this.sessionKeyAlgorithm).keySize) {
|
|
16393
|
+
throw new Error('Unexpected session key size');
|
|
16394
|
+
}
|
|
17232
16395
|
} else {
|
|
16396
|
+
// session key size is checked as part of SEIPDv2 decryption, where we know the expected symmetric algo
|
|
17233
16397
|
this.sessionKey = key;
|
|
17234
16398
|
}
|
|
17235
16399
|
}
|
|
@@ -18878,7 +18042,7 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
|
|
|
18878
18042
|
const signatureProperties = { signatureType: enums.signature.subkeyBinding };
|
|
18879
18043
|
if (options.sign) {
|
|
18880
18044
|
signatureProperties.keyFlags = [enums.keyFlags.signData];
|
|
18881
|
-
signatureProperties.embeddedSignature = await createSignaturePacket(dataToSign,
|
|
18045
|
+
signatureProperties.embeddedSignature = await createSignaturePacket(dataToSign, [], subkey, {
|
|
18882
18046
|
signatureType: enums.signature.keyBinding
|
|
18883
18047
|
}, options.date, undefined, undefined, undefined, config);
|
|
18884
18048
|
} else {
|
|
@@ -18890,41 +18054,95 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
|
|
|
18890
18054
|
signatureProperties.keyExpirationTime = options.keyExpirationTime;
|
|
18891
18055
|
signatureProperties.keyNeverExpires = false;
|
|
18892
18056
|
}
|
|
18893
|
-
const subkeySignaturePacket = await createSignaturePacket(dataToSign,
|
|
18057
|
+
const subkeySignaturePacket = await createSignaturePacket(dataToSign, [], primaryKey, signatureProperties, options.date, undefined, undefined, undefined, config);
|
|
18894
18058
|
return subkeySignaturePacket;
|
|
18895
18059
|
}
|
|
18896
18060
|
|
|
18897
18061
|
/**
|
|
18898
|
-
* Returns the preferred signature hash algorithm
|
|
18899
|
-
* @param {Key} [
|
|
18900
|
-
* @param {SecretKeyPacket|SecretSubkeyPacket}
|
|
18062
|
+
* Returns the preferred signature hash algorithm for a set of keys.
|
|
18063
|
+
* @param {Array<Key>} [targetKeys] - The keys to get preferences from
|
|
18064
|
+
* @param {SecretKeyPacket|SecretSubkeyPacket} signingKeyPacket - key packet used for signing
|
|
18901
18065
|
* @param {Date} [date] - Use the given date for verification instead of the current time
|
|
18902
|
-
* @param {Object} [
|
|
18066
|
+
* @param {Object} [targetUserID] - User IDs corresponding to `targetKeys` to get preferences from
|
|
18903
18067
|
* @param {Object} config - full configuration
|
|
18904
18068
|
* @returns {Promise<enums.hash>}
|
|
18905
18069
|
* @async
|
|
18906
18070
|
*/
|
|
18907
|
-
async function getPreferredHashAlgo(
|
|
18908
|
-
|
|
18909
|
-
|
|
18910
|
-
|
|
18911
|
-
|
|
18912
|
-
|
|
18913
|
-
|
|
18914
|
-
|
|
18915
|
-
|
|
18071
|
+
async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Date(), targetUserIDs = [], config) {
|
|
18072
|
+
/**
|
|
18073
|
+
* If `preferredSenderAlgo` appears in the prefs of all recipients, we pick it; otherwise, we use the
|
|
18074
|
+
* strongest supported algo (`defaultAlgo` is always implicitly supported by all keys).
|
|
18075
|
+
* if no keys are available, `preferredSenderAlgo` is returned.
|
|
18076
|
+
* For ECC signing key, the curve preferred hash is taken into account as well (see logic below).
|
|
18077
|
+
*/
|
|
18078
|
+
const defaultAlgo = enums.hash.sha256; // MUST implement
|
|
18079
|
+
const preferredSenderAlgo = config.preferredHashAlgorithm;
|
|
18080
|
+
|
|
18081
|
+
const supportedAlgosPerTarget = await Promise.all(targetKeys.map(async (key, i) => {
|
|
18082
|
+
const selfCertification = await key.getPrimarySelfSignature(date, targetUserIDs[i], config);
|
|
18083
|
+
const targetPrefs = selfCertification.preferredHashAlgorithms;
|
|
18084
|
+
return targetPrefs;
|
|
18085
|
+
}));
|
|
18086
|
+
const supportedAlgosMap = new Map(); // use Map over object to preserve numeric keys
|
|
18087
|
+
for (const supportedAlgos of supportedAlgosPerTarget) {
|
|
18088
|
+
for (const hashAlgo of supportedAlgos) {
|
|
18089
|
+
try {
|
|
18090
|
+
// ensure that `hashAlgo` is recognized/implemented by us, otherwise e.g. `getHashByteLength` will throw later on
|
|
18091
|
+
const supportedAlgo = enums.write(enums.hash, hashAlgo);
|
|
18092
|
+
supportedAlgosMap.set(
|
|
18093
|
+
supportedAlgo,
|
|
18094
|
+
supportedAlgosMap.has(supportedAlgo) ? supportedAlgosMap.get(supportedAlgo) + 1 : 1
|
|
18095
|
+
);
|
|
18096
|
+
} catch {}
|
|
18916
18097
|
}
|
|
18917
18098
|
}
|
|
18918
|
-
|
|
18919
|
-
|
|
18920
|
-
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18099
|
+
const isSupportedHashAlgo = hashAlgo => targetKeys.length === 0 || supportedAlgosMap.get(hashAlgo) === targetKeys.length || hashAlgo === defaultAlgo;
|
|
18100
|
+
const getStrongestSupportedHashAlgo = () => {
|
|
18101
|
+
if (supportedAlgosMap.size === 0) {
|
|
18102
|
+
return defaultAlgo;
|
|
18103
|
+
}
|
|
18104
|
+
const sortedHashAlgos = Array.from(supportedAlgosMap.keys())
|
|
18105
|
+
.filter(hashAlgo => isSupportedHashAlgo(hashAlgo))
|
|
18106
|
+
.sort((algoA, algoB) => mod.hash.getHashByteLength(algoA) - mod.hash.getHashByteLength(algoB));
|
|
18107
|
+
const strongestHashAlgo = sortedHashAlgos[0];
|
|
18108
|
+
// defaultAlgo is always implicilty supported, and might be stronger than the rest
|
|
18109
|
+
return mod.hash.getHashByteLength(strongestHashAlgo) >= mod.hash.getHashByteLength(defaultAlgo) ? strongestHashAlgo : defaultAlgo;
|
|
18110
|
+
};
|
|
18111
|
+
|
|
18112
|
+
const eccAlgos = new Set([
|
|
18113
|
+
enums.publicKey.ecdsa,
|
|
18114
|
+
enums.publicKey.eddsaLegacy,
|
|
18115
|
+
enums.publicKey.ed25519,
|
|
18116
|
+
enums.publicKey.ed448
|
|
18117
|
+
]);
|
|
18118
|
+
|
|
18119
|
+
if (eccAlgos.has(signingKeyPacket.algorithm)) {
|
|
18120
|
+
// For ECC, the returned hash algo MUST be at least as strong as `preferredCurveHashAlgo`, see:
|
|
18121
|
+
// - ECDSA: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.2-5
|
|
18122
|
+
// - EdDSALegacy: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
18123
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
18124
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
18125
|
+
// Hence, we return the `preferredHashAlgo` as long as it's supported and strong enough;
|
|
18126
|
+
// Otherwise, we look at the strongest supported algo, and ultimately fallback to the curve
|
|
18127
|
+
// preferred algo, even if not supported by all targets.
|
|
18128
|
+
const preferredCurveAlgo = mod.getPreferredCurveHashAlgo(signingKeyPacket.algorithm, signingKeyPacket.publicParams.oid);
|
|
18129
|
+
|
|
18130
|
+
const preferredSenderAlgoIsSupported = isSupportedHashAlgo(preferredSenderAlgo);
|
|
18131
|
+
const preferredSenderAlgoStrongerThanCurveAlgo = mod.hash.getHashByteLength(preferredSenderAlgo) >= mod.hash.getHashByteLength(preferredCurveAlgo);
|
|
18132
|
+
|
|
18133
|
+
if (preferredSenderAlgoIsSupported && preferredSenderAlgoStrongerThanCurveAlgo) {
|
|
18134
|
+
return preferredSenderAlgo;
|
|
18135
|
+
} else {
|
|
18136
|
+
const strongestSupportedAlgo = getStrongestSupportedHashAlgo();
|
|
18137
|
+
return mod.hash.getHashByteLength(strongestSupportedAlgo) >= mod.hash.getHashByteLength(preferredCurveAlgo) ?
|
|
18138
|
+
strongestSupportedAlgo :
|
|
18139
|
+
preferredCurveAlgo;
|
|
18140
|
+
}
|
|
18924
18141
|
}
|
|
18925
18142
|
|
|
18926
|
-
|
|
18927
|
-
|
|
18143
|
+
// `preferredSenderAlgo` may be weaker than the default, but we do not guard against this,
|
|
18144
|
+
// since it was manually set by the sender.
|
|
18145
|
+
return isSupportedHashAlgo(preferredSenderAlgo) ? preferredSenderAlgo : getStrongestSupportedHashAlgo();
|
|
18928
18146
|
}
|
|
18929
18147
|
|
|
18930
18148
|
/**
|
|
@@ -18995,7 +18213,7 @@ async function getPreferredCipherSuite(keys = [], date = new Date(), userIDs = [
|
|
|
18995
18213
|
/**
|
|
18996
18214
|
* Create signature packet
|
|
18997
18215
|
* @param {Object} dataToSign - Contains packets to be signed
|
|
18998
|
-
* @param {
|
|
18216
|
+
* @param {Array<Key>} recipientKeys - keys to get preferences from
|
|
18999
18217
|
* @param {SecretKeyPacket|
|
|
19000
18218
|
* SecretSubkeyPacket} signingKeyPacket secret key packet for signing
|
|
19001
18219
|
* @param {Object} [signatureProperties] - Properties to write on the signature packet before signing
|
|
@@ -19006,7 +18224,7 @@ async function getPreferredCipherSuite(keys = [], date = new Date(), userIDs = [
|
|
|
19006
18224
|
* @param {Object} config - full configuration
|
|
19007
18225
|
* @returns {Promise<SignaturePacket>} Signature packet.
|
|
19008
18226
|
*/
|
|
19009
|
-
async function createSignaturePacket(dataToSign,
|
|
18227
|
+
async function createSignaturePacket(dataToSign, recipientKeys, signingKeyPacket, signatureProperties, date, recipientUserIDs, notations = [], detached = false, config) {
|
|
19010
18228
|
if (signingKeyPacket.isDummy()) {
|
|
19011
18229
|
throw new Error('Cannot sign with a gnu-dummy key.');
|
|
19012
18230
|
}
|
|
@@ -19016,7 +18234,7 @@ async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, s
|
|
|
19016
18234
|
const signaturePacket = new SignaturePacket();
|
|
19017
18235
|
Object.assign(signaturePacket, signatureProperties);
|
|
19018
18236
|
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
|
19019
|
-
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(
|
|
18237
|
+
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(recipientKeys, signingKeyPacket, date, recipientUserIDs, config);
|
|
19020
18238
|
signaturePacket.rawNotations = [...notations];
|
|
19021
18239
|
await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached, config);
|
|
19022
18240
|
return signaturePacket;
|
|
@@ -19353,7 +18571,7 @@ class User {
|
|
|
19353
18571
|
throw new Error("The user's own key can only be used for self-certifications");
|
|
19354
18572
|
}
|
|
19355
18573
|
const signingKey = await privateKey.getSigningKey(undefined, date, undefined, config);
|
|
19356
|
-
return createSignaturePacket(dataToSign, privateKey, signingKey.keyPacket, {
|
|
18574
|
+
return createSignaturePacket(dataToSign, [privateKey], signingKey.keyPacket, {
|
|
19357
18575
|
// Most OpenPGP implementations use generic certification (0x10)
|
|
19358
18576
|
signatureType: enums.signature.certGeneric,
|
|
19359
18577
|
keyFlags: [enums.keyFlags.certifyKeys | enums.keyFlags.signData]
|
|
@@ -19541,7 +18759,7 @@ class User {
|
|
|
19541
18759
|
key: primaryKey
|
|
19542
18760
|
};
|
|
19543
18761
|
const user = new User(dataToSign.userID || dataToSign.userAttribute, this.mainKey);
|
|
19544
|
-
user.revocationSignatures.push(await createSignaturePacket(dataToSign,
|
|
18762
|
+
user.revocationSignatures.push(await createSignaturePacket(dataToSign, [], primaryKey, {
|
|
19545
18763
|
signatureType: enums.signature.certRevocation,
|
|
19546
18764
|
reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag),
|
|
19547
18765
|
reasonForRevocationString
|
|
@@ -19734,7 +18952,7 @@ class Subkey {
|
|
|
19734
18952
|
) {
|
|
19735
18953
|
const dataToSign = { key: primaryKey, bind: this.keyPacket };
|
|
19736
18954
|
const subkey = new Subkey(this.keyPacket, this.mainKey);
|
|
19737
|
-
subkey.revocationSignatures.push(await createSignaturePacket(dataToSign,
|
|
18955
|
+
subkey.revocationSignatures.push(await createSignaturePacket(dataToSign, [], primaryKey, {
|
|
19738
18956
|
signatureType: enums.signature.subkeyRevocation,
|
|
19739
18957
|
reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag),
|
|
19740
18958
|
reasonForRevocationString
|
|
@@ -20767,7 +19985,7 @@ class PrivateKey extends PublicKey {
|
|
|
20767
19985
|
}
|
|
20768
19986
|
const dataToSign = { key: this.keyPacket };
|
|
20769
19987
|
const key = this.clone();
|
|
20770
|
-
key.revocationSignatures.push(await createSignaturePacket(dataToSign,
|
|
19988
|
+
key.revocationSignatures.push(await createSignaturePacket(dataToSign, [], this.keyPacket, {
|
|
20771
19989
|
signatureType: enums.signature.keyRevocation,
|
|
20772
19990
|
reasonForRevocationFlag: enums.write(enums.reasonForRevocation, reasonForRevocationFlag),
|
|
20773
19991
|
reasonForRevocationString
|
|
@@ -21080,7 +20298,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, conf
|
|
|
21080
20298
|
const signatureProperties = getKeySignatureProperties();
|
|
21081
20299
|
signatureProperties.signatureType = enums.signature.key;
|
|
21082
20300
|
|
|
21083
|
-
const signaturePacket = await createSignaturePacket(dataToSign,
|
|
20301
|
+
const signaturePacket = await createSignaturePacket(dataToSign, [], secretKeyPacket, signatureProperties, options.date, undefined, undefined, undefined, config);
|
|
21084
20302
|
packetlist.push(signaturePacket);
|
|
21085
20303
|
}
|
|
21086
20304
|
|
|
@@ -21096,7 +20314,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, conf
|
|
|
21096
20314
|
signatureProperties.isPrimaryUserID = true;
|
|
21097
20315
|
}
|
|
21098
20316
|
|
|
21099
|
-
const signaturePacket = await createSignaturePacket(dataToSign,
|
|
20317
|
+
const signaturePacket = await createSignaturePacket(dataToSign, [], secretKeyPacket, signatureProperties, options.date, undefined, undefined, undefined, config);
|
|
21100
20318
|
|
|
21101
20319
|
return { userIDPacket, signaturePacket };
|
|
21102
20320
|
})).then(list => {
|
|
@@ -21120,7 +20338,7 @@ async function wrapKeyObject(secretKeyPacket, secretSubkeyPackets, options, conf
|
|
|
21120
20338
|
// Add revocation signature packet for creating a revocation certificate.
|
|
21121
20339
|
// This packet should be removed before returning the key.
|
|
21122
20340
|
const dataToSign = { key: secretKeyPacket };
|
|
21123
|
-
packetlist.push(await createSignaturePacket(dataToSign,
|
|
20341
|
+
packetlist.push(await createSignaturePacket(dataToSign, [], secretKeyPacket, {
|
|
21124
20342
|
signatureType: enums.signature.keyRevocation,
|
|
21125
20343
|
reasonForRevocationFlag: enums.reasonForRevocation.noReason,
|
|
21126
20344
|
reasonForRevocationString: ''
|
|
@@ -21795,16 +21013,18 @@ class Message {
|
|
|
21795
21013
|
/**
|
|
21796
21014
|
* Sign the message (the literal data packet of the message)
|
|
21797
21015
|
* @param {Array<PrivateKey>} signingKeys - private keys with decrypted secret key data for signing
|
|
21016
|
+
* @param {Array<Key>} recipientKeys - recipient keys to get the signing preferences from
|
|
21798
21017
|
* @param {Signature} [signature] - Any existing detached signature to add to the message
|
|
21799
21018
|
* @param {Array<module:type/keyid~KeyID>} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i]
|
|
21800
21019
|
* @param {Date} [date] - Override the creation time of the signature
|
|
21801
|
-
* @param {Array} [
|
|
21020
|
+
* @param {Array<UserID>} [signingUserIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
|
21021
|
+
* @param {Array<UserID>} [recipientUserIDs] - User IDs associated with `recipientKeys` to get the signing preferences from
|
|
21802
21022
|
* @param {Array} [notations] - Notation Data to add to the signatures, e.g. [{ name: 'test@example.org', value: new TextEncoder().encode('test'), humanReadable: true, critical: false }]
|
|
21803
21023
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
21804
21024
|
* @returns {Promise<Message>} New message with signed content.
|
|
21805
21025
|
* @async
|
|
21806
21026
|
*/
|
|
21807
|
-
async sign(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(),
|
|
21027
|
+
async sign(signingKeys = [], recipientKeys = [], signature = null, signingKeyIDs = [], date = new Date(), signingUserIDs = [], recipientUserIDs = [], notations = [], config$1 = config) {
|
|
21808
21028
|
const packetlist = new PacketList();
|
|
21809
21029
|
|
|
21810
21030
|
const literalDataPacket = this.packets.findPacket(enums.packet.literalData);
|
|
@@ -21812,7 +21032,7 @@ class Message {
|
|
|
21812
21032
|
throw new Error('No literal data packet to sign.');
|
|
21813
21033
|
}
|
|
21814
21034
|
|
|
21815
|
-
const signaturePackets = await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date,
|
|
21035
|
+
const signaturePackets = await createSignaturePackets(literalDataPacket, signingKeys, recipientKeys, signature, signingKeyIDs, date, signingUserIDs, recipientUserIDs, notations, false, config$1); // this returns the existing signature packets as well
|
|
21816
21036
|
const onePassSignaturePackets = signaturePackets.map(
|
|
21817
21037
|
(signaturePacket, i) => OnePassSignaturePacket.fromSignaturePacket(signaturePacket, i === 0))
|
|
21818
21038
|
.reverse(); // innermost OPS refers to the first signature packet
|
|
@@ -21848,21 +21068,23 @@ class Message {
|
|
|
21848
21068
|
/**
|
|
21849
21069
|
* Create a detached signature for the message (the literal data packet of the message)
|
|
21850
21070
|
* @param {Array<PrivateKey>} signingKeys - private keys with decrypted secret key data for signing
|
|
21071
|
+
* @param {Array<Key>} recipientKeys - recipient keys to get the signing preferences from
|
|
21851
21072
|
* @param {Signature} [signature] - Any existing detached signature
|
|
21852
21073
|
* @param {Array<module:type/keyid~KeyID>} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i]
|
|
21853
21074
|
* @param {Date} [date] - Override the creation time of the signature
|
|
21854
|
-
* @param {Array} [
|
|
21075
|
+
* @param {Array<UserID>} [signingUserIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
|
21076
|
+
* @param {Array<UserID>} [recipientUserIDs] - User IDs associated with `recipientKeys` to get the signing preferences from
|
|
21855
21077
|
* @param {Array} [notations] - Notation Data to add to the signatures, e.g. [{ name: 'test@example.org', value: new TextEncoder().encode('test'), humanReadable: true, critical: false }]
|
|
21856
21078
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
21857
21079
|
* @returns {Promise<Signature>} New detached signature of message content.
|
|
21858
21080
|
* @async
|
|
21859
21081
|
*/
|
|
21860
|
-
async signDetached(signingKeys = [], signature = null, signingKeyIDs = [], date = new Date(), userIDs = [], notations = [], config$1 = config) {
|
|
21082
|
+
async signDetached(signingKeys = [], recipientKeys = [], signature = null, signingKeyIDs = [], recipientKeyIDs = [], date = new Date(), userIDs = [], notations = [], config$1 = config) {
|
|
21861
21083
|
const literalDataPacket = this.packets.findPacket(enums.packet.literalData);
|
|
21862
21084
|
if (!literalDataPacket) {
|
|
21863
21085
|
throw new Error('No literal data packet to sign.');
|
|
21864
21086
|
}
|
|
21865
|
-
return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, signature, signingKeyIDs, date, userIDs, notations, true, config$1));
|
|
21087
|
+
return new Signature(await createSignaturePackets(literalDataPacket, signingKeys, recipientKeys, signature, signingKeyIDs, recipientKeyIDs, date, userIDs, notations, true, config$1));
|
|
21866
21088
|
}
|
|
21867
21089
|
|
|
21868
21090
|
/**
|
|
@@ -21997,10 +21219,12 @@ class Message {
|
|
|
21997
21219
|
* Create signature packets for the message
|
|
21998
21220
|
* @param {LiteralDataPacket} literalDataPacket - the literal data packet to sign
|
|
21999
21221
|
* @param {Array<PrivateKey>} [signingKeys] - private keys with decrypted secret key data for signing
|
|
21222
|
+
* @param {Array<Key>} [recipientKeys] - recipient keys to get the signing preferences from
|
|
22000
21223
|
* @param {Signature} [signature] - Any existing detached signature to append
|
|
22001
21224
|
* @param {Array<module:type/keyid~KeyID>} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i]
|
|
22002
21225
|
* @param {Date} [date] - Override the creationtime of the signature
|
|
22003
|
-
* @param {Array} [
|
|
21226
|
+
* @param {Array<UserID>} [signingUserIDs] - User IDs to sign to, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
|
21227
|
+
* @param {Array<UserID>} [recipientUserIDs] - User IDs associated with `recipientKeys` to get the signing preferences from
|
|
22004
21228
|
* @param {Array} [notations] - Notation Data to add to the signatures, e.g. [{ name: 'test@example.org', value: new TextEncoder().encode('test'), humanReadable: true, critical: false }]
|
|
22005
21229
|
* @param {Array} [signatureSalts] - A list of signature salts matching the number of signingKeys that should be used for v6 signatures
|
|
22006
21230
|
* @param {Boolean} [detached] - Whether to create detached signature packets
|
|
@@ -22009,7 +21233,7 @@ class Message {
|
|
|
22009
21233
|
* @async
|
|
22010
21234
|
* @private
|
|
22011
21235
|
*/
|
|
22012
|
-
async function createSignaturePackets(literalDataPacket, signingKeys, signature = null, signingKeyIDs = [], date = new Date(),
|
|
21236
|
+
async function createSignaturePackets(literalDataPacket, signingKeys, recipientKeys = [], signature = null, signingKeyIDs = [], date = new Date(), signingUserIDs = [], recipientUserIDs = [], notations = [], detached = false, config$1 = config) {
|
|
22013
21237
|
const packetlist = new PacketList();
|
|
22014
21238
|
|
|
22015
21239
|
// If data packet was created from Uint8Array, use binary, otherwise use text
|
|
@@ -22017,12 +21241,12 @@ async function createSignaturePackets(literalDataPacket, signingKeys, signature
|
|
|
22017
21241
|
enums.signature.binary : enums.signature.text;
|
|
22018
21242
|
|
|
22019
21243
|
await Promise.all(signingKeys.map(async (primaryKey, i) => {
|
|
22020
|
-
const
|
|
21244
|
+
const signingUserID = signingUserIDs[i];
|
|
22021
21245
|
if (!primaryKey.isPrivate()) {
|
|
22022
21246
|
throw new Error('Need private key for signing');
|
|
22023
21247
|
}
|
|
22024
|
-
const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date,
|
|
22025
|
-
return createSignaturePacket(literalDataPacket, primaryKey, signingKey.keyPacket, { signatureType }, date,
|
|
21248
|
+
const signingKey = await primaryKey.getSigningKey(signingKeyIDs[i], date, signingUserID, config$1);
|
|
21249
|
+
return createSignaturePacket(literalDataPacket, recipientKeys.length ? recipientKeys : [primaryKey], signingKey.keyPacket, { signatureType }, date, recipientUserIDs, notations, detached, config$1);
|
|
22026
21250
|
})).then(signatureList => {
|
|
22027
21251
|
packetlist.push(...signatureList);
|
|
22028
21252
|
});
|
|
@@ -22272,20 +21496,22 @@ class CleartextMessage {
|
|
|
22272
21496
|
|
|
22273
21497
|
/**
|
|
22274
21498
|
* Sign the cleartext message
|
|
22275
|
-
* @param {Array<Key>}
|
|
21499
|
+
* @param {Array<Key>} signingKeys - private keys with decrypted secret key data for signing
|
|
21500
|
+
* @param {Array<Key>} recipientKeys - recipient keys to get the signing preferences from
|
|
22276
21501
|
* @param {Signature} [signature] - Any existing detached signature
|
|
22277
21502
|
* @param {Array<module:type/keyid~KeyID>} [signingKeyIDs] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to privateKeys[i]
|
|
22278
21503
|
* @param {Date} [date] - The creation time of the signature that should be created
|
|
22279
|
-
* @param {Array} [
|
|
21504
|
+
* @param {Array} [signingKeyIDs] - User IDs to sign with, e.g. [{ name:'Steve Sender', email:'steve@openpgp.org' }]
|
|
21505
|
+
* @param {Array} [recipientUserIDs] - User IDs associated with `recipientKeys` to get the signing preferences from
|
|
22280
21506
|
* @param {Array} [notations] - Notation Data to add to the signatures, e.g. [{ name: 'test@example.org', value: new TextEncoder().encode('test'), humanReadable: true, critical: false }]
|
|
22281
21507
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
22282
21508
|
* @returns {Promise<CleartextMessage>} New cleartext message with signed content.
|
|
22283
21509
|
* @async
|
|
22284
21510
|
*/
|
|
22285
|
-
async sign(
|
|
21511
|
+
async sign(signingKeys, recipientKeys = [], signature = null, signingKeyIDs = [], date = new Date(), signingUserIDs = [], recipientUserIDs = [], notations = [], config$1 = config) {
|
|
22286
21512
|
const literalDataPacket = new LiteralDataPacket();
|
|
22287
21513
|
literalDataPacket.setText(this.text);
|
|
22288
|
-
const newSignature = new Signature(await createSignaturePackets(literalDataPacket,
|
|
21514
|
+
const newSignature = new Signature(await createSignaturePackets(literalDataPacket, signingKeys, recipientKeys, signature, signingKeyIDs, date, signingUserIDs, recipientUserIDs, notations, true, config$1));
|
|
22289
21515
|
return new CleartextMessage(this.text, newSignature);
|
|
22290
21516
|
}
|
|
22291
21517
|
|
|
@@ -22721,7 +21947,7 @@ async function encrypt({ message, encryptionKeys, signingKeys, passwords, sessio
|
|
|
22721
21947
|
|
|
22722
21948
|
try {
|
|
22723
21949
|
if (signingKeys.length || signature) { // sign the message only if signing keys or signature is specified
|
|
22724
|
-
message = await message.sign(signingKeys, signature, signingKeyIDs, date, signingUserIDs, signatureNotations, config$1);
|
|
21950
|
+
message = await message.sign(signingKeys, encryptionKeys, signature, signingKeyIDs, date, signingUserIDs, encryptionKeyIDs, signatureNotations, config$1);
|
|
22725
21951
|
}
|
|
22726
21952
|
message = message.compress(
|
|
22727
21953
|
await getPreferredCompressionAlgo(encryptionKeys, date, encryptionUserIDs, config$1),
|
|
@@ -22823,21 +22049,23 @@ async function decrypt({ message, decryptionKeys, passwords, sessionKeys, verifi
|
|
|
22823
22049
|
* @param {Object} options
|
|
22824
22050
|
* @param {CleartextMessage|Message} options.message - (cleartext) message to be signed
|
|
22825
22051
|
* @param {PrivateKey|PrivateKey[]} options.signingKeys - Array of keys or single key with decrypted secret key data to sign cleartext
|
|
22052
|
+
* @param {Key|Key[]} options.recipientKeys - Array of keys or single to get the signing preferences from
|
|
22826
22053
|
* @param {'armored'|'binary'|'object'} [options.format='armored'] - Format of the returned message
|
|
22827
22054
|
* @param {Boolean} [options.detached=false] - If the return value should contain a detached signature
|
|
22828
22055
|
* @param {KeyID|KeyID[]} [options.signingKeyIDs=latest-created valid signing (sub)keys] - Array of key IDs to use for signing. Each signingKeyIDs[i] corresponds to signingKeys[i]
|
|
22829
22056
|
* @param {Date} [options.date=current date] - Override the creation date of the signature
|
|
22830
22057
|
* @param {Object|Object[]} [options.signingUserIDs=primary user IDs] - Array of user IDs to sign with, one per key in `signingKeys`, e.g. `[{ name: 'Steve Sender', email: 'steve@openpgp.org' }]`
|
|
22058
|
+
* @param {Object|Object[]} [options.recipientUserIDs=primary user IDs] - Array of user IDs to get the signing preferences from, one per key in `recipientKeys`
|
|
22831
22059
|
* @param {Object|Object[]} [options.signatureNotations=[]] - Array of notations to add to the signatures, e.g. `[{ name: 'test@example.org', value: new TextEncoder().encode('test'), humanReadable: true, critical: false }]`
|
|
22832
22060
|
* @param {Object} [options.config] - Custom configuration settings to overwrite those in [config]{@link module:config}
|
|
22833
22061
|
* @returns {Promise<MaybeStream<String|Uint8Array>>} Signed message (string if `armor` was true, the default; Uint8Array if `armor` was false).
|
|
22834
22062
|
* @async
|
|
22835
22063
|
* @static
|
|
22836
22064
|
*/
|
|
22837
|
-
async function sign({ message, signingKeys, format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], signatureNotations = [], config: config$1, ...rest }) {
|
|
22065
|
+
async function sign({ message, signingKeys, recipientKeys = [], format = 'armored', detached = false, signingKeyIDs = [], date = new Date(), signingUserIDs = [], recipientUserIDs = [], signatureNotations = [], config: config$1, ...rest }) {
|
|
22838
22066
|
config$1 = { ...config, ...config$1 }; checkConfig(config$1);
|
|
22839
22067
|
checkCleartextOrMessage(message); checkOutputMessageFormat(format);
|
|
22840
|
-
signingKeys = toArray(signingKeys); signingKeyIDs = toArray(signingKeyIDs); signingUserIDs = toArray(signingUserIDs); signatureNotations = toArray(signatureNotations);
|
|
22068
|
+
signingKeys = toArray(signingKeys); signingKeyIDs = toArray(signingKeyIDs); signingUserIDs = toArray(signingUserIDs); recipientKeys = toArray(recipientKeys); recipientUserIDs = toArray(recipientUserIDs); signatureNotations = toArray(signatureNotations);
|
|
22841
22069
|
|
|
22842
22070
|
if (rest.privateKeys) throw new Error('The `privateKeys` option has been removed from openpgp.sign, pass `signingKeys` instead');
|
|
22843
22071
|
if (rest.armor !== undefined) throw new Error('The `armor` option has been removed from openpgp.sign, pass `format` instead.');
|
|
@@ -22853,9 +22081,9 @@ async function sign({ message, signingKeys, format = 'armored', detached = false
|
|
|
22853
22081
|
try {
|
|
22854
22082
|
let signature;
|
|
22855
22083
|
if (detached) {
|
|
22856
|
-
signature = await message.signDetached(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, signatureNotations, config$1);
|
|
22084
|
+
signature = await message.signDetached(signingKeys, recipientKeys, undefined, signingKeyIDs, date, signingUserIDs, recipientUserIDs, signatureNotations, config$1);
|
|
22857
22085
|
} else {
|
|
22858
|
-
signature = await message.sign(signingKeys, undefined, signingKeyIDs, date, signingUserIDs, signatureNotations, config$1);
|
|
22086
|
+
signature = await message.sign(signingKeys, recipientKeys, undefined, signingKeyIDs, date, signingUserIDs, recipientUserIDs, signatureNotations, config$1);
|
|
22859
22087
|
}
|
|
22860
22088
|
if (format === 'object') return signature;
|
|
22861
22089
|
|