@protontech/openpgp 6.0.0-alpha.1.patch.1 → 6.0.0-beta.0.patch.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 +211 -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 +211 -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 +211 -83
- package/dist/openpgp.js +211 -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 +211 -83
- package/openpgp.d.ts +5 -3
- package/package.json +9 -9
package/dist/node/openpgp.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! OpenPGP.js v6.0.0-
|
|
1
|
+
/*! OpenPGP.js v6.0.0-beta.0.patch.0 - 2024-04-19 - this is LGPL licensed code, see LICENSE/our website https://openpgpjs.org/ for more information. */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
@@ -1490,6 +1490,14 @@ var config = {
|
|
|
1490
1490
|
* @property {Boolean} aeadProtect
|
|
1491
1491
|
*/
|
|
1492
1492
|
aeadProtect: false,
|
|
1493
|
+
/**
|
|
1494
|
+
* Whether to disable encrypton using SEIPDv2 even if the encryption keys include the SEIPDv2 feature flag.
|
|
1495
|
+
* If true, SEIPDv1 (i.e. no AEAD) packets are always used instead.
|
|
1496
|
+
* SEIPDv2 is a more secure and faster choice, but it is not necessarily compatible with other libs and our mobile apps.
|
|
1497
|
+
* @memberof module:config
|
|
1498
|
+
* @property {Boolean} ignoreSEIPDv2FeatureFlag
|
|
1499
|
+
*/
|
|
1500
|
+
ignoreSEIPDv2FeatureFlag: false,
|
|
1493
1501
|
/**
|
|
1494
1502
|
* When reading OpenPGP v4 private keys (e.g. those generated in OpenPGP.js when not setting `config.v5Keys = true`)
|
|
1495
1503
|
* which were encrypted by OpenPGP.js v5 (or older) using `config.aeadProtect = true`,
|
|
@@ -1602,11 +1610,6 @@ var config = {
|
|
|
1602
1610
|
* @property {Boolean} passwordCollisionCheck
|
|
1603
1611
|
*/
|
|
1604
1612
|
passwordCollisionCheck: false,
|
|
1605
|
-
/**
|
|
1606
|
-
* @memberof module:config
|
|
1607
|
-
* @property {Boolean} revocationsExpire If true, expired revocation signatures are ignored
|
|
1608
|
-
*/
|
|
1609
|
-
revocationsExpire: false,
|
|
1610
1613
|
/**
|
|
1611
1614
|
* Allow decryption using RSA keys without `encrypt` flag.
|
|
1612
1615
|
* This setting is potentially insecure, but it is needed to get around an old openpgpjs bug
|
|
@@ -1682,7 +1685,7 @@ var config = {
|
|
|
1682
1685
|
* @memberof module:config
|
|
1683
1686
|
* @property {String} versionString A version string to be included in armored messages
|
|
1684
1687
|
*/
|
|
1685
|
-
versionString: 'OpenPGP.js 6.0.0-
|
|
1688
|
+
versionString: 'OpenPGP.js 6.0.0-beta.0.patch.0',
|
|
1686
1689
|
/**
|
|
1687
1690
|
* @memberof module:config
|
|
1688
1691
|
* @property {String} commentString A comment string to be included in armored messages
|
|
@@ -1702,6 +1705,14 @@ var config = {
|
|
|
1702
1705
|
* @property {Array} knownNotations
|
|
1703
1706
|
*/
|
|
1704
1707
|
knownNotations: [],
|
|
1708
|
+
/**
|
|
1709
|
+
* If true, a salt notation is used to randomize signatures generated by v4 and v5 keys (v6 signatures are always non-deterministic, by design).
|
|
1710
|
+
* This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
|
|
1711
|
+
* 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
|
|
1712
|
+
* weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
|
|
1713
|
+
* 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.
|
|
1714
|
+
*/
|
|
1715
|
+
nonDeterministicSignaturesViaNotation: true,
|
|
1705
1716
|
/**
|
|
1706
1717
|
* Whether to use the the noble-curves library for curves (other than Curve25519) that are not supported by the available native crypto API.
|
|
1707
1718
|
* When false, certain standard curves will not be supported (depending on the platform).
|
|
@@ -1732,14 +1743,7 @@ var config = {
|
|
|
1732
1743
|
* @memberof module:config
|
|
1733
1744
|
* @property {Set<String>} rejectCurves {@link module:enums.curve}
|
|
1734
1745
|
*/
|
|
1735
|
-
rejectCurves: new Set([enums.curve.secp256k1])
|
|
1736
|
-
/**
|
|
1737
|
-
* Whether to validate generated EdDSA signatures before returning them, to ensure they are not faulty signatures.
|
|
1738
|
-
* This check will make signing 2-3 times slower.
|
|
1739
|
-
* Faulty signatures may be generated (in principle) if random bitflips occur at specific points in the signature
|
|
1740
|
-
* computation, and could be used to recover the signer's secret key given a second signature over the same data.
|
|
1741
|
-
*/
|
|
1742
|
-
checkEdDSAFaultySignatures: true
|
|
1746
|
+
rejectCurves: new Set([enums.curve.secp256k1])
|
|
1743
1747
|
};
|
|
1744
1748
|
|
|
1745
1749
|
/**
|
|
@@ -2224,16 +2228,19 @@ const util = {
|
|
|
2224
2228
|
},
|
|
2225
2229
|
|
|
2226
2230
|
/**
|
|
2227
|
-
* Test email format
|
|
2228
|
-
*
|
|
2229
|
-
*
|
|
2230
|
-
*
|
|
2231
|
+
* Test email format to ensure basic compliance:
|
|
2232
|
+
* - must include a single @
|
|
2233
|
+
* - no control or space unicode chars allowed
|
|
2234
|
+
* - no backslash and square brackets (as the latter can mess with the userID parsing)
|
|
2235
|
+
* - cannot end with a punctuation char
|
|
2236
|
+
* These checks are not meant to be exhaustive; applications are strongly encouraged to implement stricter validation,
|
|
2237
|
+
* e.g. based on the W3C HTML spec (https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email)).
|
|
2231
2238
|
*/
|
|
2232
2239
|
isEmailAddress: function(data) {
|
|
2233
2240
|
if (!util.isString(data)) {
|
|
2234
2241
|
return false;
|
|
2235
2242
|
}
|
|
2236
|
-
const re = /^[
|
|
2243
|
+
const re = /^[^\p{C}\p{Z}@<>\\]+@[^\p{C}\p{Z}@<>\\]+[^\p{C}\p{Z}\p{P}]$/u;
|
|
2237
2244
|
return re.test(data);
|
|
2238
2245
|
},
|
|
2239
2246
|
|
|
@@ -2639,6 +2646,78 @@ function addheader(customComment, config) {
|
|
|
2639
2646
|
return result;
|
|
2640
2647
|
}
|
|
2641
2648
|
|
|
2649
|
+
/**
|
|
2650
|
+
* Calculates a checksum over the given data and returns it base64 encoded
|
|
2651
|
+
* @param {String | ReadableStream<String>} data - Data to create a CRC-24 checksum for
|
|
2652
|
+
* @returns {String | ReadableStream<String>} Base64 encoded checksum.
|
|
2653
|
+
* @private
|
|
2654
|
+
*/
|
|
2655
|
+
function getCheckSum(data) {
|
|
2656
|
+
const crc = createcrc24(data);
|
|
2657
|
+
return encode$1(crc);
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
// https://create.stephan-brumme.com/crc32/#slicing-by-8-overview
|
|
2661
|
+
|
|
2662
|
+
const crc_table = [
|
|
2663
|
+
new Array(0xFF),
|
|
2664
|
+
new Array(0xFF),
|
|
2665
|
+
new Array(0xFF),
|
|
2666
|
+
new Array(0xFF)
|
|
2667
|
+
];
|
|
2668
|
+
|
|
2669
|
+
for (let i = 0; i <= 0xFF; i++) {
|
|
2670
|
+
let crc = i << 16;
|
|
2671
|
+
for (let j = 0; j < 8; j++) {
|
|
2672
|
+
crc = (crc << 1) ^ ((crc & 0x800000) !== 0 ? 0x864CFB : 0);
|
|
2673
|
+
}
|
|
2674
|
+
crc_table[0][i] =
|
|
2675
|
+
((crc & 0xFF0000) >> 16) |
|
|
2676
|
+
(crc & 0x00FF00) |
|
|
2677
|
+
((crc & 0x0000FF) << 16);
|
|
2678
|
+
}
|
|
2679
|
+
for (let i = 0; i <= 0xFF; i++) {
|
|
2680
|
+
crc_table[1][i] = (crc_table[0][i] >> 8) ^ crc_table[0][crc_table[0][i] & 0xFF];
|
|
2681
|
+
}
|
|
2682
|
+
for (let i = 0; i <= 0xFF; i++) {
|
|
2683
|
+
crc_table[2][i] = (crc_table[1][i] >> 8) ^ crc_table[0][crc_table[1][i] & 0xFF];
|
|
2684
|
+
}
|
|
2685
|
+
for (let i = 0; i <= 0xFF; i++) {
|
|
2686
|
+
crc_table[3][i] = (crc_table[2][i] >> 8) ^ crc_table[0][crc_table[2][i] & 0xFF];
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness
|
|
2690
|
+
const isLittleEndian$1 = (function() {
|
|
2691
|
+
const buffer = new ArrayBuffer(2);
|
|
2692
|
+
new DataView(buffer).setInt16(0, 0xFF, true /* littleEndian */);
|
|
2693
|
+
// Int16Array uses the platform's endianness.
|
|
2694
|
+
return new Int16Array(buffer)[0] === 0xFF;
|
|
2695
|
+
}());
|
|
2696
|
+
|
|
2697
|
+
/**
|
|
2698
|
+
* Internal function to calculate a CRC-24 checksum over a given string (data)
|
|
2699
|
+
* @param {String | ReadableStream<String>} input - Data to create a CRC-24 checksum for
|
|
2700
|
+
* @returns {Uint8Array | ReadableStream<Uint8Array>} The CRC-24 checksum.
|
|
2701
|
+
* @private
|
|
2702
|
+
*/
|
|
2703
|
+
function createcrc24(input) {
|
|
2704
|
+
let crc = 0xCE04B7;
|
|
2705
|
+
return transform(input, value => {
|
|
2706
|
+
const len32 = isLittleEndian$1 ? Math.floor(value.length / 4) : 0;
|
|
2707
|
+
const arr32 = new Uint32Array(value.buffer, value.byteOffset, len32);
|
|
2708
|
+
for (let i = 0; i < len32; i++) {
|
|
2709
|
+
crc ^= arr32[i];
|
|
2710
|
+
crc =
|
|
2711
|
+
crc_table[0][(crc >> 24) & 0xFF] ^
|
|
2712
|
+
crc_table[1][(crc >> 16) & 0xFF] ^
|
|
2713
|
+
crc_table[2][(crc >> 8) & 0xFF] ^
|
|
2714
|
+
crc_table[3][(crc >> 0) & 0xFF];
|
|
2715
|
+
}
|
|
2716
|
+
for (let i = len32 * 4; i < value.length; i++) {
|
|
2717
|
+
crc = (crc >> 8) ^ crc_table[0][(crc & 0xFF) ^ value[i]];
|
|
2718
|
+
}
|
|
2719
|
+
}, () => new Uint8Array([crc, crc >> 8, crc >> 16]));
|
|
2720
|
+
}
|
|
2642
2721
|
|
|
2643
2722
|
/**
|
|
2644
2723
|
* Verify armored headers. crypto-refresh-06, section 6.2:
|
|
@@ -2794,10 +2873,13 @@ function unarmor(input) {
|
|
|
2794
2873
|
* @param {Integer} [partIndex]
|
|
2795
2874
|
* @param {Integer} [partTotal]
|
|
2796
2875
|
* @param {String} [customComment] - Additional comment to add to the armored string
|
|
2876
|
+
* @param {Boolean} [emitChecksum] - Whether to compute and include the CRC checksum
|
|
2877
|
+
* (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)
|
|
2878
|
+
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
2797
2879
|
* @returns {String | ReadableStream<String>} Armored text.
|
|
2798
2880
|
* @static
|
|
2799
2881
|
*/
|
|
2800
|
-
function armor(messageType, body, partIndex, partTotal, customComment, config$1 = config) {
|
|
2882
|
+
function armor(messageType, body, partIndex, partTotal, customComment, emitChecksum = false, config$1 = config) {
|
|
2801
2883
|
let text;
|
|
2802
2884
|
let hash;
|
|
2803
2885
|
if (messageType === enums.armor.signed) {
|
|
@@ -2805,18 +2887,24 @@ function armor(messageType, body, partIndex, partTotal, customComment, config$1
|
|
|
2805
2887
|
hash = body.hash;
|
|
2806
2888
|
body = body.data;
|
|
2807
2889
|
}
|
|
2890
|
+
// unless explicitly forbidden by the spec, we need to include the checksum to work around a GnuPG bug
|
|
2891
|
+
// where data fails to be decoded if the base64 ends with no padding chars (=) (see https://dev.gnupg.org/T7071)
|
|
2892
|
+
const maybeBodyClone = emitChecksum && passiveClone(body);
|
|
2893
|
+
|
|
2808
2894
|
const result = [];
|
|
2809
2895
|
switch (messageType) {
|
|
2810
2896
|
case enums.armor.multipartSection:
|
|
2811
2897
|
result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n');
|
|
2812
2898
|
result.push(addheader(customComment, config$1));
|
|
2813
2899
|
result.push(encode$1(body));
|
|
2900
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2814
2901
|
result.push('-----END PGP MESSAGE, PART ' + partIndex + '/' + partTotal + '-----\n');
|
|
2815
2902
|
break;
|
|
2816
2903
|
case enums.armor.multipartLast:
|
|
2817
2904
|
result.push('-----BEGIN PGP MESSAGE, PART ' + partIndex + '-----\n');
|
|
2818
2905
|
result.push(addheader(customComment, config$1));
|
|
2819
2906
|
result.push(encode$1(body));
|
|
2907
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2820
2908
|
result.push('-----END PGP MESSAGE, PART ' + partIndex + '-----\n');
|
|
2821
2909
|
break;
|
|
2822
2910
|
case enums.armor.signed:
|
|
@@ -2826,30 +2914,35 @@ function armor(messageType, body, partIndex, partTotal, customComment, config$1
|
|
|
2826
2914
|
result.push('\n-----BEGIN PGP SIGNATURE-----\n');
|
|
2827
2915
|
result.push(addheader(customComment, config$1));
|
|
2828
2916
|
result.push(encode$1(body));
|
|
2917
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2829
2918
|
result.push('-----END PGP SIGNATURE-----\n');
|
|
2830
2919
|
break;
|
|
2831
2920
|
case enums.armor.message:
|
|
2832
2921
|
result.push('-----BEGIN PGP MESSAGE-----\n');
|
|
2833
2922
|
result.push(addheader(customComment, config$1));
|
|
2834
2923
|
result.push(encode$1(body));
|
|
2924
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2835
2925
|
result.push('-----END PGP MESSAGE-----\n');
|
|
2836
2926
|
break;
|
|
2837
2927
|
case enums.armor.publicKey:
|
|
2838
2928
|
result.push('-----BEGIN PGP PUBLIC KEY BLOCK-----\n');
|
|
2839
2929
|
result.push(addheader(customComment, config$1));
|
|
2840
2930
|
result.push(encode$1(body));
|
|
2931
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2841
2932
|
result.push('-----END PGP PUBLIC KEY BLOCK-----\n');
|
|
2842
2933
|
break;
|
|
2843
2934
|
case enums.armor.privateKey:
|
|
2844
2935
|
result.push('-----BEGIN PGP PRIVATE KEY BLOCK-----\n');
|
|
2845
2936
|
result.push(addheader(customComment, config$1));
|
|
2846
2937
|
result.push(encode$1(body));
|
|
2938
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2847
2939
|
result.push('-----END PGP PRIVATE KEY BLOCK-----\n');
|
|
2848
2940
|
break;
|
|
2849
2941
|
case enums.armor.signature:
|
|
2850
2942
|
result.push('-----BEGIN PGP SIGNATURE-----\n');
|
|
2851
2943
|
result.push(addheader(customComment, config$1));
|
|
2852
2944
|
result.push(encode$1(body));
|
|
2945
|
+
maybeBodyClone && result.push('=', getCheckSum(maybeBodyClone));
|
|
2853
2946
|
result.push('-----END PGP SIGNATURE-----\n');
|
|
2854
2947
|
break;
|
|
2855
2948
|
}
|
|
@@ -9377,20 +9470,6 @@ async function sign$5(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9377
9470
|
}
|
|
9378
9471
|
const secretKey = util.concatUint8Array([privateKey, publicKey.subarray(1)]);
|
|
9379
9472
|
const signature = nacl.sign.detached(hashed, secretKey);
|
|
9380
|
-
if (config.checkEdDSAFaultySignatures && !nacl.sign.detached.verify(hashed, signature, publicKey.subarray(1))) {
|
|
9381
|
-
/**
|
|
9382
|
-
* Detect faulty signatures caused by random bitflips during `crypto_sign` which could lead to private key extraction
|
|
9383
|
-
* if two signatures over the same message are obtained.
|
|
9384
|
-
* See https://github.com/jedisct1/libsodium/issues/170.
|
|
9385
|
-
* If the input data is not deterministic, e.g. thanks to the random salt in v6 OpenPGP signatures (not yet implemented),
|
|
9386
|
-
* then the generated signature is always safe, and the verification step is skipped.
|
|
9387
|
-
* Otherwise, we need to verify the generated to ensure that no bitflip occured:
|
|
9388
|
-
* - in M between the computation of `r` and `h`.
|
|
9389
|
-
* - in the public key before computing `h`
|
|
9390
|
-
* 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.
|
|
9391
|
-
*/
|
|
9392
|
-
throw new Error('Transient signing failure');
|
|
9393
|
-
}
|
|
9394
9473
|
// EdDSA signature params are returned in little-endian format
|
|
9395
9474
|
return {
|
|
9396
9475
|
r: signature.subarray(0, 32),
|
|
@@ -9511,20 +9590,6 @@ async function sign$4(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9511
9590
|
case enums.publicKey.ed25519: {
|
|
9512
9591
|
const secretKey = util.concatUint8Array([privateKey, publicKey]);
|
|
9513
9592
|
const signature = nacl.sign.detached(hashed, secretKey);
|
|
9514
|
-
if (config.checkEdDSAFaultySignatures && !nacl.sign.detached.verify(hashed, signature, publicKey)) {
|
|
9515
|
-
/**
|
|
9516
|
-
* Detect faulty signatures caused by random bitflips during `crypto_sign` which could lead to private key extraction
|
|
9517
|
-
* if two signatures over the same message are obtained.
|
|
9518
|
-
* See https://github.com/jedisct1/libsodium/issues/170.
|
|
9519
|
-
* If the input data is not deterministic, e.g. thanks to the random salt in v6 OpenPGP signatures (not yet implemented),
|
|
9520
|
-
* then the generated signature is always safe, and the verification step is skipped.
|
|
9521
|
-
* Otherwise, we need to verify the generated to ensure that no bitflip occured:
|
|
9522
|
-
* - in M between the computation of `r` and `h`.
|
|
9523
|
-
* - in the public key before computing `h`
|
|
9524
|
-
* 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.
|
|
9525
|
-
*/
|
|
9526
|
-
throw new Error('Transient signing failure');
|
|
9527
|
-
}
|
|
9528
9593
|
return { RS: signature };
|
|
9529
9594
|
}
|
|
9530
9595
|
case enums.publicKey.ed448: {
|
|
@@ -11257,7 +11322,7 @@ class ECDHXSymmetricKey {
|
|
|
11257
11322
|
* Encrypts data using specified algorithm and public key parameters.
|
|
11258
11323
|
* See {@link https://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1} for public key algorithms.
|
|
11259
11324
|
* @param {module:enums.publicKey} keyAlgo - Public key algorithm
|
|
11260
|
-
* @param {module:enums.symmetric} symmetricAlgo - Cipher algorithm
|
|
11325
|
+
* @param {module:enums.symmetric|null} symmetricAlgo - Cipher algorithm (v3 only)
|
|
11261
11326
|
* @param {Object} publicParams - Algorithm-specific public key parameters
|
|
11262
11327
|
* @param {Object} privateParams - Algorithm-specific private key parameters
|
|
11263
11328
|
* @param {Uint8Array} data - Data to be encrypted
|
|
@@ -11285,7 +11350,7 @@ async function publicKeyEncrypt(keyAlgo, symmetricAlgo, publicParams, privatePar
|
|
|
11285
11350
|
}
|
|
11286
11351
|
case enums.publicKey.x25519:
|
|
11287
11352
|
case enums.publicKey.x448: {
|
|
11288
|
-
if (!util.isAES(symmetricAlgo)) {
|
|
11353
|
+
if (symmetricAlgo && !util.isAES(symmetricAlgo)) {
|
|
11289
11354
|
// see https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/276
|
|
11290
11355
|
throw new Error('X25519 and X448 keys can only encrypt AES session keys');
|
|
11291
11356
|
}
|
|
@@ -11917,9 +11982,26 @@ class Argon2OutOfMemoryError extends Error {
|
|
|
11917
11982
|
let loadArgonWasmModule;
|
|
11918
11983
|
let argon2Promise;
|
|
11919
11984
|
// reload wasm module above this treshold, to deallocated used memory
|
|
11920
|
-
|
|
11985
|
+
// (cannot be declared as a simple `static` field as its not supported by Safari 14)
|
|
11986
|
+
let ARGON2_WASM_MEMORY_THRESHOLD_RELOAD = 2 << 19;
|
|
11921
11987
|
|
|
11922
11988
|
class Argon2S2K {
|
|
11989
|
+
static get ARGON2_WASM_MEMORY_THRESHOLD_RELOAD() {
|
|
11990
|
+
return ARGON2_WASM_MEMORY_THRESHOLD_RELOAD;
|
|
11991
|
+
}
|
|
11992
|
+
|
|
11993
|
+
static set ARGON2_WASM_MEMORY_THRESHOLD_RELOAD(memoryThreshold) {
|
|
11994
|
+
ARGON2_WASM_MEMORY_THRESHOLD_RELOAD = memoryThreshold;
|
|
11995
|
+
}
|
|
11996
|
+
|
|
11997
|
+
static reloadWasmModule() {
|
|
11998
|
+
if (!loadArgonWasmModule) return;
|
|
11999
|
+
|
|
12000
|
+
// it will be awaited if needed at the next `produceKey` invocation
|
|
12001
|
+
argon2Promise = loadArgonWasmModule();
|
|
12002
|
+
argon2Promise.catch(() => {});
|
|
12003
|
+
}
|
|
12004
|
+
|
|
11923
12005
|
/**
|
|
11924
12006
|
* @param {Object} [config] - Full configuration, defaults to openpgp.config
|
|
11925
12007
|
*/
|
|
@@ -12007,10 +12089,8 @@ class Argon2S2K {
|
|
|
12007
12089
|
});
|
|
12008
12090
|
|
|
12009
12091
|
// a lot of memory was used, reload to deallocate
|
|
12010
|
-
if (decodedM > ARGON2_WASM_MEMORY_THRESHOLD_RELOAD) {
|
|
12011
|
-
|
|
12012
|
-
argon2Promise = loadArgonWasmModule();
|
|
12013
|
-
argon2Promise.catch(() => {});
|
|
12092
|
+
if (decodedM > Argon2S2K.ARGON2_WASM_MEMORY_THRESHOLD_RELOAD) {
|
|
12093
|
+
Argon2S2K.reloadWasmModule();
|
|
12014
12094
|
}
|
|
12015
12095
|
return hash;
|
|
12016
12096
|
} catch (e) {
|
|
@@ -14259,6 +14339,14 @@ class KeyID {
|
|
|
14259
14339
|
// Symbol to store cryptographic validity of the signature, to avoid recomputing multiple times on verification.
|
|
14260
14340
|
const verified = Symbol('verified');
|
|
14261
14341
|
|
|
14342
|
+
// A salt notation is used to randomize signatures.
|
|
14343
|
+
// This is to protect EdDSA signatures in particular, which are known to be vulnerable to fault attacks
|
|
14344
|
+
// leading to secret key extraction if two signatures over the same data can be collected (see https://github.com/jedisct1/libsodium/issues/170).
|
|
14345
|
+
// 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.
|
|
14346
|
+
// some chosen-prefix attacks.
|
|
14347
|
+
// v6 signatures do not need to rely on this notation, as they already include a separate, built-in salt.
|
|
14348
|
+
const SALT_NOTATION_NAME = 'salt@notations.openpgpjs.org';
|
|
14349
|
+
|
|
14262
14350
|
// GPG puts the Issuer and Signature subpackets in the unhashed area.
|
|
14263
14351
|
// Tampering with those invalidates the signature, so we still trust them and parse them.
|
|
14264
14352
|
// All other unhashed subpackets are ignored.
|
|
@@ -14428,7 +14516,7 @@ class SignaturePacket {
|
|
|
14428
14516
|
* @throws {Error} if signing failed
|
|
14429
14517
|
* @async
|
|
14430
14518
|
*/
|
|
14431
|
-
async sign(key, data, date = new Date(), detached = false) {
|
|
14519
|
+
async sign(key, data, date = new Date(), detached = false, config) {
|
|
14432
14520
|
this.version = key.version;
|
|
14433
14521
|
|
|
14434
14522
|
this.created = util.normalizeDate(date);
|
|
@@ -14438,6 +14526,31 @@ class SignaturePacket {
|
|
|
14438
14526
|
|
|
14439
14527
|
const arr = [new Uint8Array([this.version, this.signatureType, this.publicKeyAlgorithm, this.hashAlgorithm])];
|
|
14440
14528
|
|
|
14529
|
+
// add randomness to the signature
|
|
14530
|
+
if (this.version === 6) {
|
|
14531
|
+
const saltLength = saltLengthForHash(this.hashAlgorithm);
|
|
14532
|
+
if (this.salt === null) {
|
|
14533
|
+
this.salt = mod$1.random.getRandomBytes(saltLength);
|
|
14534
|
+
} else if (saltLength !== this.salt.length) {
|
|
14535
|
+
throw new Error('Provided salt does not have the required length');
|
|
14536
|
+
}
|
|
14537
|
+
} else if (config.nonDeterministicSignaturesViaNotation) {
|
|
14538
|
+
const saltNotations = this.rawNotations.filter(({ name }) => (name === SALT_NOTATION_NAME));
|
|
14539
|
+
// since re-signing the same object is not supported, it's not expected to have multiple salt notations,
|
|
14540
|
+
// but we guard against it as a sanity check
|
|
14541
|
+
if (saltNotations.length === 0) {
|
|
14542
|
+
const saltValue = mod$1.random.getRandomBytes(saltLengthForHash(this.hashAlgorithm));
|
|
14543
|
+
this.rawNotations.push({
|
|
14544
|
+
name: SALT_NOTATION_NAME,
|
|
14545
|
+
value: saltValue,
|
|
14546
|
+
humanReadable: false,
|
|
14547
|
+
critical: false
|
|
14548
|
+
});
|
|
14549
|
+
} else {
|
|
14550
|
+
throw new Error('Unexpected existing salt notation');
|
|
14551
|
+
}
|
|
14552
|
+
}
|
|
14553
|
+
|
|
14441
14554
|
// Add hashed subpackets
|
|
14442
14555
|
arr.push(this.writeHashedSubPackets());
|
|
14443
14556
|
|
|
@@ -14448,14 +14561,6 @@ class SignaturePacket {
|
|
|
14448
14561
|
|
|
14449
14562
|
this.signatureData = util.concat(arr);
|
|
14450
14563
|
|
|
14451
|
-
if (this.version === 6) {
|
|
14452
|
-
const saltLength = saltLengthForHash(this.hashAlgorithm);
|
|
14453
|
-
if (this.salt === null) {
|
|
14454
|
-
this.salt = mod$1.random.getRandomBytes(saltLength);
|
|
14455
|
-
} else if (saltLength !== this.salt.length) {
|
|
14456
|
-
throw new Error('Provided salt does not have the required length');
|
|
14457
|
-
}
|
|
14458
|
-
}
|
|
14459
14564
|
const toHash = this.toHash(this.signatureType, data, detached);
|
|
14460
14565
|
const hash = await this.hash(this.signatureType, data, toHash, detached);
|
|
14461
14566
|
|
|
@@ -16257,9 +16362,12 @@ class PublicKeyEncryptedSessionKeyPacket {
|
|
|
16257
16362
|
}
|
|
16258
16363
|
this.publicKeyAlgorithm = bytes[offset++];
|
|
16259
16364
|
this.encrypted = mod$1.parseEncSessionKeyParams(this.publicKeyAlgorithm, bytes.subarray(offset));
|
|
16260
|
-
if (this.
|
|
16261
|
-
|
|
16262
|
-
|
|
16365
|
+
if (this.publicKeyAlgorithm === enums.publicKey.x25519 || this.publicKeyAlgorithm === enums.publicKey.x448) {
|
|
16366
|
+
if (this.version === 3) {
|
|
16367
|
+
this.sessionKeyAlgorithm = enums.write(enums.symmetric, this.encrypted.C.algorithm);
|
|
16368
|
+
} else if (this.encrypted.C.algorithm !== null) {
|
|
16369
|
+
throw new Error('Unexpected cleartext symmetric algorithm');
|
|
16370
|
+
}
|
|
16263
16371
|
}
|
|
16264
16372
|
}
|
|
16265
16373
|
|
|
@@ -16303,10 +16411,13 @@ class PublicKeyEncryptedSessionKeyPacket {
|
|
|
16303
16411
|
*/
|
|
16304
16412
|
async encrypt(key) {
|
|
16305
16413
|
const algo = enums.write(enums.publicKey, this.publicKeyAlgorithm);
|
|
16306
|
-
|
|
16414
|
+
// No symmetric encryption algorithm identifier is passed to the public-key algorithm for a
|
|
16415
|
+
// v6 PKESK packet, as it is included in the v2 SEIPD packet.
|
|
16416
|
+
const sessionKeyAlgorithm = this.version === 3 ? this.sessionKeyAlgorithm : null;
|
|
16417
|
+
const encoded = encodeSessionKey(this.version, algo, sessionKeyAlgorithm, this.sessionKey);
|
|
16307
16418
|
const privateParams = algo === enums.publicKey.aead ? key.privateParams : null;
|
|
16308
16419
|
this.encrypted = await mod$1.publicKeyEncrypt(
|
|
16309
|
-
algo,
|
|
16420
|
+
algo, sessionKeyAlgorithm, key.publicParams, privateParams, encoded, key.getFingerprintBytes());
|
|
16310
16421
|
}
|
|
16311
16422
|
|
|
16312
16423
|
/**
|
|
@@ -16405,6 +16516,7 @@ function decodeSessionKey(version, keyAlgo, decryptedData, randomSessionKey) {
|
|
|
16405
16516
|
case enums.publicKey.x25519:
|
|
16406
16517
|
case enums.publicKey.x448:
|
|
16407
16518
|
return {
|
|
16519
|
+
sessionKeyAlgorithm: null,
|
|
16408
16520
|
sessionKey: decryptedData
|
|
16409
16521
|
};
|
|
16410
16522
|
default:
|
|
@@ -18092,7 +18204,9 @@ class Signature {
|
|
|
18092
18204
|
* @returns {ReadableStream<String>} ASCII armor.
|
|
18093
18205
|
*/
|
|
18094
18206
|
armor(config$1 = config) {
|
|
18095
|
-
|
|
18207
|
+
// An ASCII-armored sequence of Signature packets that only includes v6 Signature packets MUST NOT contain a CRC24 footer.
|
|
18208
|
+
const emitChecksum = this.packets.some(packet => packet.constructor.tag === SignaturePacket.tag && packet.version !== 6);
|
|
18209
|
+
return armor(enums.armor.signature, this.write(), undefined, undefined, undefined, emitChecksum, config$1);
|
|
18096
18210
|
}
|
|
18097
18211
|
|
|
18098
18212
|
/**
|
|
@@ -18305,7 +18419,7 @@ async function getPreferredCompressionAlgo(keys = [], date = new Date(), userIDs
|
|
|
18305
18419
|
async function getPreferredCipherSuite(keys = [], date = new Date(), userIDs = [], config$1 = config) {
|
|
18306
18420
|
const selfSigs = await Promise.all(keys.map((key, i) => key.getPrimarySelfSignature(date, userIDs[i], config$1)));
|
|
18307
18421
|
const withAEAD = keys.length ?
|
|
18308
|
-
selfSigs.every(selfSig => selfSig.features[0] & enums.features.seipdv2) :
|
|
18422
|
+
!config$1.ignoreSEIPDv2FeatureFlag && selfSigs.every(selfSig => selfSig.features && (selfSig.features[0] & enums.features.seipdv2)) :
|
|
18309
18423
|
config$1.aeadProtect;
|
|
18310
18424
|
|
|
18311
18425
|
if (withAEAD) {
|
|
@@ -18352,8 +18466,8 @@ async function createSignaturePacket(dataToSign, privateKey, signingKeyPacket, s
|
|
|
18352
18466
|
Object.assign(signaturePacket, signatureProperties);
|
|
18353
18467
|
signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
|
|
18354
18468
|
signaturePacket.hashAlgorithm = await getPreferredHashAlgo(privateKey, signingKeyPacket, date, userID, config);
|
|
18355
|
-
signaturePacket.rawNotations = notations;
|
|
18356
|
-
await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached);
|
|
18469
|
+
signaturePacket.rawNotations = [...notations];
|
|
18470
|
+
await signaturePacket.sign(signingKeyPacket, dataToSign, date, detached, config);
|
|
18357
18471
|
return signaturePacket;
|
|
18358
18472
|
}
|
|
18359
18473
|
|
|
@@ -18416,7 +18530,7 @@ async function isDataRevoked(primaryKey, signatureType, dataToVerify, revocation
|
|
|
18416
18530
|
!signature || revocationSignature.issuerKeyID.equals(signature.issuerKeyID)
|
|
18417
18531
|
) {
|
|
18418
18532
|
await revocationSignature.verify(
|
|
18419
|
-
key, signatureType, dataToVerify,
|
|
18533
|
+
key, signatureType, dataToVerify, date, false, config
|
|
18420
18534
|
);
|
|
18421
18535
|
|
|
18422
18536
|
// TODO get an identifier of the revoked object instead
|
|
@@ -19686,7 +19800,9 @@ class Key {
|
|
|
19686
19800
|
const revocationSignature = await getLatestValidSignature(this.revocationSignatures, this.keyPacket, enums.signature.keyRevocation, dataToVerify, date, config$1);
|
|
19687
19801
|
const packetlist = new PacketList();
|
|
19688
19802
|
packetlist.push(revocationSignature);
|
|
19689
|
-
|
|
19803
|
+
// An ASCII-armored Transferable Public Key packet sequence of a v6 key MUST NOT contain a CRC24 footer.
|
|
19804
|
+
const emitChecksum = this.keyPacket.version !== 6;
|
|
19805
|
+
return armor(enums.armor.publicKey, packetlist.write(), null, null, 'This is a revocation certificate', emitChecksum, config$1);
|
|
19690
19806
|
}
|
|
19691
19807
|
|
|
19692
19808
|
/**
|
|
@@ -19876,7 +19992,9 @@ class PublicKey extends Key {
|
|
|
19876
19992
|
* @returns {ReadableStream<String>} ASCII armor.
|
|
19877
19993
|
*/
|
|
19878
19994
|
armor(config$1 = config) {
|
|
19879
|
-
|
|
19995
|
+
// An ASCII-armored Transferable Public Key packet sequence of a v6 key MUST NOT contain a CRC24 footer.
|
|
19996
|
+
const emitChecksum = this.keyPacket.version !== 6;
|
|
19997
|
+
return armor(enums.armor.publicKey, this.toPacketList().write(), undefined, undefined, undefined, emitChecksum, config$1);
|
|
19880
19998
|
}
|
|
19881
19999
|
}
|
|
19882
20000
|
|
|
@@ -19949,7 +20067,9 @@ class PrivateKey extends PublicKey {
|
|
|
19949
20067
|
* @returns {ReadableStream<String>} ASCII armor.
|
|
19950
20068
|
*/
|
|
19951
20069
|
armor(config$1 = config) {
|
|
19952
|
-
|
|
20070
|
+
// An ASCII-armored Transferable Public Key packet sequence of a v6 key MUST NOT contain a CRC24 footer.
|
|
20071
|
+
const emitChecksum = this.keyPacket.version !== 6;
|
|
20072
|
+
return armor(enums.armor.privateKey, this.toPacketList().write(), undefined, undefined, undefined, emitChecksum, config$1);
|
|
19953
20073
|
}
|
|
19954
20074
|
|
|
19955
20075
|
/**
|
|
@@ -21268,7 +21388,13 @@ class Message {
|
|
|
21268
21388
|
* @returns {ReadableStream<String>} ASCII armor.
|
|
21269
21389
|
*/
|
|
21270
21390
|
armor(config$1 = config) {
|
|
21271
|
-
|
|
21391
|
+
const trailingPacket = this.packets[this.packets.length - 1];
|
|
21392
|
+
// An ASCII-armored Encrypted Message packet sequence that ends in an v2 SEIPD packet MUST NOT contain a CRC24 footer.
|
|
21393
|
+
// An ASCII-armored sequence of Signature packets that only includes v6 Signature packets MUST NOT contain a CRC24 footer.
|
|
21394
|
+
const emitChecksum = trailingPacket.constructor.tag === SymEncryptedIntegrityProtectedDataPacket.tag ?
|
|
21395
|
+
trailingPacket.version !== 2 :
|
|
21396
|
+
this.packets.some(packet => packet.constructor.tag === SignaturePacket.tag && packet.version !== 6);
|
|
21397
|
+
return armor(enums.armor.message, this.write(), null, null, null, emitChecksum, config$1);
|
|
21272
21398
|
}
|
|
21273
21399
|
}
|
|
21274
21400
|
|
|
@@ -21603,9 +21729,9 @@ class CleartextMessage {
|
|
|
21603
21729
|
* @returns {String | ReadableStream<String>} ASCII armor.
|
|
21604
21730
|
*/
|
|
21605
21731
|
armor(config$1 = config) {
|
|
21606
|
-
// emit header if one of the signatures has a version not 6
|
|
21607
|
-
const
|
|
21608
|
-
const hash =
|
|
21732
|
+
// emit header and checksum if one of the signatures has a version not 6
|
|
21733
|
+
const emitHeaderAndChecksum = this.signature.packets.some(packet => packet.version !== 6);
|
|
21734
|
+
const hash = emitHeaderAndChecksum ?
|
|
21609
21735
|
Array.from(new Set(this.signature.packets.map(
|
|
21610
21736
|
packet => enums.read(enums.hash, packet.hashAlgorithm).toUpperCase()
|
|
21611
21737
|
))).join() :
|
|
@@ -21616,7 +21742,9 @@ class CleartextMessage {
|
|
|
21616
21742
|
text: this.text,
|
|
21617
21743
|
data: this.signature.packets.write()
|
|
21618
21744
|
};
|
|
21619
|
-
|
|
21745
|
+
|
|
21746
|
+
// An ASCII-armored sequence of Signature packets that only includes v6 Signature packets MUST NOT contain a CRC24 footer.
|
|
21747
|
+
return armor(enums.armor.signed, body, undefined, undefined, undefined, emitHeaderAndChecksum, config$1);
|
|
21620
21748
|
}
|
|
21621
21749
|
}
|
|
21622
21750
|
|