@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/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
|
function _mergeNamespaces(n, m) {
|
|
@@ -1062,11 +1062,10 @@ var enums = {
|
|
|
1062
1062
|
ed25519: 27,
|
|
1063
1063
|
/** Ed448 (Sign only) */
|
|
1064
1064
|
ed448: 28,
|
|
1065
|
-
/** Post-quantum ML-KEM-768 + X25519 (Encrypt only) */
|
|
1066
|
-
pqc_mlkem_x25519: 105,
|
|
1067
1065
|
/** Post-quantum ML-DSA-64 + Ed25519 (Sign only) */
|
|
1068
|
-
pqc_mldsa_ed25519:
|
|
1069
|
-
|
|
1066
|
+
pqc_mldsa_ed25519: 30,
|
|
1067
|
+
/** Post-quantum ML-KEM-768 + X25519 (Encrypt only) */
|
|
1068
|
+
pqc_mlkem_x25519: 35,
|
|
1070
1069
|
/** Persistent symmetric keys: encryption algorithm */
|
|
1071
1070
|
aead: 100,
|
|
1072
1071
|
/** Persistent symmetric keys: authentication algorithm */
|
|
@@ -1717,7 +1716,7 @@ var config = {
|
|
|
1717
1716
|
* @memberof module:config
|
|
1718
1717
|
* @property {String} versionString A version string to be included in armored messages
|
|
1719
1718
|
*/
|
|
1720
|
-
versionString: 'OpenPGP.js 6.1.1-patch.
|
|
1719
|
+
versionString: 'OpenPGP.js 6.1.1-patch.4',
|
|
1721
1720
|
/**
|
|
1722
1721
|
* @memberof module:config
|
|
1723
1722
|
* @property {String} commentString A comment string to be included in armored messages
|
|
@@ -6914,7 +6913,15 @@ async function generate$a(algo) {
|
|
|
6914
6913
|
case enums.publicKey.ed25519:
|
|
6915
6914
|
try {
|
|
6916
6915
|
const webCrypto = util.getWebCrypto();
|
|
6917
|
-
const webCryptoKey = await webCrypto.generateKey('Ed25519', true, ['sign', 'verify'])
|
|
6916
|
+
const webCryptoKey = await webCrypto.generateKey('Ed25519', true, ['sign', 'verify'])
|
|
6917
|
+
.catch(err => {
|
|
6918
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
6919
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
6920
|
+
newErr.name = 'NotSupportedError';
|
|
6921
|
+
throw newErr;
|
|
6922
|
+
}
|
|
6923
|
+
throw err;
|
|
6924
|
+
});
|
|
6918
6925
|
|
|
6919
6926
|
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
|
|
6920
6927
|
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
@@ -6924,7 +6931,7 @@ async function generate$a(algo) {
|
|
|
6924
6931
|
seed: b64ToUint8Array(privateKey.d, true)
|
|
6925
6932
|
};
|
|
6926
6933
|
} catch (err) {
|
|
6927
|
-
if (err.name !== 'NotSupportedError'
|
|
6934
|
+
if (err.name !== 'NotSupportedError') {
|
|
6928
6935
|
throw err;
|
|
6929
6936
|
}
|
|
6930
6937
|
const seed = getRandomBytes(getPayloadSize$1(algo));
|
|
@@ -6957,17 +6964,11 @@ async function generate$a(algo) {
|
|
|
6957
6964
|
* @async
|
|
6958
6965
|
*/
|
|
6959
6966
|
async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
6960
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
6961
|
-
// Enforce digest sizes:
|
|
6962
|
-
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
6963
|
-
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
6964
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
6965
|
-
}
|
|
6966
6967
|
switch (algo) {
|
|
6967
6968
|
case enums.publicKey.ed25519:
|
|
6968
6969
|
try {
|
|
6969
6970
|
const webCrypto = util.getWebCrypto();
|
|
6970
|
-
const jwk = privateKeyToJWK(algo, publicKey, privateKey);
|
|
6971
|
+
const jwk = privateKeyToJWK$1(algo, publicKey, privateKey);
|
|
6971
6972
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['sign']);
|
|
6972
6973
|
|
|
6973
6974
|
const signature = new Uint8Array(
|
|
@@ -7007,17 +7008,11 @@ async function sign$9(algo, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
7007
7008
|
* @async
|
|
7008
7009
|
*/
|
|
7009
7010
|
async function verify$9(algo, hashAlgo, { RS }, m, publicKey, hashed) {
|
|
7010
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
7011
|
-
// Enforce digest sizes:
|
|
7012
|
-
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
7013
|
-
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
7014
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
7015
|
-
}
|
|
7016
7011
|
switch (algo) {
|
|
7017
7012
|
case enums.publicKey.ed25519:
|
|
7018
7013
|
try {
|
|
7019
7014
|
const webCrypto = util.getWebCrypto();
|
|
7020
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7015
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7021
7016
|
const key = await webCrypto.importKey('jwk', jwk, 'Ed25519', false, ['verify']);
|
|
7022
7017
|
const verified = await webCrypto.verify('Ed25519', key, RS, hashed);
|
|
7023
7018
|
return verified;
|
|
@@ -7092,7 +7087,7 @@ function getPreferredHashAlgo$2(algo) {
|
|
|
7092
7087
|
}
|
|
7093
7088
|
}
|
|
7094
7089
|
|
|
7095
|
-
const publicKeyToJWK = (algo, publicKey) => {
|
|
7090
|
+
const publicKeyToJWK$1 = (algo, publicKey) => {
|
|
7096
7091
|
switch (algo) {
|
|
7097
7092
|
case enums.publicKey.ed25519: {
|
|
7098
7093
|
const jwk = {
|
|
@@ -7108,10 +7103,10 @@ const publicKeyToJWK = (algo, publicKey) => {
|
|
|
7108
7103
|
}
|
|
7109
7104
|
};
|
|
7110
7105
|
|
|
7111
|
-
const privateKeyToJWK = (algo, publicKey, privateKey) => {
|
|
7106
|
+
const privateKeyToJWK$1 = (algo, publicKey, privateKey) => {
|
|
7112
7107
|
switch (algo) {
|
|
7113
7108
|
case enums.publicKey.ed25519: {
|
|
7114
|
-
const jwk = publicKeyToJWK(algo, publicKey);
|
|
7109
|
+
const jwk = publicKeyToJWK$1(algo, publicKey);
|
|
7115
7110
|
jwk.d = uint8ArrayToB64(privateKey);
|
|
7116
7111
|
return jwk;
|
|
7117
7112
|
}
|
|
@@ -8351,12 +8346,41 @@ const HKDF_INFO = {
|
|
|
8351
8346
|
*/
|
|
8352
8347
|
async function generate$9(algo) {
|
|
8353
8348
|
switch (algo) {
|
|
8354
|
-
case enums.publicKey.x25519:
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8349
|
+
case enums.publicKey.x25519:
|
|
8350
|
+
try {
|
|
8351
|
+
const webCrypto = util.getWebCrypto();
|
|
8352
|
+
const webCryptoKey = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits'])
|
|
8353
|
+
.catch(err => {
|
|
8354
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
8355
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
8356
|
+
newErr.name = 'NotSupportedError';
|
|
8357
|
+
throw newErr;
|
|
8358
|
+
}
|
|
8359
|
+
throw err;
|
|
8360
|
+
});
|
|
8361
|
+
|
|
8362
|
+
const privateKey = await webCrypto.exportKey('jwk', webCryptoKey.privateKey);
|
|
8363
|
+
const publicKey = await webCrypto.exportKey('jwk', webCryptoKey.publicKey);
|
|
8364
|
+
|
|
8365
|
+
if (privateKey.x !== publicKey.x) { // Weird issue with Webkit on Linux: https://bugs.webkit.org/show_bug.cgi?id=289693
|
|
8366
|
+
const err = new Error('Unexpected mismatching public point');
|
|
8367
|
+
err.name = 'NotSupportedError';
|
|
8368
|
+
throw err;
|
|
8369
|
+
}
|
|
8370
|
+
|
|
8371
|
+
return {
|
|
8372
|
+
A: new Uint8Array(b64ToUint8Array(publicKey.x)),
|
|
8373
|
+
k: b64ToUint8Array(privateKey.d)
|
|
8374
|
+
};
|
|
8375
|
+
} catch (err) {
|
|
8376
|
+
if (err.name !== 'NotSupportedError') {
|
|
8377
|
+
throw err;
|
|
8378
|
+
}
|
|
8379
|
+
// k stays in little-endian, unlike legacy ECDH over curve25519
|
|
8380
|
+
const k = getRandomBytes(32);
|
|
8381
|
+
const { publicKey: A } = nacl.box.keyPair.fromSecretKey(k);
|
|
8382
|
+
return { A, k };
|
|
8383
|
+
}
|
|
8360
8384
|
|
|
8361
8385
|
case enums.publicKey.x448: {
|
|
8362
8386
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
@@ -8498,13 +8522,46 @@ function getPayloadSize(algo) {
|
|
|
8498
8522
|
*/
|
|
8499
8523
|
async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
8500
8524
|
switch (algo) {
|
|
8501
|
-
case enums.publicKey.x25519:
|
|
8502
|
-
|
|
8503
|
-
|
|
8504
|
-
|
|
8505
|
-
|
|
8506
|
-
|
|
8507
|
-
|
|
8525
|
+
case enums.publicKey.x25519:
|
|
8526
|
+
try {
|
|
8527
|
+
const webCrypto = util.getWebCrypto();
|
|
8528
|
+
const ephemeralKeyPair = await webCrypto.generateKey('X25519', true, ['deriveKey', 'deriveBits'])
|
|
8529
|
+
.catch(err => {
|
|
8530
|
+
if (err.name === 'OperationError') { // Temporary (hopefully) fix for WebKit on Linux
|
|
8531
|
+
const newErr = new Error('Unexpected key generation issue');
|
|
8532
|
+
newErr.name = 'NotSupportedError';
|
|
8533
|
+
throw newErr;
|
|
8534
|
+
}
|
|
8535
|
+
throw err;
|
|
8536
|
+
});
|
|
8537
|
+
const ephemeralPublicKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.publicKey);
|
|
8538
|
+
const ephemeralPrivateKeyJwt = await webCrypto.exportKey('jwk', ephemeralKeyPair.privateKey);
|
|
8539
|
+
if (ephemeralPrivateKeyJwt.x !== ephemeralPublicKeyJwt.x) { // Weird issue with Webkit on Linux: https://bugs.webkit.org/show_bug.cgi?id=289693
|
|
8540
|
+
const err = new Error('Unexpected mismatching public point');
|
|
8541
|
+
err.name = 'NotSupportedError';
|
|
8542
|
+
throw err;
|
|
8543
|
+
}
|
|
8544
|
+
const jwk = publicKeyToJWK(algo, recipientA);
|
|
8545
|
+
const recipientPublicKey = await webCrypto.importKey('jwk', jwk, 'X25519', false, []);
|
|
8546
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8547
|
+
{ name: 'X25519', public: recipientPublicKey },
|
|
8548
|
+
ephemeralKeyPair.privateKey,
|
|
8549
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8550
|
+
);
|
|
8551
|
+
return {
|
|
8552
|
+
sharedSecret: new Uint8Array(sharedSecretBuffer),
|
|
8553
|
+
ephemeralPublicKey: new Uint8Array(b64ToUint8Array(ephemeralPublicKeyJwt.x))
|
|
8554
|
+
};
|
|
8555
|
+
} catch (err) {
|
|
8556
|
+
if (err.name !== 'NotSupportedError') {
|
|
8557
|
+
throw err;
|
|
8558
|
+
}
|
|
8559
|
+
const ephemeralSecretKey = getRandomBytes(getPayloadSize(algo));
|
|
8560
|
+
const sharedSecret = nacl.scalarMult(ephemeralSecretKey, recipientA);
|
|
8561
|
+
assertNonZeroArray(sharedSecret);
|
|
8562
|
+
const { publicKey: ephemeralPublicKey } = nacl.box.keyPair.fromSecretKey(ephemeralSecretKey);
|
|
8563
|
+
return { ephemeralPublicKey, sharedSecret };
|
|
8564
|
+
}
|
|
8508
8565
|
case enums.publicKey.x448: {
|
|
8509
8566
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8510
8567
|
const ephemeralSecretKey = x448.utils.randomPrivateKey();
|
|
@@ -8520,11 +8577,27 @@ async function generateEphemeralEncryptionMaterial(algo, recipientA) {
|
|
|
8520
8577
|
|
|
8521
8578
|
async function recomputeSharedSecret(algo, ephemeralPublicKey, A, k) {
|
|
8522
8579
|
switch (algo) {
|
|
8523
|
-
case enums.publicKey.x25519:
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8580
|
+
case enums.publicKey.x25519:
|
|
8581
|
+
try {
|
|
8582
|
+
const webCrypto = util.getWebCrypto();
|
|
8583
|
+
const privateKeyJWK = privateKeyToJWK(algo, A, k);
|
|
8584
|
+
const ephemeralPublicKeyJWK = publicKeyToJWK(algo, ephemeralPublicKey);
|
|
8585
|
+
const privateKey = await webCrypto.importKey('jwk', privateKeyJWK, 'X25519', false, ['deriveKey', 'deriveBits']);
|
|
8586
|
+
const ephemeralPublicKeyReference = await webCrypto.importKey('jwk', ephemeralPublicKeyJWK, 'X25519', false, []);
|
|
8587
|
+
const sharedSecretBuffer = await webCrypto.deriveBits(
|
|
8588
|
+
{ name: 'X25519', public: ephemeralPublicKeyReference },
|
|
8589
|
+
privateKey,
|
|
8590
|
+
getPayloadSize(algo) * 8 // in bits
|
|
8591
|
+
);
|
|
8592
|
+
return new Uint8Array(sharedSecretBuffer);
|
|
8593
|
+
} catch (err) {
|
|
8594
|
+
if (err.name !== 'NotSupportedError') {
|
|
8595
|
+
throw err;
|
|
8596
|
+
}
|
|
8597
|
+
const sharedSecret = nacl.scalarMult(k, ephemeralPublicKey);
|
|
8598
|
+
assertNonZeroArray(sharedSecret);
|
|
8599
|
+
return sharedSecret;
|
|
8600
|
+
}
|
|
8528
8601
|
case enums.publicKey.x448: {
|
|
8529
8602
|
const x448 = await util.getNobleCurve(enums.publicKey.x448);
|
|
8530
8603
|
const sharedSecret = x448.getSharedSecret(k, ephemeralPublicKey);
|
|
@@ -8552,6 +8625,35 @@ function assertNonZeroArray(sharedSecret) {
|
|
|
8552
8625
|
}
|
|
8553
8626
|
}
|
|
8554
8627
|
|
|
8628
|
+
|
|
8629
|
+
function publicKeyToJWK(algo, publicKey) {
|
|
8630
|
+
switch (algo) {
|
|
8631
|
+
case enums.publicKey.x25519: {
|
|
8632
|
+
const jwk = {
|
|
8633
|
+
kty: 'OKP',
|
|
8634
|
+
crv: 'X25519',
|
|
8635
|
+
x: uint8ArrayToB64(publicKey),
|
|
8636
|
+
ext: true
|
|
8637
|
+
};
|
|
8638
|
+
return jwk;
|
|
8639
|
+
}
|
|
8640
|
+
default:
|
|
8641
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8642
|
+
}
|
|
8643
|
+
}
|
|
8644
|
+
|
|
8645
|
+
function privateKeyToJWK(algo, publicKey, privateKey) {
|
|
8646
|
+
switch (algo) {
|
|
8647
|
+
case enums.publicKey.x25519: {
|
|
8648
|
+
const jwk = publicKeyToJWK(algo, publicKey);
|
|
8649
|
+
jwk.d = uint8ArrayToB64(privateKey);
|
|
8650
|
+
return jwk;
|
|
8651
|
+
}
|
|
8652
|
+
default:
|
|
8653
|
+
throw new Error('Unsupported ECDH algorithm');
|
|
8654
|
+
}
|
|
8655
|
+
}
|
|
8656
|
+
|
|
8555
8657
|
var ecdh_x = /*#__PURE__*/Object.freeze({
|
|
8556
8658
|
__proto__: null,
|
|
8557
8659
|
decrypt: decrypt$4,
|
|
@@ -9259,12 +9361,6 @@ var ecdsa = /*#__PURE__*/Object.freeze({
|
|
|
9259
9361
|
async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
9260
9362
|
const curve = new CurveWithOID(oid);
|
|
9261
9363
|
checkPublicPointEnconding(curve, publicKey);
|
|
9262
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
9263
|
-
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
9264
|
-
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
9265
|
-
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
9266
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
9267
|
-
}
|
|
9268
9364
|
const { RS: signature } = await sign$9(enums.publicKey.ed25519, hashAlgo, message, publicKey.subarray(1), privateKey, hashed);
|
|
9269
9365
|
// EdDSA signature params are returned in little-endian format
|
|
9270
9366
|
return {
|
|
@@ -9288,12 +9384,6 @@ async function sign$7(oid, hashAlgo, message, publicKey, privateKey, hashed) {
|
|
|
9288
9384
|
async function verify$7(oid, hashAlgo, { r, s }, m, publicKey, hashed) {
|
|
9289
9385
|
const curve = new CurveWithOID(oid);
|
|
9290
9386
|
checkPublicPointEnconding(curve, publicKey);
|
|
9291
|
-
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
9292
|
-
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
9293
|
-
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
9294
|
-
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
9295
|
-
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
9296
|
-
}
|
|
9297
9387
|
const RS = util.concatUint8Array([r, s]);
|
|
9298
9388
|
return verify$9(enums.publicKey.ed25519, hashAlgo, { RS }, m, publicKey.subarray(1), hashed);
|
|
9299
9389
|
}
|
|
@@ -10151,7 +10241,7 @@ async function generate$4(algo) {
|
|
|
10151
10241
|
async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
10152
10242
|
const { eccKeyShare, eccCipherText } = await encaps$1(algo, eccPublicKey);
|
|
10153
10243
|
const { mlkemKeyShare, mlkemCipherText } = await encaps(algo, mlkemPublicKey);
|
|
10154
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10244
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10155
10245
|
const wrappedKey = await wrap(enums.symmetric.aes256, kek, sessioneKeyData); // C
|
|
10156
10246
|
return { eccCipherText, mlkemCipherText, wrappedKey };
|
|
10157
10247
|
}
|
|
@@ -10159,25 +10249,24 @@ async function encrypt$2(algo, eccPublicKey, mlkemPublicKey, sessioneKeyData) {
|
|
|
10159
10249
|
async function decrypt$2(algo, eccCipherText, mlkemCipherText, eccSecretKey, eccPublicKey, mlkemSecretKey, mlkemPublicKey, encryptedSessionKeyData) {
|
|
10160
10250
|
const eccKeyShare = await decaps$1(algo, eccCipherText, eccSecretKey, eccPublicKey);
|
|
10161
10251
|
const mlkemKeyShare = await decaps(algo, mlkemCipherText, mlkemSecretKey);
|
|
10162
|
-
const kek = await multiKeyCombine(algo, eccKeyShare, eccCipherText, eccPublicKey
|
|
10252
|
+
const kek = await multiKeyCombine(algo, mlkemKeyShare, eccKeyShare, eccCipherText, eccPublicKey);
|
|
10163
10253
|
const sessionKey = await unwrap(enums.symmetric.aes256, kek, encryptedSessionKeyData);
|
|
10164
10254
|
return sessionKey;
|
|
10165
10255
|
}
|
|
10166
10256
|
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10257
|
+
/**
|
|
10258
|
+
* KEM key combiner
|
|
10259
|
+
*/
|
|
10260
|
+
async function multiKeyCombine(algo, mlkemKeyShare, ecdhKeyShare, ecdhCipherText, ecdhPublicKey) {
|
|
10261
|
+
const domSep = util.encodeUTF8('OpenPGPCompositeKDFv1');
|
|
10171
10262
|
const encData = util.concatUint8Array([
|
|
10172
10263
|
mlkemKeyShare,
|
|
10173
10264
|
ecdhKeyShare,
|
|
10174
10265
|
ecdhCipherText,
|
|
10175
10266
|
ecdhPublicKey,
|
|
10176
|
-
// domSep
|
|
10177
|
-
mlkemCipherText,
|
|
10178
|
-
mlkemPublicKey,
|
|
10179
10267
|
new Uint8Array([algo]),
|
|
10180
|
-
|
|
10268
|
+
domSep,
|
|
10269
|
+
new Uint8Array([domSep.length])
|
|
10181
10270
|
]);
|
|
10182
10271
|
|
|
10183
10272
|
const kek = await computeDigest(enums.hash.sha3_256, encData);
|
|
@@ -10314,12 +10403,6 @@ async function generate$1(algo) {
|
|
|
10314
10403
|
}
|
|
10315
10404
|
|
|
10316
10405
|
async function sign$2(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, mldsaSecretKey, dataDigest) {
|
|
10317
|
-
if (hashAlgo !== getRequiredHashAlgo(signatureAlgo)) {
|
|
10318
|
-
// The signature hash algo MUST be set to the specified algorithm, see
|
|
10319
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
10320
|
-
throw new Error('Unexpected hash algorithm for PQC signature');
|
|
10321
|
-
}
|
|
10322
|
-
|
|
10323
10406
|
switch (signatureAlgo) {
|
|
10324
10407
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10325
10408
|
const { eccSignature } = await sign$3(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, dataDigest);
|
|
@@ -10333,12 +10416,6 @@ async function sign$2(signatureAlgo, hashAlgo, eccSecretKey, eccPublicKey, mldsa
|
|
|
10333
10416
|
}
|
|
10334
10417
|
|
|
10335
10418
|
async function verify$2(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicKey, dataDigest, { eccSignature, mldsaSignature }) {
|
|
10336
|
-
if (hashAlgo !== getRequiredHashAlgo(signatureAlgo)) {
|
|
10337
|
-
// The signature hash algo MUST be set to the specified algorithm, see
|
|
10338
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
10339
|
-
throw new Error('Unexpected hash algorithm for PQC signature');
|
|
10340
|
-
}
|
|
10341
|
-
|
|
10342
10419
|
switch (signatureAlgo) {
|
|
10343
10420
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
10344
10421
|
const eccVerifiedPromise = verify$3(signatureAlgo, hashAlgo, eccPublicKey, dataDigest, eccSignature);
|
|
@@ -10351,11 +10428,12 @@ async function verify$2(signatureAlgo, hashAlgo, eccPublicKey, mldsaPublicKey, d
|
|
|
10351
10428
|
}
|
|
10352
10429
|
}
|
|
10353
10430
|
|
|
10354
|
-
function
|
|
10355
|
-
//
|
|
10431
|
+
function isCompatibleHashAlgo(signatureAlgo, hashAlgo) {
|
|
10432
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
10433
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
10356
10434
|
switch (signatureAlgo) {
|
|
10357
10435
|
case enums.publicKey.pqc_mldsa_ed25519:
|
|
10358
|
-
return
|
|
10436
|
+
return getHashByteLength(hashAlgo) >= 32;
|
|
10359
10437
|
default:
|
|
10360
10438
|
throw new Error('Unsupported signature algorithm');
|
|
10361
10439
|
}
|
|
@@ -12478,6 +12556,12 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12478
12556
|
return verify$8(oid, hashAlgo, { r, s }, data, Q, hashed);
|
|
12479
12557
|
}
|
|
12480
12558
|
case enums.publicKey.eddsaLegacy: {
|
|
12559
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12560
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12561
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12562
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12563
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12564
|
+
}
|
|
12481
12565
|
const { oid, Q } = publicParams;
|
|
12482
12566
|
const curveSize = new CurveWithOID(oid).payloadSize;
|
|
12483
12567
|
// When dealing little-endian MPI data, we always need to left-pad it, as done with big-endian values:
|
|
@@ -12488,6 +12572,13 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12488
12572
|
}
|
|
12489
12573
|
case enums.publicKey.ed25519:
|
|
12490
12574
|
case enums.publicKey.ed448: {
|
|
12575
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12576
|
+
// Enforce digest sizes:
|
|
12577
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12578
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12579
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12580
|
+
}
|
|
12581
|
+
|
|
12491
12582
|
const { A } = publicParams;
|
|
12492
12583
|
return verify$9(algo, hashAlgo, signature, data, A, hashed);
|
|
12493
12584
|
}
|
|
@@ -12500,6 +12591,11 @@ async function verify$1(algo, hashAlgo, signature, publicParams, privateParams,
|
|
|
12500
12591
|
return verify$5(algo.getValue(), keyMaterial, signature.mac.data, hashed);
|
|
12501
12592
|
}
|
|
12502
12593
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12594
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12595
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12596
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12597
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12598
|
+
}
|
|
12503
12599
|
const { eccPublicKey, mldsaPublicKey } = publicParams;
|
|
12504
12600
|
return verify$2(algo, hashAlgo, eccPublicKey, mldsaPublicKey, hashed, signature);
|
|
12505
12601
|
}
|
|
@@ -12548,12 +12644,24 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12548
12644
|
return sign$8(oid, hashAlgo, data, Q, d, hashed);
|
|
12549
12645
|
}
|
|
12550
12646
|
case enums.publicKey.eddsaLegacy: {
|
|
12647
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(enums.hash.sha256)) {
|
|
12648
|
+
// Enforce digest sizes, since the constraint was already present in RFC4880bis:
|
|
12649
|
+
// see https://tools.ietf.org/id/draft-ietf-openpgp-rfc4880bis-10.html#section-15-7.2
|
|
12650
|
+
// and https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.3-3
|
|
12651
|
+
throw new Error('Hash algorithm too weak for EdDSALegacy.');
|
|
12652
|
+
}
|
|
12551
12653
|
const { oid, Q } = publicKeyParams;
|
|
12552
12654
|
const { seed } = privateKeyParams;
|
|
12553
12655
|
return sign$7(oid, hashAlgo, data, Q, seed, hashed);
|
|
12554
12656
|
}
|
|
12555
12657
|
case enums.publicKey.ed25519:
|
|
12556
12658
|
case enums.publicKey.ed448: {
|
|
12659
|
+
if (getHashByteLength(hashAlgo) < getHashByteLength(getPreferredHashAlgo$2(algo))) {
|
|
12660
|
+
// Enforce digest sizes:
|
|
12661
|
+
// - Ed25519: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.4-4
|
|
12662
|
+
// - Ed448: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.5-4
|
|
12663
|
+
throw new Error('Hash algorithm too weak for EdDSA.');
|
|
12664
|
+
}
|
|
12557
12665
|
const { A } = publicKeyParams;
|
|
12558
12666
|
const { seed } = privateKeyParams;
|
|
12559
12667
|
return sign$9(algo, hashAlgo, data, A, seed, hashed);
|
|
@@ -12565,6 +12673,11 @@ async function sign$1(algo, hashAlgo, publicKeyParams, privateKeyParams, data, h
|
|
|
12565
12673
|
return { mac: new ShortByteString(mac) };
|
|
12566
12674
|
}
|
|
12567
12675
|
case enums.publicKey.pqc_mldsa_ed25519: {
|
|
12676
|
+
if (!isCompatibleHashAlgo(algo, hashAlgo)) {
|
|
12677
|
+
// The signature hash algo MUST have digest larger than 256 bits
|
|
12678
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4
|
|
12679
|
+
throw new Error('Unexpected hash algorithm for PQC signature: digest size too short');
|
|
12680
|
+
}
|
|
12568
12681
|
const { eccPublicKey } = publicKeyParams;
|
|
12569
12682
|
const { eccSecretKey, mldsaSecretKey } = privateKeyParams;
|
|
12570
12683
|
return sign$2(algo, hashAlgo, eccSecretKey, eccPublicKey, mldsaSecretKey, hashed);
|
|
@@ -16833,12 +16946,8 @@ class PublicKeyPacket {
|
|
|
16833
16946
|
throw new Error('Legacy curve25519 cannot be used with v6 keys');
|
|
16834
16947
|
}
|
|
16835
16948
|
// The composite ML-DSA + EdDSA schemes MUST be used only with v6 keys.
|
|
16836
|
-
|
|
16837
|
-
|
|
16838
|
-
this.algorithm === enums.publicKey.pqc_mldsa_ed25519 ||
|
|
16839
|
-
this.algorithm === enums.publicKey.pqc_mlkem_x25519
|
|
16840
|
-
)) {
|
|
16841
|
-
throw new Error('Unexpected key version: ML-DSA and ML-KEM algorithms can only be used with v6 keys');
|
|
16949
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
16950
|
+
throw new Error('Unexpected key version: ML-DSA algorithms can only be used with v6 keys');
|
|
16842
16951
|
}
|
|
16843
16952
|
this.publicParams = publicParams;
|
|
16844
16953
|
pos += read;
|
|
@@ -17838,11 +17947,8 @@ class SecretKeyPacket extends PublicKeyPacket {
|
|
|
17838
17947
|
)) {
|
|
17839
17948
|
throw new Error(`Cannot generate v6 keys of type 'ecc' with curve ${curve}. Generate a key of type 'curve25519' instead`);
|
|
17840
17949
|
}
|
|
17841
|
-
if (this.version !== 6 &&
|
|
17842
|
-
this.
|
|
17843
|
-
this.algorithm === enums.publicKey.pqc_mlkem_x25519
|
|
17844
|
-
)) {
|
|
17845
|
-
throw new Error(`Cannot generate v${this.version} keys of type 'pqc'. Generate a v6 key instead`);
|
|
17950
|
+
if (this.version !== 6 && this.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
17951
|
+
throw new Error(`Cannot generate v${this.version} signing keys of type 'pqc'. Generate a v6 key instead`);
|
|
17846
17952
|
}
|
|
17847
17953
|
const { privateParams, publicParams } = await generateParams(this.algorithm, bits, curve, symmetric);
|
|
17848
17954
|
this.privateParams = privateParams;
|
|
@@ -18346,12 +18452,6 @@ async function createBindingSignature(subkey, primaryKey, options, config) {
|
|
|
18346
18452
|
* @async
|
|
18347
18453
|
*/
|
|
18348
18454
|
async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Date(), targetUserIDs = [], config) {
|
|
18349
|
-
if (signingKeyPacket.algorithm === enums.publicKey.pqc_mldsa_ed25519) {
|
|
18350
|
-
// For PQC, the returned hash algo MUST be set to the specified algorithm, see
|
|
18351
|
-
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-pqc#section-5.2.1.
|
|
18352
|
-
return getRequiredHashAlgo(signingKeyPacket.algorithm);
|
|
18353
|
-
}
|
|
18354
|
-
|
|
18355
18455
|
/**
|
|
18356
18456
|
* If `preferredSenderAlgo` appears in the prefs of all recipients, we pick it; otherwise, we use the
|
|
18357
18457
|
* strongest supported algo (`defaultAlgo` is always implicitly supported by all keys).
|
|
@@ -18399,6 +18499,10 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18399
18499
|
enums.publicKey.ed448
|
|
18400
18500
|
]);
|
|
18401
18501
|
|
|
18502
|
+
const pqcAlgos = new Set([
|
|
18503
|
+
enums.publicKey.pqc_mldsa_ed25519
|
|
18504
|
+
]);
|
|
18505
|
+
|
|
18402
18506
|
if (eccAlgos.has(signingKeyPacket.algorithm)) {
|
|
18403
18507
|
// For ECC, the returned hash algo MUST be at least as strong as `preferredCurveHashAlgo`, see:
|
|
18404
18508
|
// - ECDSA: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.2-5
|
|
@@ -18421,6 +18525,21 @@ async function getPreferredHashAlgo(targetKeys, signingKeyPacket, date = new Dat
|
|
|
18421
18525
|
strongestSupportedAlgo :
|
|
18422
18526
|
preferredCurveAlgo;
|
|
18423
18527
|
}
|
|
18528
|
+
} else if (pqcAlgos.has(signingKeyPacket.algorithm)) {
|
|
18529
|
+
// For PQC, the returned hash algo MUST be at least 256 bit long, see:
|
|
18530
|
+
// https://www.ietf.org/archive/id/draft-ietf-openpgp-pqc-10.html#section-9.4 .
|
|
18531
|
+
// Hence, we return the `preferredHashAlgo` as long as it's supported and long enough;
|
|
18532
|
+
// Otherwise, we look at the strongest supported algo, and ultimately fallback the default algo (SHA-256).
|
|
18533
|
+
const preferredSenderAlgoIsSupported = isSupportedHashAlgo(preferredSenderAlgo) && isCompatibleHashAlgo(signingKeyPacket.algorithm, preferredSenderAlgo);
|
|
18534
|
+
|
|
18535
|
+
if (preferredSenderAlgoIsSupported) {
|
|
18536
|
+
return preferredSenderAlgo;
|
|
18537
|
+
} else {
|
|
18538
|
+
const strongestSupportedAlgo = getStrongestSupportedHashAlgo();
|
|
18539
|
+
return isCompatibleHashAlgo(signingKeyPacket.algorithm, strongestSupportedAlgo) ?
|
|
18540
|
+
strongestSupportedAlgo :
|
|
18541
|
+
defaultAlgo;
|
|
18542
|
+
}
|
|
18424
18543
|
}
|
|
18425
18544
|
|
|
18426
18545
|
// `preferredSenderAlgo` may be weaker than the default, but we do not guard against this,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@protontech/openpgp",
|
|
3
3
|
"description": "OpenPGP.js is a Javascript implementation of the OpenPGP protocol. This is defined in RFC 4880.",
|
|
4
|
-
"version": "6.1.1-patch.
|
|
4
|
+
"version": "6.1.1-patch.4",
|
|
5
5
|
"license": "LGPL-3.0+",
|
|
6
6
|
"homepage": "https://openpgpjs.org/",
|
|
7
7
|
"engines": {
|