@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.cjs
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
|
'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.4',
|
|
1748
1747
|
/**
|
|
1749
1748
|
* @memberof module:config
|
|
1750
1749
|
* @property {String} commentString A comment string to be included in armored messages
|
|
@@ -6947,7 +6946,15 @@ async function generate$a(algo) {
|
|
|
6947
6946
|
case enums.publicKey.ed25519:
|
|
6948
6947
|
try {
|
|
6949
6948
|
const webCrypto = util.getWebCrypto();
|
|
6950
|
-
const webCryptoKey = await webCrypto.generateKey('Ed25519', true, ['sign', 'verify'])
|
|
6949
|
+
const webCryptoKey = await webCrypto.generateKey('Ed25519', true, ['sign', 'verify'])
|
|
6950
|
+
.catch(err => {
|
|
6951
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
6952
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
6953
|
+
newErr.name = 'NotSupportedError';
|
|
6954
|
+
throw newErr;
|
|
6955
|
+
}
|
|
6956
|
+
throw err;
|
|
6957
|
+
});
|
|
6951
6958
|
|
|
6952
6959
|
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
|
|
6953
6960
|
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
@@ -6957,7 +6964,7 @@ async function generate$a(algo) {
|
|
|
6957
6964
|
seed: b64ToUint8Array(privateKey.d, true)
|
|
6958
6965
|
};
|
|
6959
6966
|
} catch (err) {
|
|
6960
|
-
if (err.name !== 'NotSupportedError'
|
|
6967
|
+
if (err.name !== 'NotSupportedError') {
|
|
6961
6968
|
throw err;
|
|
6962
6969
|
}
|
|
6963
6970
|
const seed = getRandomBytes(getPayloadSize$1(algo));
|
|
@@ -6990,17 +6997,11 @@ async function generate$a(algo) {
|
|
|
6990
6997
|
* @async
|
|
6991
6998
|
*/
|
|
6992
6999
|
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
7000
|
switch (algo) {
|
|
7000
7001
|
case enums.publicKey.ed25519:
|
|
7001
7002
|
try {
|
|
7002
7003
|
const webCrypto = util.getWebCrypto();
|
|
7003
|
-
const jwk = privateKeyToJWK(algo, publicKey, privateKey);
|
|
7004
|
+
const jwk = privateKeyToJWK$1(algo, publicKey, privateKey);
|
|
7004
7005
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['sign']);
|
|
7005
7006
|
|
|
7006
7007
|
const signature = new Uint8Array(
|
|
@@ -7040,17 +7041,11 @@ async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
7040
7041
|
* @async
|
|
7041
7042
|
*/
|
|
7042
7043
|
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
7044
|
switch (algo) {
|
|
7050
7045
|
case enums.publicKey.ed25519:
|
|
7051
7046
|
try {
|
|
7052
7047
|
const webCrypto = util.getWebCrypto();
|
|
7053
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7048
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7054
7049
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['verify']);
|
|
7055
7050
|
const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
|
|
7056
7051
|
return verified;
|
|
@@ -7125,7 +7120,7 @@ function getPreferredHashAlgo$2(algo) {
|
|
|
7125
7120
|
}
|
|
7126
7121
|
}
|
|
7127
7122
|
|
|
7128
|
-
const publicKeyToJWK = (algo, publicKey) => {
|
|
7123
|
+
const publicKeyToJWK$1 = (algo, publicKey) => {
|
|
7129
7124
|
switch (algo) {
|
|
7130
7125
|
case enums.publicKey.ed25519: {
|
|
7131
7126
|
const jwk = {
|
|
@@ -7141,10 +7136,10 @@ const publicKeyToJWK = (algo, publicKey) => {
|
|
|
7141
7136
|
}
|
|
7142
7137
|
};
|
|
7143
7138
|
|
|
7144
|
-
const privateKeyToJWK = (algo, publicKey, privateKey) => {
|
|
7139
|
+
const privateKeyToJWK$1 = (algo, publicKey, privateKey) => {
|
|
7145
7140
|
switch (algo) {
|
|
7146
7141
|
case enums.publicKey.ed25519: {
|
|
7147
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7142
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7148
7143
|
jwk.d = uint8ArrayToB64(privateKey);
|
|
7149
7144
|
return jwk;
|
|
7150
7145
|
}
|
|
@@ -8384,12 +8379,41 @@ const HKDF_INFO = {
|
|
|
8384
8379
|
*/
|
|
8385
8380
|
async function generate$9(algo) {
|
|
8386
8381
|
switch (algo) {
|
|
8387
|
-
case enums.publicKey.x25519:
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8382
|
+
case enums.publicKey.x25519:
|
|
8383
|
+
try {
|
|
8384
|
+
const webCrypto = util.getWebCrypto();
|
|
8385
|
+
const webCryptoKey = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits'])
|
|
8386
|
+
.catch(err => {
|
|
8387
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
8388
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
8389
|
+
newErr.name = 'NotSupportedError';
|
|
8390
|
+
throw newErr;
|
|
8391
|
+
}
|
|
8392
|
+
throw err;
|
|
8393
|
+
});
|
|
8394
|
+
|
|
8395
|
+
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
|
|
8396
|
+
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
8397
|
+
|
|
8398
|
+
if (privateKey.x !== publicKey.x) { // Weird issue with Webkit on Linux: https://bugs.webkit.org/show_bug.cgi?id=289693
|
|
8399
|
+
const err = new Error('Unexpected mismatching public point');
|
|
8400
|
+
err.name = 'NotSupportedError';
|
|
8401
|
+
throw err;
|
|
8402
|
+
}
|
|
8403
|
+
|
|
8404
|
+
return {
|
|
8405
|
+
A: new Uint8Array(b64ToUint8Array(publicKey.x)),
|
|
8406
|
+
k: b64ToUint8Array(privateKey.d)
|
|
8407
|
+
};
|
|
8408
|
+
} catch (err) {
|
|
8409
|
+
if (err.name !== 'NotSupportedError') {
|
|
8410
|
+
throw err;
|
|
8411
|
+
}
|
|
8412
|
+
// k stays in little-endian, unlike legacy ECDH over curve25519
|
|
8413
|
+
const k = getRandomBytes(32);
|
|
8414
|
+
const { publicKey: A } = nacl.box.keyPair.fromSecretKey(k);
|
|
8415
|
+
return { A, k };
|
|
8416
|
+
}
|
|
8393
8417
|
|
|
8394
8418
|
case enums.publicKey.x448: {
|
|
8395
8419
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
@@ -8531,13 +8555,46 @@ function getPayloadSize(algo) {
|
|
|
8531
8555
|
*/
|
|
8532
8556
|
async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
8533
8557
|
switch (algo) {
|
|
8534
|
-
case enums.publicKey.x25519:
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8558
|
+
case enums.publicKey.x25519:
|
|
8559
|
+
try {
|
|
8560
|
+
const webCrypto = util.getWebCrypto();
|
|
8561
|
+
const ephemeralKeyPair = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits'])
|
|
8562
|
+
.catch(err => {
|
|
8563
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
8564
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
8565
|
+
newErr.name = 'NotSupportedError';
|
|
8566
|
+
throw newErr;
|
|
8567
|
+
}
|
|
8568
|
+
throw err;
|
|
8569
|
+
});
|
|
8570
|
+
const ephemeralPublicKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.publicKey);
|
|
8571
|
+
const ephemeralPrivateKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.privateKey);
|
|
8572
|
+
if (ephemeralPrivateKeyJwt.x !== ephemeralPublicKeyJwt.x) { // Weird issue with Webkit on Linux: https://bugs.webkit.org/show_bug.cgi?id=289693
|
|
8573
|
+
const err = new Error('Unexpected mismatching public point');
|
|
8574
|
+
err.name = 'NotSupportedError';
|
|
8575
|
+
throw err;
|
|
8576
|
+
}
|
|
8577
|
+
const jwk = publicKeyToJWK(algo, recipientA);
|
|
8578
|
+
const recipientPublicKey = await webCrypto.importKey('jwk', jwk, 'X25519', false, []);
|
|
8579
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8580
|
+
{ name: 'X25519', public: recipientPublicKey },
|
|
8581
|
+
ephemeralKeyPair.privateKey,
|
|
8582
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8583
|
+
);
|
|
8584
|
+
return {
|
|
8585
|
+
sharedSecret: new Uint8Array(sharedSecretBuffer),
|
|
8586
|
+
ephemeralPublicKey: new Uint8Array(b64ToUint8Array(ephemeralPublicKeyJwt.x))
|
|
8587
|
+
};
|
|
8588
|
+
} catch (err) {
|
|
8589
|
+
if (err.name !== 'NotSupportedError') {
|
|
8590
|
+
throw err;
|
|
8591
|
+
}
|
|
8592
|
+
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
|
|
8593
|
+
const sharedSecret = nacl.scalarMult(ephemeralSecretKey, recipientA);
|
|
8594
|
+
assertNonZeroArray(sharedSecret);
|
|
8595
|
+
const { publicKey: ephemeralPublicKey } = nacl.box.keyPair.fromSecretKey(ephemeralSecretKey);
|
|
8596
|
+
return { ephemeralPublicKey, sharedSecret };
|
|
8597
|
+
}
|
|
8541
8598
|
case enums.publicKey.x448: {
|
|
8542
8599
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8543
8600
|
const ephemeralSecretKey = x448.utils.randomPrivateKey();
|
|
@@ -8553,11 +8610,27 @@ async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
|
8553
8610
|
|
|
8554
8611
|
async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
|
|
8555
8612
|
switch (algo) {
|
|
8556
|
-
case enums.publicKey.x25519:
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8613
|
+
case enums.publicKey.x25519:
|
|
8614
|
+
try {
|
|
8615
|
+
const webCrypto = util.getWebCrypto();
|
|
8616
|
+
const privateKeyJWK = privateKeyToJWK(algo, A, k);
|
|
8617
|
+
const ephemeralPublicKeyJWK = publicKeyToJWK(algo, ephemeralPublicKey);
|
|
8618
|
+
const privateKey = await webCrypto.importKey('jwk', privateKeyJWK, 'X25519', false, ['deriveKey', 'deriveBits']);
|
|
8619
|
+
const ephemeralPublicKeyReference = await webCrypto.importKey('jwk', ephemeralPublicKeyJWK, 'X25519', false, []);
|
|
8620
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8621
|
+
{ name: 'X25519', public: ephemeralPublicKeyReference },
|
|
8622
|
+
privateKey,
|
|
8623
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8624
|
+
);
|
|
8625
|
+
return new Uint8Array(sharedSecretBuffer);
|
|
8626
|
+
} catch (err) {
|
|
8627
|
+
if (err.name !== 'NotSupportedError') {
|
|
8628
|
+
throw err;
|
|
8629
|
+
}
|
|
8630
|
+
const sharedSecret = nacl.scalarMult(k, ephemeralPublicKey);
|
|
8631
|
+
assertNonZeroArray(sharedSecret);
|
|
8632
|
+
return sharedSecret;
|
|
8633
|
+
}
|
|
8561
8634
|
case enums.publicKey.x448: {
|
|
8562
8635
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8563
8636
|
const sharedSecret = x448.getSharedSecret(k, ephemeralPublicKey);
|
|
@@ -8585,6 +8658,35 @@ function assertNonZeroArray(sharedSecret) {
|
|
|
8585
8658
|
}
|
|
8586
8659
|
}
|
|
8587
8660
|
|
|
8661
|
+
|
|
8662
|
+
function publicKeyToJWK(algo, publicKey) {
|
|
8663
|
+
switch (algo) {
|
|
8664
|
+
case enums.publicKey.x25519: {
|
|
8665
|
+
const jwk = {
|
|
8666
|
+
kty: 'OKP',
|
|
8667
|
+
crv: 'X25519',
|
|
8668
|
+
x: uint8ArrayToB64(publicKey),
|
|
8669
|
+
ext: true
|
|
8670
|
+
};
|
|
8671
|
+
return jwk;
|
|
8672
|
+
}
|
|
8673
|
+
default:
|
|
8674
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8675
|
+
}
|
|
8676
|
+
}
|
|
8677
|
+
|
|
8678
|
+
function privateKeyToJWK(algo, publicKey, privateKey) {
|
|
8679
|
+
switch (algo) {
|
|
8680
|
+
case enums.publicKey.x25519: {
|
|
8681
|
+
const jwk = publicKeyToJWK(algo, publicKey);
|
|
8682
|
+
jwk.d = uint8ArrayToB64(privateKey);
|
|
8683
|
+
return jwk;
|
|
8684
|
+
}
|
|
8685
|
+
default:
|
|
8686
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8687
|
+
}
|
|
8688
|
+
}
|
|
8689
|
+
|
|
8588
8690
|
var ecdh_x = /*#__PURE__*/Object.freeze({
|
|
8589
8691
|
__proto__: null,
|
|
8590
8692
|
decrypt: decrypt$4,
|
|
@@ -9292,12 +9394,6 @@ var ecdsa = /*#__PURE__*/Object.freeze({
|
|
|
9292
9394
|
async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
9293
9395
|
const curve = new CurveWithOID(oid);
|
|
9294
9396
|
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
9397
|
const { RS: signature } = await sign$9(enums.publicKey.ed25519, hashAlgo, message, publicKey.subarray(1), privateKey, hashed);
|
|
9302
9398
|
// EdDSA signature params are returned in little-endian format
|
|
9303
9399
|
return {
|
|
@@ -9321,12 +9417,6 @@ async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9321
9417
|
async function verify$7(oid, hashAlgo, { r, s }, m, publicKey, hashed) {
|
|
9322
9418
|
const curve = new CurveWithOID(oid);
|
|
9323
9419
|
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
9420
|
const RS = util.concatUint8Array([r, s]);
|
|
9331
9421
|
return verify$9(enums.publicKey.ed25519, hashAlgo, { RS }, m, publicKey.subarray(1), hashed);
|
|
9332
9422
|
}
|
|
@@ -10184,7 +10274,7 @@ async function generate$4(algo) {
|
|
|
10184
10274
|
async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
10185
10275
|
const { eccKeyShare, eccCipherText } = await encaps$1(algo, eccPublicKey);
|
|
10186
10276
|
const { mlkemKeyShare, mlkemCipherText } = await encaps(algo, mlkemPublicKey);
|
|
10187
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10277
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10188
10278
|
const wrappedKey = await wrap(enums.symmetric.aes256, kek, sessioneKeyData); // C
|
|
10189
10279
|
return { eccCipherText, mlkemCipherText, wrappedKey };
|
|
10190
10280
|
}
|
|
@@ -10192,25 +10282,24 @@ async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
|
10192
10282
|
async function decrypt$2(algo, eccCipherText, mlkemCipherText, eccSecretKey, eccPublicKey, mlkemSecretKey, mlkemPublicKey, encryptedSessionKeyData) {
|
|
10193
10283
|
const eccKeyShare = await decaps$1(algo, eccCipherText, eccSecretKey, eccPublicKey);
|
|
10194
10284
|
const mlkemKeyShare = await decaps(algo, mlkemCipherText, mlkemSecretKey);
|
|
10195
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10285
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10196
10286
|
const sessionKey = await unwrap(enums.symmetric.aes256, kek, encryptedSessionKeyData);
|
|
10197
10287
|
return sessionKey;
|
|
10198
10288
|
}
|
|
10199
10289
|
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10290
|
+
/**
|
|
10291
|
+
* KEM key combiner
|
|
10292
|
+
*/
|
|
10293
|
+
async function multiKeyCombine(algo, mlkemKeyShare, ecdhKeyShare, ecdhCipherText, ecdhPublicKey) {
|
|
10294
|
+
const domSep = util.encodeUTF8('OpenPGPCompositeKDFv1');
|
|
10204
10295
|
const encData = util.concatUint8Array([
|
|
10205
10296
|
mlkemKeyShare,
|
|
10206
10297
|
ecdhKeyShare,
|
|
10207
10298
|
ecdhCipherText,
|
|
10208
10299
|
ecdhPublicKey,
|
|
10209
|
-
// domSep
|
|
10210
|
-
mlkemCipherText,
|
|
10211
|
-
mlkemPublicKey,
|
|
10212
10300
|
new Uint8Array([algo]),
|
|
10213
|
-
|
|
10301
|
+
domSep,
|
|
10302
|
+
new Uint8Array([domSep.length])
|
|
10214
10303
|
]);
|
|
10215
10304
|
|
|
10216
10305
|
const kek = await computeDigest(enums.hash.sha3_256, encData);
|
|
@@ -10347,12 +10436,6 @@ async function generate$1(algo) {
|
|
|
10347
10436
|
}
|
|
10348
10437
|
|
|
10349
10438
|
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
10439
|
switch (signatureAlgo) {
|
|
10357
10440
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10358
10441
|
const { eccSignature } = await sign$3(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, dataDigest);
|
|
@@ -10366,12 +10449,6 @@ async function sign$2(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, mldsa
|
|
|
10366
10449
|
}
|
|
10367
10450
|
|
|
10368
10451
|
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
10452
|
switch (signatureAlgo) {
|
|
10376
10453
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10377
10454
|
const eccVerifiedPromise = verify$3(signatureAlgo, hashAlgo, eccPublicKey, dataDigest, eccSignature);
|
|
@@ -10384,11 +10461,12 @@ async function verify$2(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicKey, d
|
|
|
10384
10461
|
}
|
|
10385
10462
|
}
|
|
10386
10463
|
|
|
10387
|
-
function
|
|
10388
|
-
//
|
|
10464
|
+
function isCompatibleHashAlgo(signatureAlgo, hashAlgo) {
|
|
10465
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
10466
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
10389
10467
|
switch (signatureAlgo) {
|
|
10390
10468
|
case enums.publicKey.pqc_mldsa_ed25519:
|
|
10391
|
-
return
|
|
10469
|
+
return getHashByteLength(hashAlgo) >= 32;
|
|
10392
10470
|
default:
|
|
10393
10471
|
throw new Error('Unsupported signature algorithm');
|
|
10394
10472
|
}
|
|
@@ -12511,6 +12589,12 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12511
12589
|
return verify$8(oid, hashAlgo, { r, s }, data, Q, hashed);
|
|
12512
12590
|
}
|
|
12513
12591
|
case enums.publicKey.eddsaLegacy: {
|
|
12592
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12593
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12594
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12595
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12596
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12597
|
+
}
|
|
12514
12598
|
const { oid, Q } = publicParams;
|
|
12515
12599
|
const curveSize = new CurveWithOID(oid).payloadSize;
|
|
12516
12600
|
// When dealing little-endian MPI data, we always need to left-pad it, as done with big-endian values:
|
|
@@ -12521,6 +12605,13 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12521
12605
|
}
|
|
12522
12606
|
case enums.publicKey.ed25519:
|
|
12523
12607
|
case enums.publicKey.ed448: {
|
|
12608
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12609
|
+
// Enforce digest sizes:
|
|
12610
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12611
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12612
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12613
|
+
}
|
|
12614
|
+
|
|
12524
12615
|
const { A } = publicParams;
|
|
12525
12616
|
return verify$9(algo, hashAlgo, signature, data, A, hashed);
|
|
12526
12617
|
}
|
|
@@ -12533,6 +12624,11 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12533
12624
|
return verify$5(algo.getValue(), keyMaterial, signature.mac.data, hashed);
|
|
12534
12625
|
}
|
|
12535
12626
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12627
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12628
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12629
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12630
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12631
|
+
}
|
|
12536
12632
|
const { eccPublicKey, mldsaPublicKey } = publicParams;
|
|
12537
12633
|
return verify$2(algo, hashAlgo, eccPublicKey, mldsaPublicKey, hashed, signature);
|
|
12538
12634
|
}
|
|
@@ -12581,12 +12677,24 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12581
12677
|
return sign$8(oid, hashAlgo, data, Q, d, hashed);
|
|
12582
12678
|
}
|
|
12583
12679
|
case enums.publicKey.eddsaLegacy: {
|
|
12680
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12681
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12682
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12683
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12684
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12685
|
+
}
|
|
12584
12686
|
const { oid, Q } = publicKeyParams;
|
|
12585
12687
|
const { seed } = privateKeyParams;
|
|
12586
12688
|
return sign$7(oid, hashAlgo, data, Q, seed, hashed);
|
|
12587
12689
|
}
|
|
12588
12690
|
case enums.publicKey.ed25519:
|
|
12589
12691
|
case enums.publicKey.ed448: {
|
|
12692
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12693
|
+
// Enforce digest sizes:
|
|
12694
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12695
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12696
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12697
|
+
}
|
|
12590
12698
|
const { A } = publicKeyParams;
|
|
12591
12699
|
const { seed } = privateKeyParams;
|
|
12592
12700
|
return sign$9(algo, hashAlgo, data, A, seed, hashed);
|
|
@@ -12598,6 +12706,11 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12598
12706
|
return { mac: new ShortByteString(mac) };
|
|
12599
12707
|
}
|
|
12600
12708
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12709
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12710
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12711
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12712
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12713
|
+
}
|
|
12601
12714
|
const { eccPublicKey } = publicKeyParams;
|
|
12602
12715
|
const { eccSecretKey, mldsaSecretKey } = privateKeyParams;
|
|
12603
12716
|
return sign$2(algo, hashAlgo, eccSecretKey, eccPublicKey, mldsaSecretKey, hashed);
|
|
@@ -16874,12 +16987,8 @@ class PublicKeyPacket {
|
|
|
16874
16987
|
throw new Error('Legacy curve25519 cannot be used with v6 keys');
|
|
16875
16988
|
}
|
|
16876
16989
|
// 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');
|
|
16990
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
16991
|
+
throw new Error('Unexpected key version: ML-DSA algorithms can only be used with v6 keys');
|
|
16883
16992
|
}
|
|
16884
16993
|
this.publicParams = publicParams;
|
|
16885
16994
|
pos += read;
|
|
@@ -17879,11 +17988,8 @@ class SecretKeyPacket extends PublicKeyPacket {
|
|
|
17879
17988
|
)) {
|
|
17880
17989
|
throw new Error(`Cannot generate v6 keys of type 'ecc' with curve ${curve}. Generate a key of type 'curve25519' instead`);
|
|
17881
17990
|
}
|
|
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`);
|
|
17991
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
17992
|
+
throw new Error(`Cannot generate v${this.version} signing keys of type 'pqc'. Generate a v6 key instead`);
|
|
17887
17993
|
}
|
|
17888
17994
|
const { privateParams, publicParams } = await generateParams(this.algorithm, bits, curve, symmetric);
|
|
17889
17995
|
this.privateParams = privateParams;
|
|
@@ -18387,12 +18493,6 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
|
|
|
18387
18493
|
* @async
|
|
18388
18494
|
*/
|
|
18389
18495
|
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
18496
|
/**
|
|
18397
18497
|
* If `preferredSenderAlgo` appears in the prefs of all recipients, we pick it; otherwise, we use the
|
|
18398
18498
|
* strongest supported algo (`defaultAlgo` is always implicitly supported by all keys).
|
|
@@ -18440,6 +18540,10 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18440
18540
|
enums.publicKey.ed448
|
|
18441
18541
|
]);
|
|
18442
18542
|
|
|
18543
|
+
const pqcAlgos = new Set([
|
|
18544
|
+
enums.publicKey.pqc_mldsa_ed25519
|
|
18545
|
+
]);
|
|
18546
|
+
|
|
18443
18547
|
if (eccAlgos.has(signingKeyPacket.algorithm)) {
|
|
18444
18548
|
// For ECC, the returned hash algo MUST be at least as strong as `preferredCurveHashAlgo`, see:
|
|
18445
18549
|
// - ECDSA: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.2-5
|
|
@@ -18462,6 +18566,21 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18462
18566
|
strongestSupportedAlgo :
|
|
18463
18567
|
preferredCurveAlgo;
|
|
18464
18568
|
}
|
|
18569
|
+
} else if (pqcAlgos.has(signingKeyPacket.algorithm)) {
|
|
18570
|
+
// For PQC, the returned hash algo MUST be at least 256 bit long, see:
|
|
18571
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4 .
|
|
18572
|
+
// Hence, we return the `preferredHashAlgo` as long as it's supported and long enough;
|
|
18573
|
+
// Otherwise, we look at the strongest supported algo, and ultimately fallback the default algo (SHA-256).
|
|
18574
|
+
const preferredSenderAlgoIsSupported = isSupportedHashAlgo(preferredSenderAlgo) && isCompatibleHashAlgo(signingKeyPacket.algorithm, preferredSenderAlgo);
|
|
18575
|
+
|
|
18576
|
+
if (preferredSenderAlgoIsSupported) {
|
|
18577
|
+
return preferredSenderAlgo;
|
|
18578
|
+
} else {
|
|
18579
|
+
const strongestSupportedAlgo = getStrongestSupportedHashAlgo();
|
|
18580
|
+
return isCompatibleHashAlgo(signingKeyPacket.algorithm, strongestSupportedAlgo) ?
|
|
18581
|
+
strongestSupportedAlgo :
|
|
18582
|
+
defaultAlgo;
|
|
18583
|
+
}
|
|
18465
18584
|
}
|
|
18466
18585
|
|
|
18467
18586
|
// `preferredSenderAlgo` may be weaker than the default, but we do not guard against this,
|