@protontech/openpgp 6.1.1-patch.2 → 6.1.1-patch.3
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/legacy_ciphers.min.mjs +1 -1
- package/dist/lightweight/legacy_ciphers.mjs +1 -1
- package/dist/lightweight/noble_curves.min.mjs +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/noble_post_quantum.min.mjs +1 -1
- package/dist/lightweight/noble_post_quantum.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 +178 -95
- package/dist/lightweight/seek-bzip.min.mjs +1 -1
- package/dist/lightweight/seek-bzip.mjs +1 -1
- package/dist/lightweight/sha3.min.mjs +1 -1
- package/dist/lightweight/sha3.mjs +1 -1
- package/dist/lightweight/sha512.min.mjs +1 -1
- package/dist/lightweight/sha512.mjs +1 -1
- package/dist/node/openpgp.cjs +178 -95
- package/dist/node/openpgp.min.cjs +16 -16
- package/dist/node/openpgp.min.cjs.map +1 -1
- package/dist/node/openpgp.min.mjs +16 -16
- package/dist/node/openpgp.min.mjs.map +1 -1
- package/dist/node/openpgp.mjs +178 -95
- package/dist/openpgp.js +178 -95
- package/dist/openpgp.min.js +16 -16
- package/dist/openpgp.min.js.map +1 -1
- package/dist/openpgp.min.mjs +16 -16
- package/dist/openpgp.min.mjs.map +1 -1
- package/dist/openpgp.mjs +178 -95
- package/package.json +1 -1
- package/src/enums.d.ts +2 -2
package/dist/node/openpgp.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! OpenPGP.js v6.1.1-patch.
|
|
1
|
+
/*! OpenPGP.js v6.1.1-patch.3 - 2025-06-18 - 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 : {};
|
|
@@ -1089,11 +1089,10 @@ var enums = {
|
|
|
1089
1089
|
ed25519: 27,
|
|
1090
1090
|
/** Ed448 (Sign only) */
|
|
1091
1091
|
ed448: 28,
|
|
1092
|
-
/** Post-quantum ML-KEM-768 + X25519 (Encrypt only) */
|
|
1093
|
-
pqc_mlkem_x25519: 105,
|
|
1094
1092
|
/** Post-quantum ML-DSA-64 + Ed25519 (Sign only) */
|
|
1095
|
-
pqc_mldsa_ed25519:
|
|
1096
|
-
|
|
1093
|
+
pqc_mldsa_ed25519: 30,
|
|
1094
|
+
/** Post-quantum ML-KEM-768 + X25519 (Encrypt only) */
|
|
1095
|
+
pqc_mlkem_x25519: 35,
|
|
1097
1096
|
/** Persistent symmetric keys: encryption algorithm */
|
|
1098
1097
|
aead: 100,
|
|
1099
1098
|
/** Persistent symmetric keys: authentication algorithm */
|
|
@@ -1744,7 +1743,7 @@ var config = {
|
|
|
1744
1743
|
* @memberof module:config
|
|
1745
1744
|
* @property {String} versionString A version string to be included in armored messages
|
|
1746
1745
|
*/
|
|
1747
|
-
versionString: 'OpenPGP.js 6.1.1-patch.
|
|
1746
|
+
versionString: 'OpenPGP.js 6.1.1-patch.3',
|
|
1748
1747
|
/**
|
|
1749
1748
|
* @memberof module:config
|
|
1750
1749
|
* @property {String} commentString A comment string to be included in armored messages
|
|
@@ -6990,17 +6989,11 @@ async function generate$a(algo) {
|
|
|
6990
6989
|
* @async
|
|
6991
6990
|
*/
|
|
6992
6991
|
async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
6993
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
6994
|
-
// Enforce digest sizes:
|
|
6995
|
-
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
6996
|
-
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
6997
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
6998
|
-
}
|
|
6999
6992
|
switch (algo) {
|
|
7000
6993
|
case enums.publicKey.ed25519:
|
|
7001
6994
|
try {
|
|
7002
6995
|
const webCrypto = util.getWebCrypto();
|
|
7003
|
-
const jwk = privateKeyToJWK(algo, publicKey, privateKey);
|
|
6996
|
+
const jwk = privateKeyToJWK$1(algo, publicKey, privateKey);
|
|
7004
6997
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['sign']);
|
|
7005
6998
|
|
|
7006
6999
|
const signature = new Uint8Array(
|
|
@@ -7040,17 +7033,11 @@ async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
7040
7033
|
* @async
|
|
7041
7034
|
*/
|
|
7042
7035
|
async function verify$9(algo, hashAlgo, { RS }, m, publicKey, hashed) {
|
|
7043
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
7044
|
-
// Enforce digest sizes:
|
|
7045
|
-
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
7046
|
-
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
7047
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
7048
|
-
}
|
|
7049
7036
|
switch (algo) {
|
|
7050
7037
|
case enums.publicKey.ed25519:
|
|
7051
7038
|
try {
|
|
7052
7039
|
const webCrypto = util.getWebCrypto();
|
|
7053
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7040
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7054
7041
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['verify']);
|
|
7055
7042
|
const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
|
|
7056
7043
|
return verified;
|
|
@@ -7125,7 +7112,7 @@ function getPreferredHashAlgo$2(algo) {
|
|
|
7125
7112
|
}
|
|
7126
7113
|
}
|
|
7127
7114
|
|
|
7128
|
-
const publicKeyToJWK = (algo, publicKey) => {
|
|
7115
|
+
const publicKeyToJWK$1 = (algo, publicKey) => {
|
|
7129
7116
|
switch (algo) {
|
|
7130
7117
|
case enums.publicKey.ed25519: {
|
|
7131
7118
|
const jwk = {
|
|
@@ -7141,10 +7128,10 @@ const publicKeyToJWK = (algo, publicKey) => {
|
|
|
7141
7128
|
}
|
|
7142
7129
|
};
|
|
7143
7130
|
|
|
7144
|
-
const privateKeyToJWK = (algo, publicKey, privateKey) => {
|
|
7131
|
+
const privateKeyToJWK$1 = (algo, publicKey, privateKey) => {
|
|
7145
7132
|
switch (algo) {
|
|
7146
7133
|
case enums.publicKey.ed25519: {
|
|
7147
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7134
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7148
7135
|
jwk.d = uint8ArrayToB64(privateKey);
|
|
7149
7136
|
return jwk;
|
|
7150
7137
|
}
|
|
@@ -8384,12 +8371,27 @@ const HKDF_INFO = {
|
|
|
8384
8371
|
*/
|
|
8385
8372
|
async function generate$9(algo) {
|
|
8386
8373
|
switch (algo) {
|
|
8387
|
-
case enums.publicKey.x25519:
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8374
|
+
case enums.publicKey.x25519:
|
|
8375
|
+
try {
|
|
8376
|
+
const webCrypto = util.getWebCrypto();
|
|
8377
|
+
const webCryptoKey = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits']);
|
|
8378
|
+
|
|
8379
|
+
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
|
|
8380
|
+
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
8381
|
+
|
|
8382
|
+
return {
|
|
8383
|
+
A: new Uint8Array(b64ToUint8Array(publicKey.x)),
|
|
8384
|
+
k: b64ToUint8Array(privateKey.d)
|
|
8385
|
+
};
|
|
8386
|
+
} catch (err) {
|
|
8387
|
+
if (err.name !== 'NotSupportedError') {
|
|
8388
|
+
throw err;
|
|
8389
|
+
}
|
|
8390
|
+
// k stays in little-endian, unlike legacy ECDH over curve25519
|
|
8391
|
+
const k = getRandomBytes(32);
|
|
8392
|
+
const { publicKey: A } = nacl.box.keyPair.fromSecretKey(k);
|
|
8393
|
+
return { A, k };
|
|
8394
|
+
}
|
|
8393
8395
|
|
|
8394
8396
|
case enums.publicKey.x448: {
|
|
8395
8397
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
@@ -8531,13 +8533,32 @@ function getPayloadSize(algo) {
|
|
|
8531
8533
|
*/
|
|
8532
8534
|
async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
8533
8535
|
switch (algo) {
|
|
8534
|
-
case enums.publicKey.x25519:
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8536
|
+
case enums.publicKey.x25519:
|
|
8537
|
+
try {
|
|
8538
|
+
const webCrypto = util.getWebCrypto();
|
|
8539
|
+
const jwk = publicKeyToJWK(algo, recipientA);
|
|
8540
|
+
const ephemeralKeyPair = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits']);
|
|
8541
|
+
const recipientPublicKey = await webCrypto.importKey('jwk', jwk, 'X25519', false, []);
|
|
8542
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8543
|
+
{ name: 'X25519', public: recipientPublicKey },
|
|
8544
|
+
ephemeralKeyPair.privateKey,
|
|
8545
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8546
|
+
);
|
|
8547
|
+
const ephemeralPublicKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.publicKey);
|
|
8548
|
+
return {
|
|
8549
|
+
sharedSecret: new Uint8Array(sharedSecretBuffer),
|
|
8550
|
+
ephemeralPublicKey: new Uint8Array(b64ToUint8Array(ephemeralPublicKeyJwt.x))
|
|
8551
|
+
};
|
|
8552
|
+
} catch (err) {
|
|
8553
|
+
if (err.name !== 'NotSupportedError') {
|
|
8554
|
+
throw err;
|
|
8555
|
+
}
|
|
8556
|
+
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
|
|
8557
|
+
const sharedSecret = nacl.scalarMult(ephemeralSecretKey, recipientA);
|
|
8558
|
+
assertNonZeroArray(sharedSecret);
|
|
8559
|
+
const { publicKey: ephemeralPublicKey } = nacl.box.keyPair.fromSecretKey(ephemeralSecretKey);
|
|
8560
|
+
return { ephemeralPublicKey, sharedSecret };
|
|
8561
|
+
}
|
|
8541
8562
|
case enums.publicKey.x448: {
|
|
8542
8563
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8543
8564
|
const ephemeralSecretKey = x448.utils.randomPrivateKey();
|
|
@@ -8553,11 +8574,27 @@ async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
|
8553
8574
|
|
|
8554
8575
|
async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
|
|
8555
8576
|
switch (algo) {
|
|
8556
|
-
case enums.publicKey.x25519:
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8577
|
+
case enums.publicKey.x25519:
|
|
8578
|
+
try {
|
|
8579
|
+
const webCrypto = util.getWebCrypto();
|
|
8580
|
+
const privateKeyJWK = privateKeyToJWK(algo, A, k);
|
|
8581
|
+
const ephemeralPublicKeyJWK = publicKeyToJWK(algo, ephemeralPublicKey);
|
|
8582
|
+
const privateKey = await webCrypto.importKey('jwk', privateKeyJWK, 'X25519', false, ['deriveKey', 'deriveBits']);
|
|
8583
|
+
const ephemeralPublicKeyReference = await webCrypto.importKey('jwk', ephemeralPublicKeyJWK, 'X25519', false, []);
|
|
8584
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8585
|
+
{ name: 'X25519', public: ephemeralPublicKeyReference },
|
|
8586
|
+
privateKey,
|
|
8587
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8588
|
+
);
|
|
8589
|
+
return new Uint8Array(sharedSecretBuffer);
|
|
8590
|
+
} catch (err) {
|
|
8591
|
+
if (err.name !== 'NotSupportedError') {
|
|
8592
|
+
throw err;
|
|
8593
|
+
}
|
|
8594
|
+
const sharedSecret = nacl.scalarMult(k, ephemeralPublicKey);
|
|
8595
|
+
assertNonZeroArray(sharedSecret);
|
|
8596
|
+
return sharedSecret;
|
|
8597
|
+
}
|
|
8561
8598
|
case enums.publicKey.x448: {
|
|
8562
8599
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8563
8600
|
const sharedSecret = x448.getSharedSecret(k, ephemeralPublicKey);
|
|
@@ -8585,6 +8622,35 @@ function assertNonZeroArray(sharedSecret) {
|
|
|
8585
8622
|
}
|
|
8586
8623
|
}
|
|
8587
8624
|
|
|
8625
|
+
|
|
8626
|
+
function publicKeyToJWK(algo, publicKey) {
|
|
8627
|
+
switch (algo) {
|
|
8628
|
+
case enums.publicKey.x25519: {
|
|
8629
|
+
const jwk = {
|
|
8630
|
+
kty: 'OKP',
|
|
8631
|
+
crv: 'X25519',
|
|
8632
|
+
x: uint8ArrayToB64(publicKey),
|
|
8633
|
+
ext: true
|
|
8634
|
+
};
|
|
8635
|
+
return jwk;
|
|
8636
|
+
}
|
|
8637
|
+
default:
|
|
8638
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8639
|
+
}
|
|
8640
|
+
}
|
|
8641
|
+
|
|
8642
|
+
function privateKeyToJWK(algo, publicKey, privateKey) {
|
|
8643
|
+
switch (algo) {
|
|
8644
|
+
case enums.publicKey.x25519: {
|
|
8645
|
+
const jwk = publicKeyToJWK(algo, publicKey);
|
|
8646
|
+
jwk.d = uint8ArrayToB64(privateKey);
|
|
8647
|
+
return jwk;
|
|
8648
|
+
}
|
|
8649
|
+
default:
|
|
8650
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8651
|
+
}
|
|
8652
|
+
}
|
|
8653
|
+
|
|
8588
8654
|
var ecdh_x = /*#__PURE__*/Object.freeze({
|
|
8589
8655
|
__proto__: null,
|
|
8590
8656
|
decrypt: decrypt$4,
|
|
@@ -9292,12 +9358,6 @@ var ecdsa = /*#__PURE__*/Object.freeze({
|
|
|
9292
9358
|
async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
9293
9359
|
const curve = new CurveWithOID(oid);
|
|
9294
9360
|
checkPublicPointEnconding(curve, publicKey);
|
|
9295
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
9296
|
-
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
9297
|
-
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
9298
|
-
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
9299
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
9300
|
-
}
|
|
9301
9361
|
const { RS: signature } = await sign$9(enums.publicKey.ed25519, hashAlgo, message, publicKey.subarray(1), privateKey, hashed);
|
|
9302
9362
|
// EdDSA signature params are returned in little-endian format
|
|
9303
9363
|
return {
|
|
@@ -9321,12 +9381,6 @@ async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9321
9381
|
async function verify$7(oid, hashAlgo, { r, s }, m, publicKey, hashed) {
|
|
9322
9382
|
const curve = new CurveWithOID(oid);
|
|
9323
9383
|
checkPublicPointEnconding(curve, publicKey);
|
|
9324
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
9325
|
-
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
9326
|
-
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
9327
|
-
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
9328
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
9329
|
-
}
|
|
9330
9384
|
const RS = util.concatUint8Array([r, s]);
|
|
9331
9385
|
return verify$9(enums.publicKey.ed25519, hashAlgo, { RS }, m, publicKey.subarray(1), hashed);
|
|
9332
9386
|
}
|
|
@@ -10184,7 +10238,7 @@ async function generate$4(algo) {
|
|
|
10184
10238
|
async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
10185
10239
|
const { eccKeyShare, eccCipherText } = await encaps$1(algo, eccPublicKey);
|
|
10186
10240
|
const { mlkemKeyShare, mlkemCipherText } = await encaps(algo, mlkemPublicKey);
|
|
10187
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10241
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10188
10242
|
const wrappedKey = await wrap(enums.symmetric.aes256, kek, sessioneKeyData); // C
|
|
10189
10243
|
return { eccCipherText, mlkemCipherText, wrappedKey };
|
|
10190
10244
|
}
|
|
@@ -10192,25 +10246,24 @@ async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
|
10192
10246
|
async function decrypt$2(algo, eccCipherText, mlkemCipherText, eccSecretKey, eccPublicKey, mlkemSecretKey, mlkemPublicKey, encryptedSessionKeyData) {
|
|
10193
10247
|
const eccKeyShare = await decaps$1(algo, eccCipherText, eccSecretKey, eccPublicKey);
|
|
10194
10248
|
const mlkemKeyShare = await decaps(algo, mlkemCipherText, mlkemSecretKey);
|
|
10195
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10249
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10196
10250
|
const sessionKey = await unwrap(enums.symmetric.aes256, kek, encryptedSessionKeyData);
|
|
10197
10251
|
return sessionKey;
|
|
10198
10252
|
}
|
|
10199
10253
|
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10254
|
+
/**
|
|
10255
|
+
* KEM key combiner
|
|
10256
|
+
*/
|
|
10257
|
+
async function multiKeyCombine(algo, mlkemKeyShare, ecdhKeyShare, ecdhCipherText, ecdhPublicKey) {
|
|
10258
|
+
const domSep = util.encodeUTF8('OpenPGPCompositeKDFv1');
|
|
10204
10259
|
const encData = util.concatUint8Array([
|
|
10205
10260
|
mlkemKeyShare,
|
|
10206
10261
|
ecdhKeyShare,
|
|
10207
10262
|
ecdhCipherText,
|
|
10208
10263
|
ecdhPublicKey,
|
|
10209
|
-
// domSep
|
|
10210
|
-
mlkemCipherText,
|
|
10211
|
-
mlkemPublicKey,
|
|
10212
10264
|
new Uint8Array([algo]),
|
|
10213
|
-
|
|
10265
|
+
domSep,
|
|
10266
|
+
new Uint8Array([domSep.length])
|
|
10214
10267
|
]);
|
|
10215
10268
|
|
|
10216
10269
|
const kek = await computeDigest(enums.hash.sha3_256, encData);
|
|
@@ -10347,12 +10400,6 @@ async function generate$1(algo) {
|
|
|
10347
10400
|
}
|
|
10348
10401
|
|
|
10349
10402
|
async function sign$2(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, mldsaSecretKey, dataDigest) {
|
|
10350
|
-
if (hashAlgo !== getRequiredHashAlgo(signatureAlgo)) {
|
|
10351
|
-
// The signature hash algo MUST be set to the specified algorithm, see
|
|
10352
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
10353
|
-
throw new Error('Unexpected hash algorithm for PQC signature');
|
|
10354
|
-
}
|
|
10355
|
-
|
|
10356
10403
|
switch (signatureAlgo) {
|
|
10357
10404
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10358
10405
|
const { eccSignature } = await sign$3(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, dataDigest);
|
|
@@ -10366,12 +10413,6 @@ async function sign$2(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, mldsa
|
|
|
10366
10413
|
}
|
|
10367
10414
|
|
|
10368
10415
|
async function verify$2(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicKey, dataDigest, { eccSignature, mldsaSignature }) {
|
|
10369
|
-
if (hashAlgo !== getRequiredHashAlgo(signatureAlgo)) {
|
|
10370
|
-
// The signature hash algo MUST be set to the specified algorithm, see
|
|
10371
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
10372
|
-
throw new Error('Unexpected hash algorithm for PQC signature');
|
|
10373
|
-
}
|
|
10374
|
-
|
|
10375
10416
|
switch (signatureAlgo) {
|
|
10376
10417
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10377
10418
|
const eccVerifiedPromise = verify$3(signatureAlgo, hashAlgo, eccPublicKey, dataDigest, eccSignature);
|
|
@@ -10384,11 +10425,12 @@ async function verify$2(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicKey, d
|
|
|
10384
10425
|
}
|
|
10385
10426
|
}
|
|
10386
10427
|
|
|
10387
|
-
function
|
|
10388
|
-
//
|
|
10428
|
+
function isCompatibleHashAlgo(signatureAlgo, hashAlgo) {
|
|
10429
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
10430
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
10389
10431
|
switch (signatureAlgo) {
|
|
10390
10432
|
case enums.publicKey.pqc_mldsa_ed25519:
|
|
10391
|
-
return
|
|
10433
|
+
return getHashByteLength(hashAlgo) >= 32;
|
|
10392
10434
|
default:
|
|
10393
10435
|
throw new Error('Unsupported signature algorithm');
|
|
10394
10436
|
}
|
|
@@ -12511,6 +12553,12 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12511
12553
|
return verify$8(oid, hashAlgo, { r, s }, data, Q, hashed);
|
|
12512
12554
|
}
|
|
12513
12555
|
case enums.publicKey.eddsaLegacy: {
|
|
12556
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12557
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12558
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12559
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12560
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12561
|
+
}
|
|
12514
12562
|
const { oid, Q } = publicParams;
|
|
12515
12563
|
const curveSize = new CurveWithOID(oid).payloadSize;
|
|
12516
12564
|
// When dealing little-endian MPI data, we always need to left-pad it, as done with big-endian values:
|
|
@@ -12521,6 +12569,13 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12521
12569
|
}
|
|
12522
12570
|
case enums.publicKey.ed25519:
|
|
12523
12571
|
case enums.publicKey.ed448: {
|
|
12572
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12573
|
+
// Enforce digest sizes:
|
|
12574
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12575
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12576
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12577
|
+
}
|
|
12578
|
+
|
|
12524
12579
|
const { A } = publicParams;
|
|
12525
12580
|
return verify$9(algo, hashAlgo, signature, data, A, hashed);
|
|
12526
12581
|
}
|
|
@@ -12533,6 +12588,11 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12533
12588
|
return verify$5(algo.getValue(), keyMaterial, signature.mac.data, hashed);
|
|
12534
12589
|
}
|
|
12535
12590
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12591
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12592
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12593
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12594
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12595
|
+
}
|
|
12536
12596
|
const { eccPublicKey, mldsaPublicKey } = publicParams;
|
|
12537
12597
|
return verify$2(algo, hashAlgo, eccPublicKey, mldsaPublicKey, hashed, signature);
|
|
12538
12598
|
}
|
|
@@ -12581,12 +12641,24 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12581
12641
|
return sign$8(oid, hashAlgo, data, Q, d, hashed);
|
|
12582
12642
|
}
|
|
12583
12643
|
case enums.publicKey.eddsaLegacy: {
|
|
12644
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12645
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12646
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12647
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12648
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12649
|
+
}
|
|
12584
12650
|
const { oid, Q } = publicKeyParams;
|
|
12585
12651
|
const { seed } = privateKeyParams;
|
|
12586
12652
|
return sign$7(oid, hashAlgo, data, Q, seed, hashed);
|
|
12587
12653
|
}
|
|
12588
12654
|
case enums.publicKey.ed25519:
|
|
12589
12655
|
case enums.publicKey.ed448: {
|
|
12656
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12657
|
+
// Enforce digest sizes:
|
|
12658
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12659
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12660
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12661
|
+
}
|
|
12590
12662
|
const { A } = publicKeyParams;
|
|
12591
12663
|
const { seed } = privateKeyParams;
|
|
12592
12664
|
return sign$9(algo, hashAlgo, data, A, seed, hashed);
|
|
@@ -12598,6 +12670,11 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12598
12670
|
return { mac: new ShortByteString(mac) };
|
|
12599
12671
|
}
|
|
12600
12672
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12673
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12674
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12675
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12676
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12677
|
+
}
|
|
12601
12678
|
const { eccPublicKey } = publicKeyParams;
|
|
12602
12679
|
const { eccSecretKey, mldsaSecretKey } = privateKeyParams;
|
|
12603
12680
|
return sign$2(algo, hashAlgo, eccSecretKey, eccPublicKey, mldsaSecretKey, hashed);
|
|
@@ -16874,12 +16951,8 @@ class PublicKeyPacket {
|
|
|
16874
16951
|
throw new Error('Legacy curve25519 cannot be used with v6 keys');
|
|
16875
16952
|
}
|
|
16876
16953
|
// The composite ML-DSA + EdDSA schemes MUST be used only with v6 keys.
|
|
16877
|
-
|
|
16878
|
-
|
|
16879
|
-
this.algorithm === enums.publicKey.pqc_mldsa_ed25519 ||
|
|
16880
|
-
this.algorithm === enums.publicKey.pqc_mlkem_x25519
|
|
16881
|
-
)) {
|
|
16882
|
-
throw new Error('Unexpected key version: ML-DSA and ML-KEM algorithms can only be used with v6 keys');
|
|
16954
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
16955
|
+
throw new Error('Unexpected key version: ML-DSA algorithms can only be used with v6 keys');
|
|
16883
16956
|
}
|
|
16884
16957
|
this.publicParams = publicParams;
|
|
16885
16958
|
pos += read;
|
|
@@ -17879,11 +17952,8 @@ class SecretKeyPacket extends PublicKeyPacket {
|
|
|
17879
17952
|
)) {
|
|
17880
17953
|
throw new Error(`Cannot generate v6 keys of type 'ecc' with curve ${curve}. Generate a key of type 'curve25519' instead`);
|
|
17881
17954
|
}
|
|
17882
|
-
if (this.version !== 6 &&
|
|
17883
|
-
this.
|
|
17884
|
-
this.algorithm === enums.publicKey.pqc_mlkem_x25519
|
|
17885
|
-
)) {
|
|
17886
|
-
throw new Error(`Cannot generate v${this.version} keys of type 'pqc'. Generate a v6 key instead`);
|
|
17955
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
17956
|
+
throw new Error(`Cannot generate v${this.version} signing keys of type 'pqc'. Generate a v6 key instead`);
|
|
17887
17957
|
}
|
|
17888
17958
|
const { privateParams, publicParams } = await generateParams(this.algorithm, bits, curve, symmetric);
|
|
17889
17959
|
this.privateParams = privateParams;
|
|
@@ -18387,12 +18457,6 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
|
|
|
18387
18457
|
* @async
|
|
18388
18458
|
*/
|
|
18389
18459
|
async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Date(), targetUserIDs = [], config) {
|
|
18390
|
-
if (signingKeyPacket.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
18391
|
-
// For PQC, the returned hash algo MUST be set to the specified algorithm, see
|
|
18392
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
18393
|
-
return getRequiredHashAlgo(signingKeyPacket.algorithm);
|
|
18394
|
-
}
|
|
18395
|
-
|
|
18396
18460
|
/**
|
|
18397
18461
|
* If `preferredSenderAlgo` appears in the prefs of all recipients, we pick it; otherwise, we use the
|
|
18398
18462
|
* strongest supported algo (`defaultAlgo` is always implicitly supported by all keys).
|
|
@@ -18440,6 +18504,10 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18440
18504
|
enums.publicKey.ed448
|
|
18441
18505
|
]);
|
|
18442
18506
|
|
|
18507
|
+
const pqcAlgos = new Set([
|
|
18508
|
+
enums.publicKey.pqc_mldsa_ed25519
|
|
18509
|
+
]);
|
|
18510
|
+
|
|
18443
18511
|
if (eccAlgos.has(signingKeyPacket.algorithm)) {
|
|
18444
18512
|
// For ECC, the returned hash algo MUST be at least as strong as `preferredCurveHashAlgo`, see:
|
|
18445
18513
|
// - ECDSA: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.2-5
|
|
@@ -18462,6 +18530,21 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18462
18530
|
strongestSupportedAlgo :
|
|
18463
18531
|
preferredCurveAlgo;
|
|
18464
18532
|
}
|
|
18533
|
+
} else if (pqcAlgos.has(signingKeyPacket.algorithm)) {
|
|
18534
|
+
// For PQC, the returned hash algo MUST be at least 256 bit long, see:
|
|
18535
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4 .
|
|
18536
|
+
// Hence, we return the `preferredHashAlgo` as long as it's supported and long enough;
|
|
18537
|
+
// Otherwise, we look at the strongest supported algo, and ultimately fallback the default algo (SHA-256).
|
|
18538
|
+
const preferredSenderAlgoIsSupported = isSupportedHashAlgo(preferredSenderAlgo) && isCompatibleHashAlgo(signingKeyPacket.algorithm, preferredSenderAlgo);
|
|
18539
|
+
|
|
18540
|
+
if (preferredSenderAlgoIsSupported) {
|
|
18541
|
+
return preferredSenderAlgo;
|
|
18542
|
+
} else {
|
|
18543
|
+
const strongestSupportedAlgo = getStrongestSupportedHashAlgo();
|
|
18544
|
+
return isCompatibleHashAlgo(signingKeyPacket.algorithm, strongestSupportedAlgo) ?
|
|
18545
|
+
strongestSupportedAlgo :
|
|
18546
|
+
defaultAlgo;
|
|
18547
|
+
}
|
|
18465
18548
|
}
|
|
18466
18549
|
|
|
18467
18550
|
// `preferredSenderAlgo` may be weaker than the default, but we do not guard against this,
|