@protontech/openpgp 6.1.1-patch.2 → 6.1.1-patch.4
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 +216 -97
- 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 +216 -97
- 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 +216 -97
- package/dist/openpgp.js +216 -97
- 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 +216 -97
- 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.4 - 2025-07-14 - 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.4',
|
|
1725
1724
|
/**
|
|
1726
1725
|
* @memberof module:config
|
|
1727
1726
|
* @property {String} commentString A comment string to be included in armored messages
|
|
@@ -6924,7 +6923,15 @@ async function generate$a(algo) {
|
|
|
6924
6923
|
case enums.publicKey.ed25519:
|
|
6925
6924
|
try {
|
|
6926
6925
|
const webCrypto = util.getWebCrypto();
|
|
6927
|
-
const webCryptoKey = await webCrypto.generateKey('Ed25519', true, ['sign', 'verify'])
|
|
6926
|
+
const webCryptoKey = await webCrypto.generateKey('Ed25519', true, ['sign', 'verify'])
|
|
6927
|
+
.catch(err => {
|
|
6928
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
6929
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
6930
|
+
newErr.name = 'NotSupportedError';
|
|
6931
|
+
throw newErr;
|
|
6932
|
+
}
|
|
6933
|
+
throw err;
|
|
6934
|
+
});
|
|
6928
6935
|
|
|
6929
6936
|
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
|
|
6930
6937
|
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
@@ -6934,7 +6941,7 @@ async function generate$a(algo) {
|
|
|
6934
6941
|
seed: b64ToUint8Array(privateKey.d, true)
|
|
6935
6942
|
};
|
|
6936
6943
|
} catch (err) {
|
|
6937
|
-
if (err.name !== 'NotSupportedError'
|
|
6944
|
+
if (err.name !== 'NotSupportedError') {
|
|
6938
6945
|
throw err;
|
|
6939
6946
|
}
|
|
6940
6947
|
const seed = getRandomBytes(getPayloadSize$1(algo));
|
|
@@ -6967,17 +6974,11 @@ async function generate$a(algo) {
|
|
|
6967
6974
|
* @async
|
|
6968
6975
|
*/
|
|
6969
6976
|
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
6977
|
switch (algo) {
|
|
6977
6978
|
case enums.publicKey.ed25519:
|
|
6978
6979
|
try {
|
|
6979
6980
|
const webCrypto = util.getWebCrypto();
|
|
6980
|
-
const jwk = privateKeyToJWK(algo, publicKey, privateKey);
|
|
6981
|
+
const jwk = privateKeyToJWK$1(algo, publicKey, privateKey);
|
|
6981
6982
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['sign']);
|
|
6982
6983
|
|
|
6983
6984
|
const signature = new Uint8Array(
|
|
@@ -7017,17 +7018,11 @@ async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
7017
7018
|
* @async
|
|
7018
7019
|
*/
|
|
7019
7020
|
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
7021
|
switch (algo) {
|
|
7027
7022
|
case enums.publicKey.ed25519:
|
|
7028
7023
|
try {
|
|
7029
7024
|
const webCrypto = util.getWebCrypto();
|
|
7030
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7025
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7031
7026
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['verify']);
|
|
7032
7027
|
const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
|
|
7033
7028
|
return verified;
|
|
@@ -7102,7 +7097,7 @@ function getPreferredHashAlgo$2(algo) {
|
|
|
7102
7097
|
}
|
|
7103
7098
|
}
|
|
7104
7099
|
|
|
7105
|
-
const publicKeyToJWK = (algo, publicKey) => {
|
|
7100
|
+
const publicKeyToJWK$1 = (algo, publicKey) => {
|
|
7106
7101
|
switch (algo) {
|
|
7107
7102
|
case enums.publicKey.ed25519: {
|
|
7108
7103
|
const jwk = {
|
|
@@ -7118,10 +7113,10 @@ const publicKeyToJWK = (algo, publicKey) => {
|
|
|
7118
7113
|
}
|
|
7119
7114
|
};
|
|
7120
7115
|
|
|
7121
|
-
const privateKeyToJWK = (algo, publicKey, privateKey) => {
|
|
7116
|
+
const privateKeyToJWK$1 = (algo, publicKey, privateKey) => {
|
|
7122
7117
|
switch (algo) {
|
|
7123
7118
|
case enums.publicKey.ed25519: {
|
|
7124
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7119
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7125
7120
|
jwk.d = uint8ArrayToB64(privateKey);
|
|
7126
7121
|
return jwk;
|
|
7127
7122
|
}
|
|
@@ -8361,12 +8356,41 @@ const HKDF_INFO = {
|
|
|
8361
8356
|
*/
|
|
8362
8357
|
async function generate$9(algo) {
|
|
8363
8358
|
switch (algo) {
|
|
8364
|
-
case enums.publicKey.x25519:
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8359
|
+
case enums.publicKey.x25519:
|
|
8360
|
+
try {
|
|
8361
|
+
const webCrypto = util.getWebCrypto();
|
|
8362
|
+
const webCryptoKey = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits'])
|
|
8363
|
+
.catch(err => {
|
|
8364
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
8365
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
8366
|
+
newErr.name = 'NotSupportedError';
|
|
8367
|
+
throw newErr;
|
|
8368
|
+
}
|
|
8369
|
+
throw err;
|
|
8370
|
+
});
|
|
8371
|
+
|
|
8372
|
+
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
|
|
8373
|
+
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
8374
|
+
|
|
8375
|
+
if (privateKey.x !== publicKey.x) { // Weird issue with Webkit on Linux: https://bugs.webkit.org/show_bug.cgi?id=289693
|
|
8376
|
+
const err = new Error('Unexpected mismatching public point');
|
|
8377
|
+
err.name = 'NotSupportedError';
|
|
8378
|
+
throw err;
|
|
8379
|
+
}
|
|
8380
|
+
|
|
8381
|
+
return {
|
|
8382
|
+
A: new Uint8Array(b64ToUint8Array(publicKey.x)),
|
|
8383
|
+
k: b64ToUint8Array(privateKey.d)
|
|
8384
|
+
};
|
|
8385
|
+
} catch (err) {
|
|
8386
|
+
if (err.name !== 'NotSupportedError') {
|
|
8387
|
+
throw err;
|
|
8388
|
+
}
|
|
8389
|
+
// k stays in little-endian, unlike legacy ECDH over curve25519
|
|
8390
|
+
const k = getRandomBytes(32);
|
|
8391
|
+
const { publicKey: A } = nacl.box.keyPair.fromSecretKey(k);
|
|
8392
|
+
return { A, k };
|
|
8393
|
+
}
|
|
8370
8394
|
|
|
8371
8395
|
case enums.publicKey.x448: {
|
|
8372
8396
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
@@ -8508,13 +8532,46 @@ function getPayloadSize(algo) {
|
|
|
8508
8532
|
*/
|
|
8509
8533
|
async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
8510
8534
|
switch (algo) {
|
|
8511
|
-
case enums.publicKey.x25519:
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8535
|
+
case enums.publicKey.x25519:
|
|
8536
|
+
try {
|
|
8537
|
+
const webCrypto = util.getWebCrypto();
|
|
8538
|
+
const ephemeralKeyPair = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits'])
|
|
8539
|
+
.catch(err => {
|
|
8540
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
8541
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
8542
|
+
newErr.name = 'NotSupportedError';
|
|
8543
|
+
throw newErr;
|
|
8544
|
+
}
|
|
8545
|
+
throw err;
|
|
8546
|
+
});
|
|
8547
|
+
const ephemeralPublicKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.publicKey);
|
|
8548
|
+
const ephemeralPrivateKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.privateKey);
|
|
8549
|
+
if (ephemeralPrivateKeyJwt.x !== ephemeralPublicKeyJwt.x) { // Weird issue with Webkit on Linux: https://bugs.webkit.org/show_bug.cgi?id=289693
|
|
8550
|
+
const err = new Error('Unexpected mismatching public point');
|
|
8551
|
+
err.name = 'NotSupportedError';
|
|
8552
|
+
throw err;
|
|
8553
|
+
}
|
|
8554
|
+
const jwk = publicKeyToJWK(algo, recipientA);
|
|
8555
|
+
const recipientPublicKey = await webCrypto.importKey('jwk', jwk, 'X25519', false, []);
|
|
8556
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8557
|
+
{ name: 'X25519', public: recipientPublicKey },
|
|
8558
|
+
ephemeralKeyPair.privateKey,
|
|
8559
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8560
|
+
);
|
|
8561
|
+
return {
|
|
8562
|
+
sharedSecret: new Uint8Array(sharedSecretBuffer),
|
|
8563
|
+
ephemeralPublicKey: new Uint8Array(b64ToUint8Array(ephemeralPublicKeyJwt.x))
|
|
8564
|
+
};
|
|
8565
|
+
} catch (err) {
|
|
8566
|
+
if (err.name !== 'NotSupportedError') {
|
|
8567
|
+
throw err;
|
|
8568
|
+
}
|
|
8569
|
+
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
|
|
8570
|
+
const sharedSecret = nacl.scalarMult(ephemeralSecretKey, recipientA);
|
|
8571
|
+
assertNonZeroArray(sharedSecret);
|
|
8572
|
+
const { publicKey: ephemeralPublicKey } = nacl.box.keyPair.fromSecretKey(ephemeralSecretKey);
|
|
8573
|
+
return { ephemeralPublicKey, sharedSecret };
|
|
8574
|
+
}
|
|
8518
8575
|
case enums.publicKey.x448: {
|
|
8519
8576
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8520
8577
|
const ephemeralSecretKey = x448.utils.randomPrivateKey();
|
|
@@ -8530,11 +8587,27 @@ async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
|
8530
8587
|
|
|
8531
8588
|
async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
|
|
8532
8589
|
switch (algo) {
|
|
8533
|
-
case enums.publicKey.x25519:
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8590
|
+
case enums.publicKey.x25519:
|
|
8591
|
+
try {
|
|
8592
|
+
const webCrypto = util.getWebCrypto();
|
|
8593
|
+
const privateKeyJWK = privateKeyToJWK(algo, A, k);
|
|
8594
|
+
const ephemeralPublicKeyJWK = publicKeyToJWK(algo, ephemeralPublicKey);
|
|
8595
|
+
const privateKey = await webCrypto.importKey('jwk', privateKeyJWK, 'X25519', false, ['deriveKey', 'deriveBits']);
|
|
8596
|
+
const ephemeralPublicKeyReference = await webCrypto.importKey('jwk', ephemeralPublicKeyJWK, 'X25519', false, []);
|
|
8597
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8598
|
+
{ name: 'X25519', public: ephemeralPublicKeyReference },
|
|
8599
|
+
privateKey,
|
|
8600
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8601
|
+
);
|
|
8602
|
+
return new Uint8Array(sharedSecretBuffer);
|
|
8603
|
+
} catch (err) {
|
|
8604
|
+
if (err.name !== 'NotSupportedError') {
|
|
8605
|
+
throw err;
|
|
8606
|
+
}
|
|
8607
|
+
const sharedSecret = nacl.scalarMult(k, ephemeralPublicKey);
|
|
8608
|
+
assertNonZeroArray(sharedSecret);
|
|
8609
|
+
return sharedSecret;
|
|
8610
|
+
}
|
|
8538
8611
|
case enums.publicKey.x448: {
|
|
8539
8612
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8540
8613
|
const sharedSecret = x448.getSharedSecret(k, ephemeralPublicKey);
|
|
@@ -8562,6 +8635,35 @@ function assertNonZeroArray(sharedSecret) {
|
|
|
8562
8635
|
}
|
|
8563
8636
|
}
|
|
8564
8637
|
|
|
8638
|
+
|
|
8639
|
+
function publicKeyToJWK(algo, publicKey) {
|
|
8640
|
+
switch (algo) {
|
|
8641
|
+
case enums.publicKey.x25519: {
|
|
8642
|
+
const jwk = {
|
|
8643
|
+
kty: 'OKP',
|
|
8644
|
+
crv: 'X25519',
|
|
8645
|
+
x: uint8ArrayToB64(publicKey),
|
|
8646
|
+
ext: true
|
|
8647
|
+
};
|
|
8648
|
+
return jwk;
|
|
8649
|
+
}
|
|
8650
|
+
default:
|
|
8651
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8652
|
+
}
|
|
8653
|
+
}
|
|
8654
|
+
|
|
8655
|
+
function privateKeyToJWK(algo, publicKey, privateKey) {
|
|
8656
|
+
switch (algo) {
|
|
8657
|
+
case enums.publicKey.x25519: {
|
|
8658
|
+
const jwk = publicKeyToJWK(algo, publicKey);
|
|
8659
|
+
jwk.d = uint8ArrayToB64(privateKey);
|
|
8660
|
+
return jwk;
|
|
8661
|
+
}
|
|
8662
|
+
default:
|
|
8663
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8664
|
+
}
|
|
8665
|
+
}
|
|
8666
|
+
|
|
8565
8667
|
var ecdh_x = /*#__PURE__*/Object.freeze({
|
|
8566
8668
|
__proto__: null,
|
|
8567
8669
|
decrypt: decrypt$4,
|
|
@@ -9269,12 +9371,6 @@ var ecdsa = /*#__PURE__*/Object.freeze({
|
|
|
9269
9371
|
async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
9270
9372
|
const curve = new CurveWithOID(oid);
|
|
9271
9373
|
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
9374
|
const { RS: signature } = await sign$9(enums.publicKey.ed25519, hashAlgo, message, publicKey.subarray(1), privateKey, hashed);
|
|
9279
9375
|
// EdDSA signature params are returned in little-endian format
|
|
9280
9376
|
return {
|
|
@@ -9298,12 +9394,6 @@ async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9298
9394
|
async function verify$7(oid, hashAlgo, { r, s }, m, publicKey, hashed) {
|
|
9299
9395
|
const curve = new CurveWithOID(oid);
|
|
9300
9396
|
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
9397
|
const RS = util.concatUint8Array([r, s]);
|
|
9308
9398
|
return verify$9(enums.publicKey.ed25519, hashAlgo, { RS }, m, publicKey.subarray(1), hashed);
|
|
9309
9399
|
}
|
|
@@ -10161,7 +10251,7 @@ async function generate$4(algo) {
|
|
|
10161
10251
|
async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
10162
10252
|
const { eccKeyShare, eccCipherText } = await encaps$1(algo, eccPublicKey);
|
|
10163
10253
|
const { mlkemKeyShare, mlkemCipherText } = await encaps(algo, mlkemPublicKey);
|
|
10164
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10254
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10165
10255
|
const wrappedKey = await wrap(enums.symmetric.aes256, kek, sessioneKeyData); // C
|
|
10166
10256
|
return { eccCipherText, mlkemCipherText, wrappedKey };
|
|
10167
10257
|
}
|
|
@@ -10169,25 +10259,24 @@ async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
|
10169
10259
|
async function decrypt$2(algo, eccCipherText, mlkemCipherText, eccSecretKey, eccPublicKey, mlkemSecretKey, mlkemPublicKey, encryptedSessionKeyData) {
|
|
10170
10260
|
const eccKeyShare = await decaps$1(algo, eccCipherText, eccSecretKey, eccPublicKey);
|
|
10171
10261
|
const mlkemKeyShare = await decaps(algo, mlkemCipherText, mlkemSecretKey);
|
|
10172
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10262
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10173
10263
|
const sessionKey = await unwrap(enums.symmetric.aes256, kek, encryptedSessionKeyData);
|
|
10174
10264
|
return sessionKey;
|
|
10175
10265
|
}
|
|
10176
10266
|
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10267
|
+
/**
|
|
10268
|
+
* KEM key combiner
|
|
10269
|
+
*/
|
|
10270
|
+
async function multiKeyCombine(algo, mlkemKeyShare, ecdhKeyShare, ecdhCipherText, ecdhPublicKey) {
|
|
10271
|
+
const domSep = util.encodeUTF8('OpenPGPCompositeKDFv1');
|
|
10181
10272
|
const encData = util.concatUint8Array([
|
|
10182
10273
|
mlkemKeyShare,
|
|
10183
10274
|
ecdhKeyShare,
|
|
10184
10275
|
ecdhCipherText,
|
|
10185
10276
|
ecdhPublicKey,
|
|
10186
|
-
// domSep
|
|
10187
|
-
mlkemCipherText,
|
|
10188
|
-
mlkemPublicKey,
|
|
10189
10277
|
new Uint8Array([algo]),
|
|
10190
|
-
|
|
10278
|
+
domSep,
|
|
10279
|
+
new Uint8Array([domSep.length])
|
|
10191
10280
|
]);
|
|
10192
10281
|
|
|
10193
10282
|
const kek = await computeDigest(enums.hash.sha3_256, encData);
|
|
@@ -10324,12 +10413,6 @@ async function generate$1(algo) {
|
|
|
10324
10413
|
}
|
|
10325
10414
|
|
|
10326
10415
|
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
10416
|
switch (signatureAlgo) {
|
|
10334
10417
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10335
10418
|
const { eccSignature } = await sign$3(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, dataDigest);
|
|
@@ -10343,12 +10426,6 @@ async function sign$2(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, mldsa
|
|
|
10343
10426
|
}
|
|
10344
10427
|
|
|
10345
10428
|
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
10429
|
switch (signatureAlgo) {
|
|
10353
10430
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10354
10431
|
const eccVerifiedPromise = verify$3(signatureAlgo, hashAlgo, eccPublicKey, dataDigest, eccSignature);
|
|
@@ -10361,11 +10438,12 @@ async function verify$2(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicKey, d
|
|
|
10361
10438
|
}
|
|
10362
10439
|
}
|
|
10363
10440
|
|
|
10364
|
-
function
|
|
10365
|
-
//
|
|
10441
|
+
function isCompatibleHashAlgo(signatureAlgo, hashAlgo) {
|
|
10442
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
10443
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
10366
10444
|
switch (signatureAlgo) {
|
|
10367
10445
|
case enums.publicKey.pqc_mldsa_ed25519:
|
|
10368
|
-
return
|
|
10446
|
+
return getHashByteLength(hashAlgo) >= 32;
|
|
10369
10447
|
default:
|
|
10370
10448
|
throw new Error('Unsupported signature algorithm');
|
|
10371
10449
|
}
|
|
@@ -12488,6 +12566,12 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12488
12566
|
return verify$8(oid, hashAlgo, { r, s }, data, Q, hashed);
|
|
12489
12567
|
}
|
|
12490
12568
|
case enums.publicKey.eddsaLegacy: {
|
|
12569
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12570
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12571
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12572
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12573
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12574
|
+
}
|
|
12491
12575
|
const { oid, Q } = publicParams;
|
|
12492
12576
|
const curveSize = new CurveWithOID(oid).payloadSize;
|
|
12493
12577
|
// When dealing little-endian MPI data, we always need to left-pad it, as done with big-endian values:
|
|
@@ -12498,6 +12582,13 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12498
12582
|
}
|
|
12499
12583
|
case enums.publicKey.ed25519:
|
|
12500
12584
|
case enums.publicKey.ed448: {
|
|
12585
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12586
|
+
// Enforce digest sizes:
|
|
12587
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12588
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12589
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12590
|
+
}
|
|
12591
|
+
|
|
12501
12592
|
const { A } = publicParams;
|
|
12502
12593
|
return verify$9(algo, hashAlgo, signature, data, A, hashed);
|
|
12503
12594
|
}
|
|
@@ -12510,6 +12601,11 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12510
12601
|
return verify$5(algo.getValue(), keyMaterial, signature.mac.data, hashed);
|
|
12511
12602
|
}
|
|
12512
12603
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12604
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12605
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12606
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12607
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12608
|
+
}
|
|
12513
12609
|
const { eccPublicKey, mldsaPublicKey } = publicParams;
|
|
12514
12610
|
return verify$2(algo, hashAlgo, eccPublicKey, mldsaPublicKey, hashed, signature);
|
|
12515
12611
|
}
|
|
@@ -12558,12 +12654,24 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12558
12654
|
return sign$8(oid, hashAlgo, data, Q, d, hashed);
|
|
12559
12655
|
}
|
|
12560
12656
|
case enums.publicKey.eddsaLegacy: {
|
|
12657
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12658
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12659
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12660
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12661
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12662
|
+
}
|
|
12561
12663
|
const { oid, Q } = publicKeyParams;
|
|
12562
12664
|
const { seed } = privateKeyParams;
|
|
12563
12665
|
return sign$7(oid, hashAlgo, data, Q, seed, hashed);
|
|
12564
12666
|
}
|
|
12565
12667
|
case enums.publicKey.ed25519:
|
|
12566
12668
|
case enums.publicKey.ed448: {
|
|
12669
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12670
|
+
// Enforce digest sizes:
|
|
12671
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12672
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12673
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12674
|
+
}
|
|
12567
12675
|
const { A } = publicKeyParams;
|
|
12568
12676
|
const { seed } = privateKeyParams;
|
|
12569
12677
|
return sign$9(algo, hashAlgo, data, A, seed, hashed);
|
|
@@ -12575,6 +12683,11 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12575
12683
|
return { mac: new ShortByteString(mac) };
|
|
12576
12684
|
}
|
|
12577
12685
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12686
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12687
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12688
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12689
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12690
|
+
}
|
|
12578
12691
|
const { eccPublicKey } = publicKeyParams;
|
|
12579
12692
|
const { eccSecretKey, mldsaSecretKey } = privateKeyParams;
|
|
12580
12693
|
return sign$2(algo, hashAlgo, eccSecretKey, eccPublicKey, mldsaSecretKey, hashed);
|
|
@@ -16851,12 +16964,8 @@ class PublicKeyPacket {
|
|
|
16851
16964
|
throw new Error('Legacy curve25519 cannot be used with v6 keys');
|
|
16852
16965
|
}
|
|
16853
16966
|
// 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');
|
|
16967
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
16968
|
+
throw new Error('Unexpected key version: ML-DSA algorithms can only be used with v6 keys');
|
|
16860
16969
|
}
|
|
16861
16970
|
this.publicParams = publicParams;
|
|
16862
16971
|
pos += read;
|
|
@@ -17856,11 +17965,8 @@ class SecretKeyPacket extends PublicKeyPacket {
|
|
|
17856
17965
|
)) {
|
|
17857
17966
|
throw new Error(`Cannot generate v6 keys of type 'ecc' with curve ${curve}. Generate a key of type 'curve25519' instead`);
|
|
17858
17967
|
}
|
|
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`);
|
|
17968
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
17969
|
+
throw new Error(`Cannot generate v${this.version} signing keys of type 'pqc'. Generate a v6 key instead`);
|
|
17864
17970
|
}
|
|
17865
17971
|
const { privateParams, publicParams } = await generateParams(this.algorithm, bits, curve, symmetric);
|
|
17866
17972
|
this.privateParams = privateParams;
|
|
@@ -18364,12 +18470,6 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
|
|
|
18364
18470
|
* @async
|
|
18365
18471
|
*/
|
|
18366
18472
|
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
18473
|
/**
|
|
18374
18474
|
* If `preferredSenderAlgo` appears in the prefs of all recipients, we pick it; otherwise, we use the
|
|
18375
18475
|
* strongest supported algo (`defaultAlgo` is always implicitly supported by all keys).
|
|
@@ -18417,6 +18517,10 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18417
18517
|
enums.publicKey.ed448
|
|
18418
18518
|
]);
|
|
18419
18519
|
|
|
18520
|
+
const pqcAlgos = new Set([
|
|
18521
|
+
enums.publicKey.pqc_mldsa_ed25519
|
|
18522
|
+
]);
|
|
18523
|
+
|
|
18420
18524
|
if (eccAlgos.has(signingKeyPacket.algorithm)) {
|
|
18421
18525
|
// For ECC, the returned hash algo MUST be at least as strong as `preferredCurveHashAlgo`, see:
|
|
18422
18526
|
// - ECDSA: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.2-5
|
|
@@ -18439,6 +18543,21 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18439
18543
|
strongestSupportedAlgo :
|
|
18440
18544
|
preferredCurveAlgo;
|
|
18441
18545
|
}
|
|
18546
|
+
} else if (pqcAlgos.has(signingKeyPacket.algorithm)) {
|
|
18547
|
+
// For PQC, the returned hash algo MUST be at least 256 bit long, see:
|
|
18548
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4 .
|
|
18549
|
+
// Hence, we return the `preferredHashAlgo` as long as it's supported and long enough;
|
|
18550
|
+
// Otherwise, we look at the strongest supported algo, and ultimately fallback the default algo (SHA-256).
|
|
18551
|
+
const preferredSenderAlgoIsSupported = isSupportedHashAlgo(preferredSenderAlgo) && isCompatibleHashAlgo(signingKeyPacket.algorithm, preferredSenderAlgo);
|
|
18552
|
+
|
|
18553
|
+
if (preferredSenderAlgoIsSupported) {
|
|
18554
|
+
return preferredSenderAlgo;
|
|
18555
|
+
} else {
|
|
18556
|
+
const strongestSupportedAlgo = getStrongestSupportedHashAlgo();
|
|
18557
|
+
return isCompatibleHashAlgo(signingKeyPacket.algorithm, strongestSupportedAlgo) ?
|
|
18558
|
+
strongestSupportedAlgo :
|
|
18559
|
+
defaultAlgo;
|
|
18560
|
+
}
|
|
18442
18561
|
}
|
|
18443
18562
|
|
|
18444
18563
|
// `preferredSenderAlgo` may be weaker than the default, but we do not guard against this,
|