@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.mjs
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
|
const globalThis = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
3
3
|
|
|
4
4
|
import { createRequire } from 'module';
|
|
@@ -1066,11 +1066,10 @@ var enums = {
|
|
|
1066
1066
|
ed25519: 27,
|
|
1067
1067
|
/** Ed448 (Sign only) */
|
|
1068
1068
|
ed448: 28,
|
|
1069
|
-
/** Post-quantum ML-KEM-768 + X25519 (Encrypt only) */
|
|
1070
|
-
pqc_mlkem_x25519: 105,
|
|
1071
1069
|
/** Post-quantum ML-DSA-64 + Ed25519 (Sign only) */
|
|
1072
|
-
pqc_mldsa_ed25519:
|
|
1073
|
-
|
|
1070
|
+
pqc_mldsa_ed25519: 30,
|
|
1071
|
+
/** Post-quantum ML-KEM-768 + X25519 (Encrypt only) */
|
|
1072
|
+
pqc_mlkem_x25519: 35,
|
|
1074
1073
|
/** Persistent symmetric keys: encryption algorithm */
|
|
1075
1074
|
aead: 100,
|
|
1076
1075
|
/** Persistent symmetric keys: authentication algorithm */
|
|
@@ -1721,7 +1720,7 @@ var config = {
|
|
|
1721
1720
|
* @memberof module:config
|
|
1722
1721
|
* @property {String} versionString A version string to be included in armored messages
|
|
1723
1722
|
*/
|
|
1724
|
-
versionString: 'OpenPGP.js 6.1.1-patch.
|
|
1723
|
+
versionString: 'OpenPGP.js 6.1.1-patch.3',
|
|
1725
1724
|
/**
|
|
1726
1725
|
* @memberof module:config
|
|
1727
1726
|
* @property {String} commentString A comment string to be included in armored messages
|
|
@@ -6967,17 +6966,11 @@ async function generate$a(algo) {
|
|
|
6967
6966
|
* @async
|
|
6968
6967
|
*/
|
|
6969
6968
|
async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
6970
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
6971
|
-
// Enforce digest sizes:
|
|
6972
|
-
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
6973
|
-
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
6974
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
6975
|
-
}
|
|
6976
6969
|
switch (algo) {
|
|
6977
6970
|
case enums.publicKey.ed25519:
|
|
6978
6971
|
try {
|
|
6979
6972
|
const webCrypto = util.getWebCrypto();
|
|
6980
|
-
const jwk = privateKeyToJWK(algo, publicKey, privateKey);
|
|
6973
|
+
const jwk = privateKeyToJWK$1(algo, publicKey, privateKey);
|
|
6981
6974
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['sign']);
|
|
6982
6975
|
|
|
6983
6976
|
const signature = new Uint8Array(
|
|
@@ -7017,17 +7010,11 @@ async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
7017
7010
|
* @async
|
|
7018
7011
|
*/
|
|
7019
7012
|
async function verify$9(algo, hashAlgo, { RS }, m, publicKey, hashed) {
|
|
7020
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
7021
|
-
// Enforce digest sizes:
|
|
7022
|
-
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
7023
|
-
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
7024
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
7025
|
-
}
|
|
7026
7013
|
switch (algo) {
|
|
7027
7014
|
case enums.publicKey.ed25519:
|
|
7028
7015
|
try {
|
|
7029
7016
|
const webCrypto = util.getWebCrypto();
|
|
7030
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7017
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7031
7018
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['verify']);
|
|
7032
7019
|
const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
|
|
7033
7020
|
return verified;
|
|
@@ -7102,7 +7089,7 @@ function getPreferredHashAlgo$2(algo) {
|
|
|
7102
7089
|
}
|
|
7103
7090
|
}
|
|
7104
7091
|
|
|
7105
|
-
const publicKeyToJWK = (algo, publicKey) => {
|
|
7092
|
+
const publicKeyToJWK$1 = (algo, publicKey) => {
|
|
7106
7093
|
switch (algo) {
|
|
7107
7094
|
case enums.publicKey.ed25519: {
|
|
7108
7095
|
const jwk = {
|
|
@@ -7118,10 +7105,10 @@ const publicKeyToJWK = (algo, publicKey) => {
|
|
|
7118
7105
|
}
|
|
7119
7106
|
};
|
|
7120
7107
|
|
|
7121
|
-
const privateKeyToJWK = (algo, publicKey, privateKey) => {
|
|
7108
|
+
const privateKeyToJWK$1 = (algo, publicKey, privateKey) => {
|
|
7122
7109
|
switch (algo) {
|
|
7123
7110
|
case enums.publicKey.ed25519: {
|
|
7124
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7111
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7125
7112
|
jwk.d = uint8ArrayToB64(privateKey);
|
|
7126
7113
|
return jwk;
|
|
7127
7114
|
}
|
|
@@ -8361,12 +8348,27 @@ const HKDF_INFO = {
|
|
|
8361
8348
|
*/
|
|
8362
8349
|
async function generate$9(algo) {
|
|
8363
8350
|
switch (algo) {
|
|
8364
|
-
case enums.publicKey.x25519:
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8351
|
+
case enums.publicKey.x25519:
|
|
8352
|
+
try {
|
|
8353
|
+
const webCrypto = util.getWebCrypto();
|
|
8354
|
+
const webCryptoKey = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits']);
|
|
8355
|
+
|
|
8356
|
+
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
|
|
8357
|
+
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
8358
|
+
|
|
8359
|
+
return {
|
|
8360
|
+
A: new Uint8Array(b64ToUint8Array(publicKey.x)),
|
|
8361
|
+
k: b64ToUint8Array(privateKey.d)
|
|
8362
|
+
};
|
|
8363
|
+
} catch (err) {
|
|
8364
|
+
if (err.name !== 'NotSupportedError') {
|
|
8365
|
+
throw err;
|
|
8366
|
+
}
|
|
8367
|
+
// k stays in little-endian, unlike legacy ECDH over curve25519
|
|
8368
|
+
const k = getRandomBytes(32);
|
|
8369
|
+
const { publicKey: A } = nacl.box.keyPair.fromSecretKey(k);
|
|
8370
|
+
return { A, k };
|
|
8371
|
+
}
|
|
8370
8372
|
|
|
8371
8373
|
case enums.publicKey.x448: {
|
|
8372
8374
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
@@ -8508,13 +8510,32 @@ function getPayloadSize(algo) {
|
|
|
8508
8510
|
*/
|
|
8509
8511
|
async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
8510
8512
|
switch (algo) {
|
|
8511
|
-
case enums.publicKey.x25519:
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8513
|
+
case enums.publicKey.x25519:
|
|
8514
|
+
try {
|
|
8515
|
+
const webCrypto = util.getWebCrypto();
|
|
8516
|
+
const jwk = publicKeyToJWK(algo, recipientA);
|
|
8517
|
+
const ephemeralKeyPair = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits']);
|
|
8518
|
+
const recipientPublicKey = await webCrypto.importKey('jwk', jwk, 'X25519', false, []);
|
|
8519
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8520
|
+
{ name: 'X25519', public: recipientPublicKey },
|
|
8521
|
+
ephemeralKeyPair.privateKey,
|
|
8522
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8523
|
+
);
|
|
8524
|
+
const ephemeralPublicKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.publicKey);
|
|
8525
|
+
return {
|
|
8526
|
+
sharedSecret: new Uint8Array(sharedSecretBuffer),
|
|
8527
|
+
ephemeralPublicKey: new Uint8Array(b64ToUint8Array(ephemeralPublicKeyJwt.x))
|
|
8528
|
+
};
|
|
8529
|
+
} catch (err) {
|
|
8530
|
+
if (err.name !== 'NotSupportedError') {
|
|
8531
|
+
throw err;
|
|
8532
|
+
}
|
|
8533
|
+
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
|
|
8534
|
+
const sharedSecret = nacl.scalarMult(ephemeralSecretKey, recipientA);
|
|
8535
|
+
assertNonZeroArray(sharedSecret);
|
|
8536
|
+
const { publicKey: ephemeralPublicKey } = nacl.box.keyPair.fromSecretKey(ephemeralSecretKey);
|
|
8537
|
+
return { ephemeralPublicKey, sharedSecret };
|
|
8538
|
+
}
|
|
8518
8539
|
case enums.publicKey.x448: {
|
|
8519
8540
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8520
8541
|
const ephemeralSecretKey = x448.utils.randomPrivateKey();
|
|
@@ -8530,11 +8551,27 @@ async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
|
8530
8551
|
|
|
8531
8552
|
async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
|
|
8532
8553
|
switch (algo) {
|
|
8533
|
-
case enums.publicKey.x25519:
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8554
|
+
case enums.publicKey.x25519:
|
|
8555
|
+
try {
|
|
8556
|
+
const webCrypto = util.getWebCrypto();
|
|
8557
|
+
const privateKeyJWK = privateKeyToJWK(algo, A, k);
|
|
8558
|
+
const ephemeralPublicKeyJWK = publicKeyToJWK(algo, ephemeralPublicKey);
|
|
8559
|
+
const privateKey = await webCrypto.importKey('jwk', privateKeyJWK, 'X25519', false, ['deriveKey', 'deriveBits']);
|
|
8560
|
+
const ephemeralPublicKeyReference = await webCrypto.importKey('jwk', ephemeralPublicKeyJWK, 'X25519', false, []);
|
|
8561
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8562
|
+
{ name: 'X25519', public: ephemeralPublicKeyReference },
|
|
8563
|
+
privateKey,
|
|
8564
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8565
|
+
);
|
|
8566
|
+
return new Uint8Array(sharedSecretBuffer);
|
|
8567
|
+
} catch (err) {
|
|
8568
|
+
if (err.name !== 'NotSupportedError') {
|
|
8569
|
+
throw err;
|
|
8570
|
+
}
|
|
8571
|
+
const sharedSecret = nacl.scalarMult(k, ephemeralPublicKey);
|
|
8572
|
+
assertNonZeroArray(sharedSecret);
|
|
8573
|
+
return sharedSecret;
|
|
8574
|
+
}
|
|
8538
8575
|
case enums.publicKey.x448: {
|
|
8539
8576
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8540
8577
|
const sharedSecret = x448.getSharedSecret(k, ephemeralPublicKey);
|
|
@@ -8562,6 +8599,35 @@ function assertNonZeroArray(sharedSecret) {
|
|
|
8562
8599
|
}
|
|
8563
8600
|
}
|
|
8564
8601
|
|
|
8602
|
+
|
|
8603
|
+
function publicKeyToJWK(algo, publicKey) {
|
|
8604
|
+
switch (algo) {
|
|
8605
|
+
case enums.publicKey.x25519: {
|
|
8606
|
+
const jwk = {
|
|
8607
|
+
kty: 'OKP',
|
|
8608
|
+
crv: 'X25519',
|
|
8609
|
+
x: uint8ArrayToB64(publicKey),
|
|
8610
|
+
ext: true
|
|
8611
|
+
};
|
|
8612
|
+
return jwk;
|
|
8613
|
+
}
|
|
8614
|
+
default:
|
|
8615
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8616
|
+
}
|
|
8617
|
+
}
|
|
8618
|
+
|
|
8619
|
+
function privateKeyToJWK(algo, publicKey, privateKey) {
|
|
8620
|
+
switch (algo) {
|
|
8621
|
+
case enums.publicKey.x25519: {
|
|
8622
|
+
const jwk = publicKeyToJWK(algo, publicKey);
|
|
8623
|
+
jwk.d = uint8ArrayToB64(privateKey);
|
|
8624
|
+
return jwk;
|
|
8625
|
+
}
|
|
8626
|
+
default:
|
|
8627
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8628
|
+
}
|
|
8629
|
+
}
|
|
8630
|
+
|
|
8565
8631
|
var ecdh_x = /*#__PURE__*/Object.freeze({
|
|
8566
8632
|
__proto__: null,
|
|
8567
8633
|
decrypt: decrypt$4,
|
|
@@ -9269,12 +9335,6 @@ var ecdsa = /*#__PURE__*/Object.freeze({
|
|
|
9269
9335
|
async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
9270
9336
|
const curve = new CurveWithOID(oid);
|
|
9271
9337
|
checkPublicPointEnconding(curve, publicKey);
|
|
9272
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
9273
|
-
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
9274
|
-
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
9275
|
-
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
9276
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
9277
|
-
}
|
|
9278
9338
|
const { RS: signature } = await sign$9(enums.publicKey.ed25519, hashAlgo, message, publicKey.subarray(1), privateKey, hashed);
|
|
9279
9339
|
// EdDSA signature params are returned in little-endian format
|
|
9280
9340
|
return {
|
|
@@ -9298,12 +9358,6 @@ async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9298
9358
|
async function verify$7(oid, hashAlgo, { r, s }, m, publicKey, hashed) {
|
|
9299
9359
|
const curve = new CurveWithOID(oid);
|
|
9300
9360
|
checkPublicPointEnconding(curve, publicKey);
|
|
9301
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
9302
|
-
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
9303
|
-
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
9304
|
-
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
9305
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
9306
|
-
}
|
|
9307
9361
|
const RS = util.concatUint8Array([r, s]);
|
|
9308
9362
|
return verify$9(enums.publicKey.ed25519, hashAlgo, { RS }, m, publicKey.subarray(1), hashed);
|
|
9309
9363
|
}
|
|
@@ -10161,7 +10215,7 @@ async function generate$4(algo) {
|
|
|
10161
10215
|
async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
10162
10216
|
const { eccKeyShare, eccCipherText } = await encaps$1(algo, eccPublicKey);
|
|
10163
10217
|
const { mlkemKeyShare, mlkemCipherText } = await encaps(algo, mlkemPublicKey);
|
|
10164
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10218
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10165
10219
|
const wrappedKey = await wrap(enums.symmetric.aes256, kek, sessioneKeyData); // C
|
|
10166
10220
|
return { eccCipherText, mlkemCipherText, wrappedKey };
|
|
10167
10221
|
}
|
|
@@ -10169,25 +10223,24 @@ async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
|
10169
10223
|
async function decrypt$2(algo, eccCipherText, mlkemCipherText, eccSecretKey, eccPublicKey, mlkemSecretKey, mlkemPublicKey, encryptedSessionKeyData) {
|
|
10170
10224
|
const eccKeyShare = await decaps$1(algo, eccCipherText, eccSecretKey, eccPublicKey);
|
|
10171
10225
|
const mlkemKeyShare = await decaps(algo, mlkemCipherText, mlkemSecretKey);
|
|
10172
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10226
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10173
10227
|
const sessionKey = await unwrap(enums.symmetric.aes256, kek, encryptedSessionKeyData);
|
|
10174
10228
|
return sessionKey;
|
|
10175
10229
|
}
|
|
10176
10230
|
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10231
|
+
/**
|
|
10232
|
+
* KEM key combiner
|
|
10233
|
+
*/
|
|
10234
|
+
async function multiKeyCombine(algo, mlkemKeyShare, ecdhKeyShare, ecdhCipherText, ecdhPublicKey) {
|
|
10235
|
+
const domSep = util.encodeUTF8('OpenPGPCompositeKDFv1');
|
|
10181
10236
|
const encData = util.concatUint8Array([
|
|
10182
10237
|
mlkemKeyShare,
|
|
10183
10238
|
ecdhKeyShare,
|
|
10184
10239
|
ecdhCipherText,
|
|
10185
10240
|
ecdhPublicKey,
|
|
10186
|
-
// domSep
|
|
10187
|
-
mlkemCipherText,
|
|
10188
|
-
mlkemPublicKey,
|
|
10189
10241
|
new Uint8Array([algo]),
|
|
10190
|
-
|
|
10242
|
+
domSep,
|
|
10243
|
+
new Uint8Array([domSep.length])
|
|
10191
10244
|
]);
|
|
10192
10245
|
|
|
10193
10246
|
const kek = await computeDigest(enums.hash.sha3_256, encData);
|
|
@@ -10324,12 +10377,6 @@ async function generate$1(algo) {
|
|
|
10324
10377
|
}
|
|
10325
10378
|
|
|
10326
10379
|
async function sign$2(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, mldsaSecretKey, dataDigest) {
|
|
10327
|
-
if (hashAlgo !== getRequiredHashAlgo(signatureAlgo)) {
|
|
10328
|
-
// The signature hash algo MUST be set to the specified algorithm, see
|
|
10329
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
10330
|
-
throw new Error('Unexpected hash algorithm for PQC signature');
|
|
10331
|
-
}
|
|
10332
|
-
|
|
10333
10380
|
switch (signatureAlgo) {
|
|
10334
10381
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10335
10382
|
const { eccSignature } = await sign$3(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, dataDigest);
|
|
@@ -10343,12 +10390,6 @@ async function sign$2(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, mldsa
|
|
|
10343
10390
|
}
|
|
10344
10391
|
|
|
10345
10392
|
async function verify$2(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicKey, dataDigest, { eccSignature, mldsaSignature }) {
|
|
10346
|
-
if (hashAlgo !== getRequiredHashAlgo(signatureAlgo)) {
|
|
10347
|
-
// The signature hash algo MUST be set to the specified algorithm, see
|
|
10348
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
10349
|
-
throw new Error('Unexpected hash algorithm for PQC signature');
|
|
10350
|
-
}
|
|
10351
|
-
|
|
10352
10393
|
switch (signatureAlgo) {
|
|
10353
10394
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10354
10395
|
const eccVerifiedPromise = verify$3(signatureAlgo, hashAlgo, eccPublicKey, dataDigest, eccSignature);
|
|
@@ -10361,11 +10402,12 @@ async function verify$2(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicKey, d
|
|
|
10361
10402
|
}
|
|
10362
10403
|
}
|
|
10363
10404
|
|
|
10364
|
-
function
|
|
10365
|
-
//
|
|
10405
|
+
function isCompatibleHashAlgo(signatureAlgo, hashAlgo) {
|
|
10406
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
10407
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
10366
10408
|
switch (signatureAlgo) {
|
|
10367
10409
|
case enums.publicKey.pqc_mldsa_ed25519:
|
|
10368
|
-
return
|
|
10410
|
+
return getHashByteLength(hashAlgo) >= 32;
|
|
10369
10411
|
default:
|
|
10370
10412
|
throw new Error('Unsupported signature algorithm');
|
|
10371
10413
|
}
|
|
@@ -12488,6 +12530,12 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12488
12530
|
return verify$8(oid, hashAlgo, { r, s }, data, Q, hashed);
|
|
12489
12531
|
}
|
|
12490
12532
|
case enums.publicKey.eddsaLegacy: {
|
|
12533
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12534
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12535
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12536
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12537
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12538
|
+
}
|
|
12491
12539
|
const { oid, Q } = publicParams;
|
|
12492
12540
|
const curveSize = new CurveWithOID(oid).payloadSize;
|
|
12493
12541
|
// When dealing little-endian MPI data, we always need to left-pad it, as done with big-endian values:
|
|
@@ -12498,6 +12546,13 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12498
12546
|
}
|
|
12499
12547
|
case enums.publicKey.ed25519:
|
|
12500
12548
|
case enums.publicKey.ed448: {
|
|
12549
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12550
|
+
// Enforce digest sizes:
|
|
12551
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12552
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12553
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12554
|
+
}
|
|
12555
|
+
|
|
12501
12556
|
const { A } = publicParams;
|
|
12502
12557
|
return verify$9(algo, hashAlgo, signature, data, A, hashed);
|
|
12503
12558
|
}
|
|
@@ -12510,6 +12565,11 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12510
12565
|
return verify$5(algo.getValue(), keyMaterial, signature.mac.data, hashed);
|
|
12511
12566
|
}
|
|
12512
12567
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12568
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12569
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12570
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12571
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12572
|
+
}
|
|
12513
12573
|
const { eccPublicKey, mldsaPublicKey } = publicParams;
|
|
12514
12574
|
return verify$2(algo, hashAlgo, eccPublicKey, mldsaPublicKey, hashed, signature);
|
|
12515
12575
|
}
|
|
@@ -12558,12 +12618,24 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12558
12618
|
return sign$8(oid, hashAlgo, data, Q, d, hashed);
|
|
12559
12619
|
}
|
|
12560
12620
|
case enums.publicKey.eddsaLegacy: {
|
|
12621
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12622
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12623
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12624
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12625
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12626
|
+
}
|
|
12561
12627
|
const { oid, Q } = publicKeyParams;
|
|
12562
12628
|
const { seed } = privateKeyParams;
|
|
12563
12629
|
return sign$7(oid, hashAlgo, data, Q, seed, hashed);
|
|
12564
12630
|
}
|
|
12565
12631
|
case enums.publicKey.ed25519:
|
|
12566
12632
|
case enums.publicKey.ed448: {
|
|
12633
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12634
|
+
// Enforce digest sizes:
|
|
12635
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12636
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12637
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12638
|
+
}
|
|
12567
12639
|
const { A } = publicKeyParams;
|
|
12568
12640
|
const { seed } = privateKeyParams;
|
|
12569
12641
|
return sign$9(algo, hashAlgo, data, A, seed, hashed);
|
|
@@ -12575,6 +12647,11 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12575
12647
|
return { mac: new ShortByteString(mac) };
|
|
12576
12648
|
}
|
|
12577
12649
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12650
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12651
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12652
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12653
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12654
|
+
}
|
|
12578
12655
|
const { eccPublicKey } = publicKeyParams;
|
|
12579
12656
|
const { eccSecretKey, mldsaSecretKey } = privateKeyParams;
|
|
12580
12657
|
return sign$2(algo, hashAlgo, eccSecretKey, eccPublicKey, mldsaSecretKey, hashed);
|
|
@@ -16851,12 +16928,8 @@ class PublicKeyPacket {
|
|
|
16851
16928
|
throw new Error('Legacy curve25519 cannot be used with v6 keys');
|
|
16852
16929
|
}
|
|
16853
16930
|
// The composite ML-DSA + EdDSA schemes MUST be used only with v6 keys.
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
this.algorithm === enums.publicKey.pqc_mldsa_ed25519 ||
|
|
16857
|
-
this.algorithm === enums.publicKey.pqc_mlkem_x25519
|
|
16858
|
-
)) {
|
|
16859
|
-
throw new Error('Unexpected key version: ML-DSA and ML-KEM algorithms can only be used with v6 keys');
|
|
16931
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
16932
|
+
throw new Error('Unexpected key version: ML-DSA algorithms can only be used with v6 keys');
|
|
16860
16933
|
}
|
|
16861
16934
|
this.publicParams = publicParams;
|
|
16862
16935
|
pos += read;
|
|
@@ -17856,11 +17929,8 @@ class SecretKeyPacket extends PublicKeyPacket {
|
|
|
17856
17929
|
)) {
|
|
17857
17930
|
throw new Error(`Cannot generate v6 keys of type 'ecc' with curve ${curve}. Generate a key of type 'curve25519' instead`);
|
|
17858
17931
|
}
|
|
17859
|
-
if (this.version !== 6 &&
|
|
17860
|
-
this.
|
|
17861
|
-
this.algorithm === enums.publicKey.pqc_mlkem_x25519
|
|
17862
|
-
)) {
|
|
17863
|
-
throw new Error(`Cannot generate v${this.version} keys of type 'pqc'. Generate a v6 key instead`);
|
|
17932
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
17933
|
+
throw new Error(`Cannot generate v${this.version} signing keys of type 'pqc'. Generate a v6 key instead`);
|
|
17864
17934
|
}
|
|
17865
17935
|
const { privateParams, publicParams } = await generateParams(this.algorithm, bits, curve, symmetric);
|
|
17866
17936
|
this.privateParams = privateParams;
|
|
@@ -18364,12 +18434,6 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
|
|
|
18364
18434
|
* @async
|
|
18365
18435
|
*/
|
|
18366
18436
|
async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Date(), targetUserIDs = [], config) {
|
|
18367
|
-
if (signingKeyPacket.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
18368
|
-
// For PQC, the returned hash algo MUST be set to the specified algorithm, see
|
|
18369
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
18370
|
-
return getRequiredHashAlgo(signingKeyPacket.algorithm);
|
|
18371
|
-
}
|
|
18372
|
-
|
|
18373
18437
|
/**
|
|
18374
18438
|
* If `preferredSenderAlgo` appears in the prefs of all recipients, we pick it; otherwise, we use the
|
|
18375
18439
|
* strongest supported algo (`defaultAlgo` is always implicitly supported by all keys).
|
|
@@ -18417,6 +18481,10 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18417
18481
|
enums.publicKey.ed448
|
|
18418
18482
|
]);
|
|
18419
18483
|
|
|
18484
|
+
const pqcAlgos = new Set([
|
|
18485
|
+
enums.publicKey.pqc_mldsa_ed25519
|
|
18486
|
+
]);
|
|
18487
|
+
|
|
18420
18488
|
if (eccAlgos.has(signingKeyPacket.algorithm)) {
|
|
18421
18489
|
// For ECC, the returned hash algo MUST be at least as strong as `preferredCurveHashAlgo`, see:
|
|
18422
18490
|
// - ECDSA: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.2-5
|
|
@@ -18439,6 +18507,21 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18439
18507
|
strongestSupportedAlgo :
|
|
18440
18508
|
preferredCurveAlgo;
|
|
18441
18509
|
}
|
|
18510
|
+
} else if (pqcAlgos.has(signingKeyPacket.algorithm)) {
|
|
18511
|
+
// For PQC, the returned hash algo MUST be at least 256 bit long, see:
|
|
18512
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4 .
|
|
18513
|
+
// Hence, we return the `preferredHashAlgo` as long as it's supported and long enough;
|
|
18514
|
+
// Otherwise, we look at the strongest supported algo, and ultimately fallback the default algo (SHA-256).
|
|
18515
|
+
const preferredSenderAlgoIsSupported = isSupportedHashAlgo(preferredSenderAlgo) && isCompatibleHashAlgo(signingKeyPacket.algorithm, preferredSenderAlgo);
|
|
18516
|
+
|
|
18517
|
+
if (preferredSenderAlgoIsSupported) {
|
|
18518
|
+
return preferredSenderAlgo;
|
|
18519
|
+
} else {
|
|
18520
|
+
const strongestSupportedAlgo = getStrongestSupportedHashAlgo();
|
|
18521
|
+
return isCompatibleHashAlgo(signingKeyPacket.algorithm, strongestSupportedAlgo) ?
|
|
18522
|
+
strongestSupportedAlgo :
|
|
18523
|
+
defaultAlgo;
|
|
18524
|
+
}
|
|
18442
18525
|
}
|
|
18443
18526
|
|
|
18444
18527
|
// `preferredSenderAlgo` may be weaker than the default, but we do not guard against this,
|