@protontech/openpgp 6.0.0-alpha.1.patch.0 → 6.0.0-beta.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/dist/lightweight/argon2id.min.mjs +1 -1
- package/dist/lightweight/argon2id.mjs +1 -1
- package/dist/lightweight/bn.interface.min.mjs +2 -2
- package/dist/lightweight/bn.interface.min.mjs.map +1 -1
- package/dist/lightweight/bn.interface.mjs +1 -1
- package/dist/lightweight/interface.min.mjs +1 -1
- package/dist/lightweight/interface.mjs +1 -1
- package/dist/lightweight/legacy_ciphers.min.mjs +1 -1
- package/dist/lightweight/legacy_ciphers.mjs +1 -1
- package/dist/lightweight/native.interface.min.mjs +1 -1
- package/dist/lightweight/native.interface.mjs +1 -1
- package/dist/lightweight/noble_curves.min.mjs +3 -3
- 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.mjs +1 -1
- package/dist/lightweight/openpgp.min.mjs +2 -2
- package/dist/lightweight/openpgp.min.mjs.map +1 -1
- package/dist/lightweight/openpgp.mjs +203 -83
- package/dist/lightweight/sha3.min.mjs +2 -2
- package/dist/lightweight/sha3.min.mjs.map +1 -1
- package/dist/lightweight/sha3.mjs +1 -1
- package/dist/node/openpgp.cjs +203 -83
- package/dist/node/openpgp.min.cjs +11 -11
- package/dist/node/openpgp.min.cjs.map +1 -1
- package/dist/node/openpgp.min.mjs +11 -11
- package/dist/node/openpgp.min.mjs.map +1 -1
- package/dist/node/openpgp.mjs +203 -83
- package/dist/openpgp.js +203 -83
- package/dist/openpgp.min.js +11 -11
- package/dist/openpgp.min.js.map +1 -1
- package/dist/openpgp.min.mjs +11 -11
- package/dist/openpgp.min.mjs.map +1 -1
- package/dist/openpgp.mjs +203 -83
- package/openpgp.d.ts +4 -3
- package/package.json +9 -9
package/dist/node/openpgp.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! OpenPGP.js v6.0.0-
|
|
1
|
+
/*! OpenPGP.js v6.0.0-beta.0 - 2024-04-18 - 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
|
import { createRequire } from 'module';
|
|
@@ -1580,11 +1580,6 @@ var config = {
|
|
|
1580
1580
|
* @property {Boolean} passwordCollisionCheck
|
|
1581
1581
|
*/
|
|
1582
1582
|
passwordCollisionCheck: false,
|
|
1583
|
-
/**
|
|
1584
|
-
* @memberof module:config
|
|
1585
|
-
* @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored
|
|
1586
|
-
*/
|
|
1587
|
-
revocationsExpire: false,
|
|
1588
1583
|
/**
|
|
1589
1584
|
* Allow decryption using RSA keys without `encrypt` flag.
|
|
1590
1585
|
* This setting is potentially insecure, but it is needed to get around an old openpgpjs bug
|
|
@@ -1660,7 +1655,7 @@ var config = {
|
|
|
1660
1655
|
* @memberof module:config
|
|
1661
1656
|
* @property {String} versionString A version string to be included in armored messages
|
|
1662
1657
|
*/
|
|
1663
|
-
versionString: 'OpenPGP.js 6.0.0-
|
|
1658
|
+
versionString: 'OpenPGP.js 6.0.0-beta.0',
|
|
1664
1659
|
/**
|
|
1665
1660
|
* @memberof module:config
|
|
1666
1661
|
* @property {String} commentString A comment string to be included in armored messages
|
|
@@ -1680,6 +1675,14 @@ var config = {
|
|
|
1680
1675
|
* @property {Array} knownNotations
|
|
1681
1676
|
*/
|
|
1682
1677
|
knownNotations: [],
|
|
1678
|
+
/**
|
|
1679
|
+
* If true, a salt notation is used to randomize signatures generated by v4 and v5 keys (v6 signatures are always non-deterministic, by design).
|
|
1680
|
+
* This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
|
|
1681
|
+
* during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of
|
|
1682
|
+
* weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
|
|
1683
|
+
* NOTE: the notation is interoperable, but will reveal that the signature has been generated using OpenPGP.js, which may not be desirable in some cases.
|
|
1684
|
+
*/
|
|
1685
|
+
nonDeterministicSignaturesViaNotation: true,
|
|
1683
1686
|
/**
|
|
1684
1687
|
* Whether to use the the noble-curves library for curves (other than Curve25519) that are not supported by the available native crypto API.
|
|
1685
1688
|
* When false, certain standard curves will not be supported (depending on the platform).
|
|
@@ -1710,14 +1713,7 @@ var config = {
|
|
|
1710
1713
|
* @memberof module:config
|
|
1711
1714
|
* @property {Set<String>} rejectCurves {@link module:enums.curve}
|
|
1712
1715
|
*/
|
|
1713
|
-
rejectCurves: new Set([enums.curve.secp256k1])
|
|
1714
|
-
/**
|
|
1715
|
-
* Whether to validate generated EdDSA signatures before returning them, to ensure they are not faulty signatures.
|
|
1716
|
-
* This check will make signing 2-3 times slower.
|
|
1717
|
-
* Faulty signatures may be generated (in principle) if random bitflips occur at specific points in the signature
|
|
1718
|
-
* computation, and could be used to recover the signer's secret key given a second signature over the same data.
|
|
1719
|
-
*/
|
|
1720
|
-
checkEdDSAFaultySignatures: true
|
|
1716
|
+
rejectCurves: new Set([enums.curve.secp256k1])
|
|
1721
1717
|
};
|
|
1722
1718
|
|
|
1723
1719
|
/**
|
|
@@ -2202,16 +2198,19 @@ const util = {
|
|
|
2202
2198
|
},
|
|
2203
2199
|
|
|
2204
2200
|
/**
|
|
2205
|
-
* Test email format
|
|
2206
|
-
*
|
|
2207
|
-
*
|
|
2208
|
-
*
|
|
2201
|
+
* Test email format to ensure basic compliance:
|
|
2202
|
+
* - must include a single @
|
|
2203
|
+
* - no control or space unicode chars allowed
|
|
2204
|
+
* - no backslash and square brackets (as the latter can mess with the userID parsing)
|
|
2205
|
+
* - cannot end with a punctuation char
|
|
2206
|
+
* These checks are not meant to be exhaustive; applications are strongly encouraged to implement stricter validation,
|
|
2207
|
+
* e.g. based on the W3C HTML spec (https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email)).
|
|
2209
2208
|
*/
|
|
2210
2209
|
isEmailAddress: function(data) {
|
|
2211
2210
|
if (!util.isString(data)) {
|
|
2212
2211
|
return false;
|
|
2213
2212
|
}
|
|
2214
|
-
const re = /^[
|
|
2213
|
+
const re = /^[^\p{C}\p{Z}@<>\\]+@[^\p{C}\p{Z}@<>\\]+[^\p{C}\p{Z}\p{P}]$/u;
|
|
2215
2214
|
return re.test(data);
|
|
2216
2215
|
},
|
|
2217
2216
|
|
|
@@ -2617,6 +2616,78 @@ function addheader(customComment, config) {
|
|
|
2617
2616
|
return result;
|
|
2618
2617
|
}
|
|
2619
2618
|
|
|
2619
|
+
/**
|
|
2620
|
+
* Calculates a checksum over the given data and returns it base64 encoded
|
|
2621
|
+
* @param {String | ReadableStream<String>} data - Data to create a CRC-24 checksum for
|
|
2622
|
+
* @returns {String | ReadableStream<String>} Base64 encoded checksum.
|
|
2623
|
+
* @private
|
|
2624
|
+
*/
|
|
2625
|
+
function getCheckSum(data) {
|
|
2626
|
+
const crc = createcrc24(data);
|
|
2627
|
+
return encode$1(crc);
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
// https://create.stephan-brumme.com/crc32/#slicing-by-8-overview
|
|
2631
|
+
|
|
2632
|
+
const crc_table = [
|
|
2633
|
+
new Array(0xFF),
|
|
2634
|
+
new Array(0xFF),
|
|
2635
|
+
new Array(0xFF),
|
|
2636
|
+
new Array(0xFF)
|
|
2637
|
+
];
|
|
2638
|
+
|
|
2639
|
+
for (let i = 0; i <= 0xFF; i++) {
|
|
2640
|
+
let crc = i << 16;
|
|
2641
|
+
for (let j = 0; j < 8; j++) {
|
|
2642
|
+
crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0);
|
|
2643
|
+
}
|
|
2644
|
+
crc_table[0][i] =
|
|
2645
|
+
((crc & 0xFF0000) >> 16) |
|
|
2646
|
+
(crc & 0x00FF00) |
|
|
2647
|
+
((crc & 0x0000FF) << 16);
|
|
2648
|
+
}
|
|
2649
|
+
for (let i = 0; i <= 0xFF; i++) {
|
|
2650
|
+
crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF];
|
|
2651
|
+
}
|
|
2652
|
+
for (let i = 0; i <= 0xFF; i++) {
|
|
2653
|
+
crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF];
|
|
2654
|
+
}
|
|
2655
|
+
for (let i = 0; i <= 0xFF; i++) {
|
|
2656
|
+
crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF];
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness
|
|
2660
|
+
const isLittleEndian$1 = (function() {
|
|
2661
|
+
const buffer = new ArrayBuffer(2);
|
|
2662
|
+
new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */);
|
|
2663
|
+
// Int16Array uses the platform's endianness.
|
|
2664
|
+
return new Int16Array(buffer)[0] === 0xFF;
|
|
2665
|
+
}());
|
|
2666
|
+
|
|
2667
|
+
/**
|
|
2668
|
+
* Internal function to calculate a CRC-24 checksum over a given string (data)
|
|
2669
|
+
* @param {String | ReadableStream<String>} input - Data to create a CRC-24 checksum for
|
|
2670
|
+
* @returns {Uint8Array | ReadableStream<Uint8Array>} The CRC-24 checksum.
|
|
2671
|
+
* @private
|
|
2672
|
+
*/
|
|
2673
|
+
function createcrc24(input) {
|
|
2674
|
+
let crc = 0xCE04B7;
|
|
2675
|
+
return transform(input, value => {
|
|
2676
|
+
const len32 = isLittleEndian$1 ? Math.floor(value.length / 4) : 0;
|
|
2677
|
+
const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32);
|
|
2678
|
+
for (let i = 0; i < len32; i++) {
|
|
2679
|
+
crc ^= arr32[i];
|
|
2680
|
+
crc =
|
|
2681
|
+
crc_table[0][(crc >> 24) & 0xFF] ^
|
|
2682
|
+
crc_table[1][(crc >> 16) & 0xFF] ^
|
|
2683
|
+
crc_table[2][(crc >> 8) & 0xFF] ^
|
|
2684
|
+
crc_table[3][(crc >> 0) & 0xFF];
|
|
2685
|
+
}
|
|
2686
|
+
for (let i = len32 * 4; i < value.length; i++) {
|
|
2687
|
+
crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]];
|
|
2688
|
+
}
|
|
2689
|
+
}, () => new Uint8Array([crc, crc >> 8, crc >> 16]));
|
|
2690
|
+
}
|
|
2620
2691
|
|
|
2621
2692
|
/**
|
|
2622
2693
|
* Verify armored headers. crypto-refresh-06, section 6.2:
|
|
@@ -2772,10 +2843,13 @@ function unarmor(input) {
|
|
|
2772
2843
|
* @param {Integer} [partIndex]
|
|
2773
2844
|
* @param {Integer} [partTotal]
|
|
2774
2845
|
* @param {String} [customComment] - Additional comment to add to the armored string
|
|
2846
|
+
* @param {Boolean} [emitChecksum] - Whether to compute and include the CRC checksum
|
|
2847
|
+
* (NB: some types of data must not include it, but compliance is left as responsibility of the caller: this function does not carry out any checks)
|
|
2848
|
+
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
2775
2849
|
* @returns {String | ReadableStream<String>} Armored text.
|
|
2776
2850
|
* @static
|
|
2777
2851
|
*/
|
|
2778
|
-
function armor(messageType, body, partIndex, partTotal, customComment, config$1 = config) {
|
|
2852
|
+
function armor(messageType, body, partIndex, partTotal, customComment, emitChecksum = false, config$1 = config) {
|
|
2779
2853
|
let text;
|
|
2780
2854
|
let hash;
|
|
2781
2855
|
if (messageType === enums.armor.signed) {
|
|
@@ -2783,18 +2857,24 @@ function armor(messageType, body, partIndex, partTotal, customComment, config$1
|
|
|
2783
2857
|
hash = body.hash;
|
|
2784
2858
|
body = body.data;
|
|
2785
2859
|
}
|
|
2860
|
+
// unless explicitly forbidden by the spec, we need to include the checksum to work around a GnuPG bug
|
|
2861
|
+
// where data fails to be decoded if the base64 ends with no padding chars (=) (see https://dev.gnupg.org/T7071)
|
|
2862
|
+
const maybeBodyClone = emitChecksum && passiveClone(body);
|
|
2863
|
+
|
|
2786
2864
|
const result = [];
|
|
2787
2865
|
switch (messageType) {
|
|
2788
2866
|
case enums.armor.multipartSection:
|
|
2789
2867
|
result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n');
|
|
2790
2868
|
result.push(addheader(customComment, config$1));
|
|
2791
2869
|
result.push(encode$1(body));
|
|
2870
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2792
2871
|
result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n');
|
|
2793
2872
|
break;
|
|
2794
2873
|
case enums.armor.multipartLast:
|
|
2795
2874
|
result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n');
|
|
2796
2875
|
result.push(addheader(customComment, config$1));
|
|
2797
2876
|
result.push(encode$1(body));
|
|
2877
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2798
2878
|
result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n');
|
|
2799
2879
|
break;
|
|
2800
2880
|
case enums.armor.signed:
|
|
@@ -2804,30 +2884,35 @@ function armor(messageType, body, partIndex, partTotal, customComment, config$1
|
|
|
2804
2884
|
result.push('\n-----BEGIN PGP SIGNATURE-----\n');
|
|
2805
2885
|
result.push(addheader(customComment, config$1));
|
|
2806
2886
|
result.push(encode$1(body));
|
|
2887
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2807
2888
|
result.push('-----END PGP SIGNATURE-----\n');
|
|
2808
2889
|
break;
|
|
2809
2890
|
case enums.armor.message:
|
|
2810
2891
|
result.push('-----BEGIN PGP MESSAGE-----\n');
|
|
2811
2892
|
result.push(addheader(customComment, config$1));
|
|
2812
2893
|
result.push(encode$1(body));
|
|
2894
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2813
2895
|
result.push('-----END PGP MESSAGE-----\n');
|
|
2814
2896
|
break;
|
|
2815
2897
|
case enums.armor.publicKey:
|
|
2816
2898
|
result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n');
|
|
2817
2899
|
result.push(addheader(customComment, config$1));
|
|
2818
2900
|
result.push(encode$1(body));
|
|
2901
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2819
2902
|
result.push('-----END PGP PUBLIC KEY BLOCK-----\n');
|
|
2820
2903
|
break;
|
|
2821
2904
|
case enums.armor.privateKey:
|
|
2822
2905
|
result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n');
|
|
2823
2906
|
result.push(addheader(customComment, config$1));
|
|
2824
2907
|
result.push(encode$1(body));
|
|
2908
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2825
2909
|
result.push('-----END PGP PRIVATE KEY BLOCK-----\n');
|
|
2826
2910
|
break;
|
|
2827
2911
|
case enums.armor.signature:
|
|
2828
2912
|
result.push('-----BEGIN PGP SIGNATURE-----\n');
|
|
2829
2913
|
result.push(addheader(customComment, config$1));
|
|
2830
2914
|
result.push(encode$1(body));
|
|
2915
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2831
2916
|
result.push('-----END PGP SIGNATURE-----\n');
|
|
2832
2917
|
break;
|
|
2833
2918
|
}
|
|
@@ -9355,20 +9440,6 @@ async function sign$5(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9355
9440
|
}
|
|
9356
9441
|
const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]);
|
|
9357
9442
|
const signature = nacl.sign.detached(hashed, secretKey);
|
|
9358
|
-
if (config.checkEdDSAFaultySignatures && !nacl.sign.detached.verify(hashed, signature, publicKey.subarray(1))) {
|
|
9359
|
-
/**
|
|
9360
|
-
* Detect faulty signatures caused by random bitflips during `crypto_sign` which could lead to private key extraction
|
|
9361
|
-
* if two signatures over the same message are obtained.
|
|
9362
|
-
* See https://github.com/jedisct1/libsodium/issues/170.
|
|
9363
|
-
* If the input data is not deterministic, e.g. thanks to the random salt in v6 OpenPGP signatures (not yet implemented),
|
|
9364
|
-
* then the generated signature is always safe, and the verification step is skipped.
|
|
9365
|
-
* Otherwise, we need to verify the generated to ensure that no bitflip occured:
|
|
9366
|
-
* - in M between the computation of `r` and `h`.
|
|
9367
|
-
* - in the public key before computing `h`
|
|
9368
|
-
* The verification step is almost 2-3 times as slow as signing, but it's faster than re-signing + re-deriving the public key for separate checks.
|
|
9369
|
-
*/
|
|
9370
|
-
throw new Error('Transient signing failure');
|
|
9371
|
-
}
|
|
9372
9443
|
// EdDSA signature params are returned in little-endian format
|
|
9373
9444
|
return {
|
|
9374
9445
|
r: signature.subarray(0, 32),
|
|
@@ -9489,20 +9560,6 @@ async function sign$4(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9489
9560
|
case enums.publicKey.ed25519: {
|
|
9490
9561
|
const secretKey = util.concatUint8Array([privateKey, publicKey]);
|
|
9491
9562
|
const signature = nacl.sign.detached(hashed, secretKey);
|
|
9492
|
-
if (config.checkEdDSAFaultySignatures && !nacl.sign.detached.verify(hashed, signature, publicKey)) {
|
|
9493
|
-
/**
|
|
9494
|
-
* Detect faulty signatures caused by random bitflips during `crypto_sign` which could lead to private key extraction
|
|
9495
|
-
* if two signatures over the same message are obtained.
|
|
9496
|
-
* See https://github.com/jedisct1/libsodium/issues/170.
|
|
9497
|
-
* If the input data is not deterministic, e.g. thanks to the random salt in v6 OpenPGP signatures (not yet implemented),
|
|
9498
|
-
* then the generated signature is always safe, and the verification step is skipped.
|
|
9499
|
-
* Otherwise, we need to verify the generated to ensure that no bitflip occured:
|
|
9500
|
-
* - in M between the computation of `r` and `h`.
|
|
9501
|
-
* - in the public key before computing `h`
|
|
9502
|
-
* The verification step is almost 2-3 times as slow as signing, but it's faster than re-signing + re-deriving the public key for separate checks.
|
|
9503
|
-
*/
|
|
9504
|
-
throw new Error('Transient signing failure');
|
|
9505
|
-
}
|
|
9506
9563
|
return { RS: signature };
|
|
9507
9564
|
}
|
|
9508
9565
|
case enums.publicKey.ed448: {
|
|
@@ -11235,7 +11292,7 @@ class ECDHXSymmetricKey {
|
|
|
11235
11292
|
* Encrypts data using specified algorithm and public key parameters.
|
|
11236
11293
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
|
|
11237
11294
|
* @param {module:enums.publicKey} keyAlgo - Public key algorithm
|
|
11238
|
-
* @param {module:enums.symmetric} symmetricAlgo - Cipher algorithm
|
|
11295
|
+
* @param {module:enums.symmetric|null} symmetricAlgo - Cipher algorithm (v3 only)
|
|
11239
11296
|
* @param {Object} publicParams - Algorithm-specific public key parameters
|
|
11240
11297
|
* @param {Object} privateParams - Algorithm-specific private key parameters
|
|
11241
11298
|
* @param {Uint8Array} data - Data to be encrypted
|
|
@@ -11263,7 +11320,7 @@ async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, privatePar
|
|
|
11263
11320
|
}
|
|
11264
11321
|
case enums.publicKey.x25519:
|
|
11265
11322
|
case enums.publicKey.x448: {
|
|
11266
|
-
if (!util.isAES(symmetricAlgo)) {
|
|
11323
|
+
if (symmetricAlgo && !util.isAES(symmetricAlgo)) {
|
|
11267
11324
|
// see https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/276
|
|
11268
11325
|
throw new Error('X25519 and X448 keys can only encrypt AES session keys');
|
|
11269
11326
|
}
|
|
@@ -11895,9 +11952,26 @@ class Argon2OutOfMemoryError extends Error {
|
|
|
11895
11952
|
let loadArgonWasmModule;
|
|
11896
11953
|
let argon2Promise;
|
|
11897
11954
|
// reload wasm module above this treshold, to deallocated used memory
|
|
11898
|
-
|
|
11955
|
+
// (cannot be declared as a simple `static` field as its not supported by Safari 14)
|
|
11956
|
+
let ARGON2_WASM_MEMORY_THRESHOLD_RELOAD = 2 << 19;
|
|
11899
11957
|
|
|
11900
11958
|
class Argon2S2K {
|
|
11959
|
+
static get ARGON2_WASM_MEMORY_THRESHOLD_RELOAD() {
|
|
11960
|
+
return ARGON2_WASM_MEMORY_THRESHOLD_RELOAD;
|
|
11961
|
+
}
|
|
11962
|
+
|
|
11963
|
+
static set ARGON2_WASM_MEMORY_THRESHOLD_RELOAD(memoryThreshold) {
|
|
11964
|
+
ARGON2_WASM_MEMORY_THRESHOLD_RELOAD = memoryThreshold;
|
|
11965
|
+
}
|
|
11966
|
+
|
|
11967
|
+
static reloadWasmModule() {
|
|
11968
|
+
if (!loadArgonWasmModule) return;
|
|
11969
|
+
|
|
11970
|
+
// it will be awaited if needed at the next `produceKey` invocation
|
|
11971
|
+
argon2Promise = loadArgonWasmModule();
|
|
11972
|
+
argon2Promise.catch(() => {});
|
|
11973
|
+
}
|
|
11974
|
+
|
|
11901
11975
|
/**
|
|
11902
11976
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
11903
11977
|
*/
|
|
@@ -11985,10 +12059,8 @@ class Argon2S2K {
|
|
|
11985
12059
|
});
|
|
11986
12060
|
|
|
11987
12061
|
// a lot of memory was used, reload to deallocate
|
|
11988
|
-
if (decodedM > ARGON2_WASM_MEMORY_THRESHOLD_RELOAD) {
|
|
11989
|
-
|
|
11990
|
-
argon2Promise = loadArgonWasmModule();
|
|
11991
|
-
argon2Promise.catch(() => {});
|
|
12062
|
+
if (decodedM > Argon2S2K.ARGON2_WASM_MEMORY_THRESHOLD_RELOAD) {
|
|
12063
|
+
Argon2S2K.reloadWasmModule();
|
|
11992
12064
|
}
|
|
11993
12065
|
return hash;
|
|
11994
12066
|
} catch (e) {
|
|
@@ -14237,6 +14309,14 @@ class KeyID {
|
|
|
14237
14309
|
// Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification.
|
|
14238
14310
|
const verified = Symbol('verified');
|
|
14239
14311
|
|
|
14312
|
+
// A salt notation is used to randomize signatures.
|
|
14313
|
+
// This is to protect EdDSA signatures in particular, which are known to be vulnerable to fault attacks
|
|
14314
|
+
// leading to secret key extraction if two signatures over the same data can be collected (see https://github.com/jedisct1/libsodium/issues/170).
|
|
14315
|
+
// For simplicity, we add the salt to all algos, as it may also serve as protection in case of weaknesses in the hash algo, potentially hindering e.g.
|
|
14316
|
+
// some chosen-prefix attacks.
|
|
14317
|
+
// v6 signatures do not need to rely on this notation, as they already include a separate, built-in salt.
|
|
14318
|
+
const SALT_NOTATION_NAME = 'salt@notations.openpgpjs.org';
|
|
14319
|
+
|
|
14240
14320
|
// GPG puts the Issuer and Signature subpackets in the unhashed area.
|
|
14241
14321
|
// Tampering with those invalidates the signature, so we still trust them and parse them.
|
|
14242
14322
|
// All other unhashed subpackets are ignored.
|
|
@@ -14406,7 +14486,7 @@ class SignaturePacket {
|
|
|
14406
14486
|
* @throws {Error} if signing failed
|
|
14407
14487
|
* @async
|
|
14408
14488
|
*/
|
|
14409
|
-
async sign(key, data, date = new Date(), detached = false) {
|
|
14489
|
+
async sign(key, data, date = new Date(), detached = false, config) {
|
|
14410
14490
|
this.version = key.version;
|
|
14411
14491
|
|
|
14412
14492
|
this.created = util.normalizeDate(date);
|
|
@@ -14416,6 +14496,31 @@ class SignaturePacket {
|
|
|
14416
14496
|
|
|
14417
14497
|
const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])];
|
|
14418
14498
|
|
|
14499
|
+
// add randomness to the signature
|
|
14500
|
+
if (this.version === 6) {
|
|
14501
|
+
const saltLength = saltLengthForHash(this.hashAlgorithm);
|
|
14502
|
+
if (this.salt === null) {
|
|
14503
|
+
this.salt = mod$1.random.getRandomBytes(saltLength);
|
|
14504
|
+
} else if (saltLength !== this.salt.length) {
|
|
14505
|
+
throw new Error('Provided salt does not have the required length');
|
|
14506
|
+
}
|
|
14507
|
+
} else if (config.nonDeterministicSignaturesViaNotation) {
|
|
14508
|
+
const saltNotations = this.rawNotations.filter(({ name }) => (name === SALT_NOTATION_NAME));
|
|
14509
|
+
// since re-signing the same object is not supported, it's not expected to have multiple salt notations,
|
|
14510
|
+
// but we guard against it as a sanity check
|
|
14511
|
+
if (saltNotations.length === 0) {
|
|
14512
|
+
const saltValue = mod$1.random.getRandomBytes(saltLengthForHash(this.hashAlgorithm));
|
|
14513
|
+
this.rawNotations.push({
|
|
14514
|
+
name: SALT_NOTATION_NAME,
|
|
14515
|
+
value: saltValue,
|
|
14516
|
+
humanReadable: false,
|
|
14517
|
+
critical: false
|
|
14518
|
+
});
|
|
14519
|
+
} else {
|
|
14520
|
+
throw new Error('Unexpected existing salt notation');
|
|
14521
|
+
}
|
|
14522
|
+
}
|
|
14523
|
+
|
|
14419
14524
|
// Add hashed subpackets
|
|
14420
14525
|
arr.push(this.writeHashedSubPackets());
|
|
14421
14526
|
|
|
@@ -14426,14 +14531,6 @@ class SignaturePacket {
|
|
|
14426
14531
|
|
|
14427
14532
|
this.signatureData = util.concat(arr);
|
|
14428
14533
|
|
|
14429
|
-
if (this.version === 6) {
|
|
14430
|
-
const saltLength = saltLengthForHash(this.hashAlgorithm);
|
|
14431
|
-
if (this.salt === null) {
|
|
14432
|
-
this.salt = mod$1.random.getRandomBytes(saltLength);
|
|
14433
|
-
} else if (saltLength !== this.salt.length) {
|
|
14434
|
-
throw new Error('Provided salt does not have the required length');
|
|
14435
|
-
}
|
|
14436
|
-
}
|
|
14437
14534
|
const toHash = this.toHash(this.signatureType, data, detached);
|
|
14438
14535
|
const hash = await this.hash(this.signatureType, data, toHash, detached);
|
|
14439
14536
|
|
|
@@ -16235,9 +16332,12 @@ class PublicKeyEncryptedSessionKeyPacket {
|
|
|
16235
16332
|
}
|
|
16236
16333
|
this.publicKeyAlgorithm = bytes[offset++];
|
|
16237
16334
|
this.encrypted = mod$1.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(offset));
|
|
16238
|
-
if (this.
|
|
16239
|
-
|
|
16240
|
-
|
|
16335
|
+
if (this.publicKeyAlgorithm === enums.publicKey.x25519 || this.publicKeyAlgorithm === enums.publicKey.x448) {
|
|
16336
|
+
if (this.version === 3) {
|
|
16337
|
+
this.sessionKeyAlgorithm = enums.write(enums.symmetric, this.encrypted.C.algorithm);
|
|
16338
|
+
} else if (this.encrypted.C.algorithm !== null) {
|
|
16339
|
+
throw new Error('Unexpected cleartext symmetric algorithm');
|
|
16340
|
+
}
|
|
16241
16341
|
}
|
|
16242
16342
|
}
|
|
16243
16343
|
|
|
@@ -16281,10 +16381,13 @@ class PublicKeyEncryptedSessionKeyPacket {
|
|
|
16281
16381
|
*/
|
|
16282
16382
|
async encrypt(key) {
|
|
16283
16383
|
const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
|
16284
|
-
|
|
16384
|
+
// No symmetric encryption algorithm identifier is passed to the public-key algorithm for a
|
|
16385
|
+
// v6 PKESK packet, as it is included in the v2 SEIPD packet.
|
|
16386
|
+
const sessionKeyAlgorithm = this.version === 3 ? this.sessionKeyAlgorithm : null;
|
|
16387
|
+
const encoded = encodeSessionKey(this.version, algo, sessionKeyAlgorithm, this.sessionKey);
|
|
16285
16388
|
const privateParams = algo === enums.publicKey.aead ? key.privateParams : null;
|
|
16286
16389
|
this.encrypted = await mod$1.publicKeyEncrypt(
|
|
16287
|
-
algo,
|
|
16390
|
+
algo, sessionKeyAlgorithm, key.publicParams, privateParams, encoded, key.getFingerprintBytes());
|
|
16288
16391
|
}
|
|
16289
16392
|
|
|
16290
16393
|
/**
|
|
@@ -16383,6 +16486,7 @@ function decodeSessionKey(version, keyAlgo, decryptedData, randomSessionKey) {
|
|
|
16383
16486
|
case enums.publicKey.x25519:
|
|
16384
16487
|
case enums.publicKey.x448:
|
|
16385
16488
|
return {
|
|
16489
|
+
sessionKeyAlgorithm: null,
|
|
16386
16490
|
sessionKey: decryptedData
|
|
16387
16491
|
};
|
|
16388
16492
|
default:
|
|
@@ -18070,7 +18174,9 @@ class Signature {
|
|
|
18070
18174
|
* @returns {ReadableStream<String>} ASCII armor.
|
|
18071
18175
|
*/
|
|
18072
18176
|
armor(config$1 = config) {
|
|
18073
|
-
|
|
18177
|
+
// An ASCII-armored sequence of Signature packets that only includes v6 Signature packets MUST NOT contain a CRC24 footer.
|
|
18178
|
+
const emitChecksum = this.packets.some(packet => packet.constructor.tag === SignaturePacket.tag && packet.version !== 6);
|
|
18179
|
+
return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, emitChecksum, config$1);
|
|
18074
18180
|
}
|
|
18075
18181
|
|
|
18076
18182
|
/**
|
|
@@ -18283,7 +18389,7 @@ async function getPreferredCompressionAlgo(keys = [], date = new Date(), userIDs
|
|
|
18283
18389
|
async function getPreferredCipherSuite(keys = [], date = new Date(), userIDs = [], config$1 = config) {
|
|
18284
18390
|
const selfSigs = await Promise.all(keys.map((key, i) => key.getPrimarySelfSignature(date, userIDs[i], config$1)));
|
|
18285
18391
|
const withAEAD = keys.length ?
|
|
18286
|
-
selfSigs.every(selfSig => selfSig.features[0] & enums.features.seipdv2) :
|
|
18392
|
+
selfSigs.every(selfSig => selfSig.features && (selfSig.features[0] & enums.features.seipdv2)) :
|
|
18287
18393
|
config$1.aeadProtect;
|
|
18288
18394
|
|
|
18289
18395
|
if (withAEAD) {
|
|
@@ -18330,8 +18436,8 @@ async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, s
|
|
|
18330
18436
|
Object.assign(signaturePacket, signatureProperties);
|
|
18331
18437
|
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
|
18332
18438
|
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKeyPacket, date, userID, config);
|
|
18333
|
-
signaturePacket.rawNotations = notations;
|
|
18334
|
-
await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached);
|
|
18439
|
+
signaturePacket.rawNotations = [...notations];
|
|
18440
|
+
await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached, config);
|
|
18335
18441
|
return signaturePacket;
|
|
18336
18442
|
}
|
|
18337
18443
|
|
|
@@ -18394,7 +18500,7 @@ async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocation
|
|
|
18394
18500
|
!signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID)
|
|
18395
18501
|
) {
|
|
18396
18502
|
await revocationSignature.verify(
|
|
18397
|
-
key, signatureType, dataToVerify,
|
|
18503
|
+
key, signatureType, dataToVerify, date, false, config
|
|
18398
18504
|
);
|
|
18399
18505
|
|
|
18400
18506
|
// TODO get an identifier of the revoked object instead
|
|
@@ -19664,7 +19770,9 @@ class Key {
|
|
|
19664
19770
|
const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config$1);
|
|
19665
19771
|
const packetlist = new PacketList();
|
|
19666
19772
|
packetlist.push(revocationSignature);
|
|
19667
|
-
|
|
19773
|
+
// An ASCII-armored Transferable Public Key packet sequence of a v6 key MUST NOT contain a CRC24 footer.
|
|
19774
|
+
const emitChecksum = this.keyPacket.version !== 6;
|
|
19775
|
+
return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate', emitChecksum, config$1);
|
|
19668
19776
|
}
|
|
19669
19777
|
|
|
19670
19778
|
/**
|
|
@@ -19854,7 +19962,9 @@ class PublicKey extends Key {
|
|
|
19854
19962
|
* @returns {ReadableStream<String>} ASCII armor.
|
|
19855
19963
|
*/
|
|
19856
19964
|
armor(config$1 = config) {
|
|
19857
|
-
|
|
19965
|
+
// An ASCII-armored Transferable Public Key packet sequence of a v6 key MUST NOT contain a CRC24 footer.
|
|
19966
|
+
const emitChecksum = this.keyPacket.version !== 6;
|
|
19967
|
+
return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, emitChecksum, config$1);
|
|
19858
19968
|
}
|
|
19859
19969
|
}
|
|
19860
19970
|
|
|
@@ -19927,7 +20037,9 @@ class PrivateKey extends PublicKey {
|
|
|
19927
20037
|
* @returns {ReadableStream<String>} ASCII armor.
|
|
19928
20038
|
*/
|
|
19929
20039
|
armor(config$1 = config) {
|
|
19930
|
-
|
|
20040
|
+
// An ASCII-armored Transferable Public Key packet sequence of a v6 key MUST NOT contain a CRC24 footer.
|
|
20041
|
+
const emitChecksum = this.keyPacket.version !== 6;
|
|
20042
|
+
return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, emitChecksum, config$1);
|
|
19931
20043
|
}
|
|
19932
20044
|
|
|
19933
20045
|
/**
|
|
@@ -21246,7 +21358,13 @@ class Message {
|
|
|
21246
21358
|
* @returns {ReadableStream<String>} ASCII armor.
|
|
21247
21359
|
*/
|
|
21248
21360
|
armor(config$1 = config) {
|
|
21249
|
-
|
|
21361
|
+
const trailingPacket = this.packets[this.packets.length - 1];
|
|
21362
|
+
// An ASCII-armored Encrypted Message packet sequence that ends in an v2 SEIPD packet MUST NOT contain a CRC24 footer.
|
|
21363
|
+
// An ASCII-armored sequence of Signature packets that only includes v6 Signature packets MUST NOT contain a CRC24 footer.
|
|
21364
|
+
const emitChecksum = trailingPacket.constructor.tag === SymEncryptedIntegrityProtectedDataPacket.tag ?
|
|
21365
|
+
trailingPacket.version !== 2 :
|
|
21366
|
+
this.packets.some(packet => packet.constructor.tag === SignaturePacket.tag && packet.version !== 6);
|
|
21367
|
+
return armor(enums.armor.message, this.write(), null, null, null, emitChecksum, config$1);
|
|
21250
21368
|
}
|
|
21251
21369
|
}
|
|
21252
21370
|
|
|
@@ -21581,9 +21699,9 @@ class CleartextMessage {
|
|
|
21581
21699
|
* @returns {String | ReadableStream<String>} ASCII armor.
|
|
21582
21700
|
*/
|
|
21583
21701
|
armor(config$1 = config) {
|
|
21584
|
-
// emit header if one of the signatures has a version not 6
|
|
21585
|
-
const
|
|
21586
|
-
const hash =
|
|
21702
|
+
// emit header and checksum if one of the signatures has a version not 6
|
|
21703
|
+
const emitHeaderAndChecksum = this.signature.packets.some(packet => packet.version !== 6);
|
|
21704
|
+
const hash = emitHeaderAndChecksum ?
|
|
21587
21705
|
Array.from(new Set(this.signature.packets.map(
|
|
21588
21706
|
packet => enums.read(enums.hash, packet.hashAlgorithm).toUpperCase()
|
|
21589
21707
|
))).join() :
|
|
@@ -21594,7 +21712,9 @@ class CleartextMessage {
|
|
|
21594
21712
|
text: this.text,
|
|
21595
21713
|
data: this.signature.packets.write()
|
|
21596
21714
|
};
|
|
21597
|
-
|
|
21715
|
+
|
|
21716
|
+
// An ASCII-armored sequence of Signature packets that only includes v6 Signature packets MUST NOT contain a CRC24 footer.
|
|
21717
|
+
return armor(enums.armor.signed, body, undefined, undefined, undefined, emitHeaderAndChecksum, config$1);
|
|
21598
21718
|
}
|
|
21599
21719
|
}
|
|
21600
21720
|
|