From 06cf027d4e03da2ce885394069c9ed87dad3cc7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:48:14 +0000 Subject: [PATCH 1/4] Bump @noble/curves to v2 --- package-lock.json | 25 ++++-- package.json | 2 +- .../elliptic/brainpool/brainpoolP256r1.ts | 23 ----- .../elliptic/brainpool/brainpoolP384r1.ts | 23 ----- .../elliptic/brainpool/brainpoolP512r1.ts | 23 ----- src/crypto/public_key/elliptic/ecdsa.js | 25 +++--- .../public_key/elliptic/noble_curves.js | 12 +-- test/crypto/brainpool_rfc7027.js | 83 ------------------- test/crypto/index.js | 2 - 9 files changed, 36 insertions(+), 182 deletions(-) delete mode 100644 src/crypto/public_key/elliptic/brainpool/brainpoolP256r1.ts delete mode 100644 src/crypto/public_key/elliptic/brainpool/brainpoolP384r1.ts delete mode 100644 src/crypto/public_key/elliptic/brainpool/brainpoolP512r1.ts delete mode 100644 test/crypto/brainpool_rfc7027.js diff --git a/package-lock.json b/package-lock.json index 72322814..912facf2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@eslint/js": "^9.37.0", "@noble/ciphers": "^1.3.0", - "@noble/curves": "^1.9.7", + "@noble/curves": "^2.0.1", "@noble/hashes": "^1.8.0", "@openpgp/jsdoc": "^3.6.11", "@openpgp/seek-bzip": "^1.0.5-git", @@ -1041,16 +1041,29 @@ } }, "node_modules/@noble/curves": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", - "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz", + "integrity": "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==", "dev": true, "license": "MIT", "dependencies": { - "@noble/hashes": "1.8.0" + "@noble/hashes": "2.0.1" }, "engines": { - "node": "^14.21.3 || >=16" + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", + "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" diff --git a/package.json b/package.json index faddef68..8dc52723 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "devDependencies": { "@eslint/js": "^9.37.0", "@noble/ciphers": "^1.3.0", - "@noble/curves": "^1.9.7", + "@noble/curves": "^2.0.1", "@noble/hashes": "^1.8.0", "@openpgp/jsdoc": "^3.6.11", "@openpgp/seek-bzip": "^1.0.5-git", diff --git a/src/crypto/public_key/elliptic/brainpool/brainpoolP256r1.ts b/src/crypto/public_key/elliptic/brainpool/brainpoolP256r1.ts deleted file mode 100644 index a1d25067..00000000 --- a/src/crypto/public_key/elliptic/brainpool/brainpoolP256r1.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createCurve } from '@noble/curves/_shortw_utils'; -import { sha256 } from '@noble/hashes/sha256'; -import { Field } from '@noble/curves/abstract/modular'; - -// brainpoolP256r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.4 - -const Fp = Field(BigInt('0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377')); -const CURVE_A = Fp.create(BigInt('0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9')); -const CURVE_B = BigInt('0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6'); - -// prettier-ignore -export const brainpoolP256r1 = createCurve({ - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp, - // Curve order (q), total count of valid points in the field - n: BigInt('0xa9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a7'), - // Base (generator) point (x, y) - Gx: BigInt('0x8bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262'), - Gy: BigInt('0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997'), - h: BigInt(1), - lowS: false -} as const, sha256); diff --git a/src/crypto/public_key/elliptic/brainpool/brainpoolP384r1.ts b/src/crypto/public_key/elliptic/brainpool/brainpoolP384r1.ts deleted file mode 100644 index 0ba5dc52..00000000 --- a/src/crypto/public_key/elliptic/brainpool/brainpoolP384r1.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createCurve } from '@noble/curves/_shortw_utils'; -import { sha384 } from '@noble/hashes/sha512'; -import { Field } from '@noble/curves/abstract/modular'; - -// brainpoolP384 r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.6 - -const Fp = Field(BigInt('0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53')); -const CURVE_A = Fp.create(BigInt('0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f8aa5814a503ad4eb04a8c7dd22ce2826')); -const CURVE_B = BigInt('0x04a8c7dd22ce28268b39b55416f0447c2fb77de107dcd2a62e880ea53eeb62d57cb4390295dbc9943ab78696fa504c11'); - -// prettier-ignore -export const brainpoolP384r1 = createCurve({ - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp, - // Curve order (q), total count of valid points in the field - n: BigInt('0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b31f166e6cac0425a7cf3ab6af6b7fc3103b883202e9046565'), - // Base (generator) point (x, y) - Gx: BigInt('0x1d1c64f068cf45ffa2a63a81b7c13f6b8847a3e77ef14fe3db7fcafe0cbd10e8e826e03436d646aaef87b2e247d4af1e'), - Gy: BigInt('0x8abe1d7520f9c2a45cb1eb8e95cfd55262b70b29feec5864e19c054ff99129280e4646217791811142820341263c5315'), - h: BigInt(1), - lowS: false -} as const, sha384); diff --git a/src/crypto/public_key/elliptic/brainpool/brainpoolP512r1.ts b/src/crypto/public_key/elliptic/brainpool/brainpoolP512r1.ts deleted file mode 100644 index a4866bac..00000000 --- a/src/crypto/public_key/elliptic/brainpool/brainpoolP512r1.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createCurve } from '@noble/curves/_shortw_utils'; -import { sha512 } from '@noble/hashes/sha512'; -import { Field } from '@noble/curves/abstract/modular'; - -// brainpoolP512r1: https://datatracker.ietf.org/doc/html/rfc5639#section-3.7 - -const Fp = Field(BigInt('0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3')); -const CURVE_A = Fp.create(BigInt('0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94ca')); -const CURVE_B = BigInt('0x3df91610a83441caea9863bc2ded5d5aa8253aa10a2ef1c98b9ac8b57f1117a72bf2c7b9e7c1ac4d77fc94cadc083e67984050b75ebae5dd2809bd638016f723'); - -// prettier-ignore -export const brainpoolP512r1 = createCurve({ - a: CURVE_A, // Equation params: a, b - b: CURVE_B, - Fp, - // Curve order (q), total count of valid points in the field - n: BigInt('0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330870553e5c414ca92619418661197fac10471db1d381085ddaddb58796829ca90069'), - // Base (generator) point (x, y) - Gx: BigInt('0x81aee4bdd82ed9645a21322e9c4c6a9385ed9f70b5d916c1b43b62eef4d0098eff3b1f78e2d0d48d50d1687b93b97d5f7c6d5047406a5e688b352209bcb9f822'), - Gy: BigInt('0x7dde385d566332ecc0eabfa9cf7822fdf209f70024a57b1aa000c55b881f8111b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892'), - h: BigInt(1), - lowS: false -} as const, sha512); diff --git a/src/crypto/public_key/elliptic/ecdsa.js b/src/crypto/public_key/elliptic/ecdsa.js index ab98d618..4c5f318f 100644 --- a/src/crypto/public_key/elliptic/ecdsa.js +++ b/src/crypto/public_key/elliptic/ecdsa.js @@ -25,7 +25,6 @@ import util from '../../../util'; import { getRandomBytes } from '../../random'; import { computeDigest } from '../../hash'; import { CurveWithOID, webCurves, privateToJWK, rawPublicToJWK, validateStandardParams, nodeCurves, checkPublicPointEnconding } from './oid_curves'; -import { bigIntToUint8Array } from '../../biginteger'; const webCrypto = util.getWebCrypto(); const nodeCrypto = util.getNodeCrypto(); @@ -72,10 +71,10 @@ export async function sign(oid, hashAlgo, message, publicKey, privateKey, hashed const nobleCurve = await util.getNobleCurve(enums.publicKey.ecdsa, curve.name); // lowS: non-canonical sig: https://stackoverflow.com/questions/74338846/ecdsa-signature-verification-mismatch - const signature = nobleCurve.sign(hashed, privateKey, { lowS: false }); + const signature = nobleCurve.sign(hashed, privateKey, { lowS: false, prehash: false }); return { - r: bigIntToUint8Array(signature.r, 'be', curve.payloadSize), - s: bigIntToUint8Array(signature.s, 'be', curve.payloadSize) + r: signature.slice(0, curve.payloadSize), + s: signature.slice(curve.payloadSize, curve.payloadSize << 1) }; } @@ -183,7 +182,7 @@ export async function validateParams(oid, Q, d) { async function jsVerify(curve, signature, hashed, publicKey) { const nobleCurve = await util.getNobleCurve(enums.publicKey.ecdsa, curve.name); // lowS: non-canonical sig: https://stackoverflow.com/questions/74338846/ecdsa-signature-verification-mismatch - return nobleCurve.verify(util.concatUint8Array([signature.r, signature.s]), hashed, publicKey, { lowS: false }); + return nobleCurve.verify(util.concatUint8Array([signature.r, signature.s]), hashed, publicKey, { lowS: false, prehash: false }); } async function webSign(curve, hashAlgo, message, keyPair) { @@ -254,11 +253,11 @@ function nodeSign(curve, hashAlgo, message, privateKey) { privateKey: nodeBuffer.from(privateKey) }); - const sign = nodeCrypto.createSign(enums.read(enums.hash, hashAlgo)); - sign.write(message); - sign.end(); + const signInstance = nodeCrypto.createSign(enums.read(enums.hash, hashAlgo)); + signInstance.write(message); + signInstance.end(); - const signature = new Uint8Array(sign.sign({ key: derPrivateKey, format: 'der', type: 'sec1', dsaEncoding: 'ieee-p1363' })); + const signature = new Uint8Array(signInstance.sign({ key: derPrivateKey, format: 'der', type: 'sec1', dsaEncoding: 'ieee-p1363' })); const len = curve.payloadSize; return { @@ -275,14 +274,14 @@ function nodeVerify(curve, hashAlgo, { r, s }, message, publicKey) { publicKey: nodeBuffer.from(publicKey) }); - const verify = nodeCrypto.createVerify(enums.read(enums.hash, hashAlgo)); - verify.write(message); - verify.end(); + const verifyInstance = nodeCrypto.createVerify(enums.read(enums.hash, hashAlgo)); + verifyInstance.write(message); + verifyInstance.end(); const signature = util.concatUint8Array([r, s]); try { - return verify.verify({ key: derPublicKey, format: 'der', type: 'spki', dsaEncoding: 'ieee-p1363' }, signature); + return verifyInstance.verify({ key: derPublicKey, format: 'der', type: 'spki', dsaEncoding: 'ieee-p1363' }, signature); } catch { return false; } diff --git a/src/crypto/public_key/elliptic/noble_curves.js b/src/crypto/public_key/elliptic/noble_curves.js index acfac17e..c503ca63 100644 --- a/src/crypto/public_key/elliptic/noble_curves.js +++ b/src/crypto/public_key/elliptic/noble_curves.js @@ -4,14 +4,10 @@ * which share a lot of code anyway. */ -import { p256 as nistP256 } from '@noble/curves/p256'; -import { p384 as nistP384 } from '@noble/curves/p384'; -import { p521 as nistP521 } from '@noble/curves/p521'; -import { x448, ed448 } from '@noble/curves/ed448'; -import { secp256k1 } from '@noble/curves/secp256k1'; -import { brainpoolP256r1 } from './brainpool/brainpoolP256r1'; -import { brainpoolP384r1 } from './brainpool/brainpoolP384r1'; -import { brainpoolP512r1 } from './brainpool/brainpoolP512r1'; +import { p256 as nistP256, p384 as nistP384, p521 as nistP521 } from '@noble/curves/nist.js'; +import { x448, ed448 } from '@noble/curves/ed448.js'; +import { secp256k1 } from '@noble/curves/secp256k1.js'; +import { brainpoolP256r1, brainpoolP384r1, brainpoolP512r1 } from '@noble/curves/misc.js'; export const nobleCurves = new Map(Object.entries({ nistP256, diff --git a/test/crypto/brainpool_rfc7027.js b/test/crypto/brainpool_rfc7027.js deleted file mode 100644 index b28ff9cb..00000000 --- a/test/crypto/brainpool_rfc7027.js +++ /dev/null @@ -1,83 +0,0 @@ -import { expect } from 'chai'; - -import { brainpoolP256r1 } from '../../src/crypto/public_key/elliptic/brainpool/brainpoolP256r1'; -import { brainpoolP384r1 } from '../../src/crypto/public_key/elliptic/brainpool/brainpoolP384r1'; -import { brainpoolP512r1 } from '../../src/crypto/public_key/elliptic/brainpool/brainpoolP512r1'; -import util from '../../src/util'; - -const rfc7027 = [ - { - 'curve': 'brainpoolP256r1', - 'dA': '81DB1EE100150FF2EA338D708271BE38300CB54241D79950F77B063039804F1D', - 'QAx': '44106E913F92BC02A1705D9953A8414DB95E1AAA49E81D9E85F929A8E3100BE5', - 'QAy': '8AB4846F11CACCB73CE49CBDD120F5A900A69FD32C272223F789EF10EB089BDC', - 'dB': '55E40BC41E37E3E2AD25C3C6654511FFA8474A91A0032087593852D3E7D76BD3', - 'QBx': '8D2D688C6CF93E1160AD04CC4429117DC2C41825E1E9FCA0ADDD34E6F1B39F7B', - 'QBy': '990C57520812BE512641E47034832106BC7D3E8DD0E4C7F1136D7006547CEC6A', - 'Zx': '89AFC39D41D3B327814B80940B042590F96556EC91E6AE7939BCE31F3A18BF2B', - 'Zy': '49C27868F4ECA2179BFD7D59B1E3BF34C1DBDE61AE12931648F43E59632504DE' - }, - { - 'curve': 'brainpoolP384r1', - 'dA': '1E20F5E048A5886F1F157C74E91BDE2B98C8B52D58E5003D57053FC4B0BD65D6F15EB5D1EE1610DF870795143627D042', - 'QAx': '68B665DD91C195800650CDD363C625F4E742E8134667B767B1B476793588F885AB698C852D4A6E77A252D6380FCAF068', - 'QAy': '55BC91A39C9EC01DEE36017B7D673A931236D2F1F5C83942D049E3FA20607493E0D038FF2FD30C2AB67D15C85F7FAA59', - 'dB': '032640BC6003C59260F7250C3DB58CE647F98E1260ACCE4ACDA3DD869F74E01F8BA5E0324309DB6A9831497ABAC96670', - 'QBx': '4D44326F269A597A5B58BBA565DA5556ED7FD9A8A9EB76C25F46DB69D19DC8CE6AD18E404B15738B2086DF37E71D1EB4', - 'QBy': '62D692136DE56CBE93BF5FA3188EF58BC8A3A0EC6C1E151A21038A42E9185329B5B275903D192F8D4E1F32FE9CC78C48', - 'Zx': '0BD9D3A7EA0B3D519D09D8E48D0785FB744A6B355E6304BC51C229FBBCE239BBADF6403715C35D4FB2A5444F575D4F42', - 'Zy': '0DF213417EBE4D8E40A5F76F66C56470C489A3478D146DECF6DF0D94BAE9E598157290F8756066975F1DB34B2324B7BD' - }, - { - 'curve': 'brainpoolP512r1', - 'dA': '16302FF0DBBB5A8D733DAB7141C1B45ACBC8715939677F6A56850A38BD87BD59B09E80279609FF333EB9D4C061231FB26F92EEB04982A5F1D1764CAD57665422', - 'QAx': '0A420517E406AAC0ACDCE90FCD71487718D3B953EFD7FBEC5F7F27E28C6149999397E91E029E06457DB2D3E640668B392C2A7E737A7F0BF04436D11640FD09FD', - 'QAy': '72E6882E8DB28AAD36237CD25D580DB23783961C8DC52DFA2EC138AD472A0FCEF3887CF62B623B2A87DE5C588301EA3E5FC269B373B60724F5E82A6AD147FDE7', - 'dB': '230E18E1BCC88A362FA54E4EA3902009292F7F8033624FD471B5D8ACE49D12CFABBC19963DAB8E2F1EBA00BFFB29E4D72D13F2224562F405CB80503666B25429', - 'QBx': '9D45F66DE5D67E2E6DB6E93A59CE0BB48106097FF78A081DE781CDB31FCE8CCBAAEA8DD4320C4119F1E9CD437A2EAB3731FA9668AB268D871DEDA55A5473199F', - 'QBy': '2FDC313095BCDD5FB3A91636F07A959C8E86B5636A1E930E8396049CB481961D365CC11453A06C719835475B12CB52FC3C383BCE35E27EF194512B71876285FA', - 'Zx': 'A7927098655F1F9976FA50A9D566865DC530331846381C87256BAF3226244B76D36403C024D7BBF0AA0803EAFF405D3D24F11A9B5C0BEF679FE1454B21C4CD1F', - 'Zy': '7DB71C3DEF63212841C463E881BDCF055523BD368240E6C3143BD8DEF8B3B3223B95E0F53082FF5E412F4222537A43DF1C6D25729DDB51620A832BE6A26680A2' - } -]; - -const hexToBigint = hex => BigInt(`0x${hex}`); - -// prettier-ignore -const BRAINPOOL = { - brainpoolP256r1, - brainpoolP384r1, - brainpoolP512r1 -}; - -export default () => describe('Brainpool curves (RFC7027)', () => { - it('Field orders', () => { - const vectors = { - brainpoolP256r1: BigInt('0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377'), - brainpoolP384r1: BigInt('0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123acd3a729901d1a71874700133107ec53'), - brainpoolP512r1: BigInt('0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca703308717d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3') - }; - for (const n of Object.keys(vectors)) { expect(BRAINPOOL[n].CURVE.Fp.ORDER).to.deep.equal(vectors[n]); } - }); - - for (const v of rfc7027) { - it(v.curve, () => { - const curve = BRAINPOOL[v.curve]; - const secKeyA = util.hexToUint8Array(v.dA); - const pubKeyA = curve.getPublicKey(secKeyA); - const pubPointA = curve.ProjectivePoint.fromHex(pubKeyA); - expect(pubPointA.x).to.equal(hexToBigint(v.QAx)); - expect(pubPointA.y).to.equal(hexToBigint(v.QAy)); - const secKeyB = hexToBigint(v.dB); - const pubKeyB = curve.getPublicKey(secKeyB); - const pubPointB = curve.ProjectivePoint.fromHex(pubKeyB); - expect(pubPointB.x).to.equal(hexToBigint(v.QBx)); - expect(pubPointB.y).to.equal(hexToBigint(v.QBy)); - const shared = curve.getSharedSecret(secKeyA, pubKeyB); - const sharedPoint = curve.ProjectivePoint.fromHex(shared); - expect(sharedPoint.x).to.equal(hexToBigint(v.Zx)); - expect(sharedPoint.y).to.equal(hexToBigint(v.Zy)); - expect(shared).to.deep.equal(curve.getSharedSecret(secKeyB, pubKeyA)); - }); - } -}); diff --git a/test/crypto/index.js b/test/crypto/index.js index 5e7567ff..b222b964 100644 --- a/test/crypto/index.js +++ b/test/crypto/index.js @@ -3,7 +3,6 @@ import testCipher from './cipher'; import testHash from './hash'; import testCrypto from './crypto'; import testElliptic from './ecdsa_eddsa'; -import testBrainpoolRFC7027 from './brainpool_rfc7027'; import testECDH from './ecdh'; import testPKCS5 from './pkcs5'; import testAESKW from './aes_kw'; @@ -20,7 +19,6 @@ export default () => describe('Crypto', function () { testHash(); testCrypto(); testElliptic(); - testBrainpoolRFC7027(); testECDH(); testPKCS5(); testAESKW(); From c40eb64743d828894653262689147a58f46b3e15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:48:21 +0000 Subject: [PATCH 2/4] Bump @noble/hashes to v2 --- package-lock.json | 17 +------- package.json | 2 +- src/crypto/hash/md5.ts | 77 --------------------------------- src/crypto/hash/noble_hashes.js | 9 ++-- 4 files changed, 6 insertions(+), 99 deletions(-) delete mode 100644 src/crypto/hash/md5.ts diff --git a/package-lock.json b/package-lock.json index 912facf2..1a7dd67f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@eslint/js": "^9.37.0", "@noble/ciphers": "^1.3.0", "@noble/curves": "^2.0.1", - "@noble/hashes": "^1.8.0", + "@noble/hashes": "^2.0.1", "@openpgp/jsdoc": "^3.6.11", "@openpgp/seek-bzip": "^1.0.5-git", "@openpgp/tweetnacl": "^1.0.4-2", @@ -1056,7 +1056,7 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { + "node_modules/@noble/hashes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", @@ -1069,19 +1069,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", diff --git a/package.json b/package.json index 8dc52723..3a72bb22 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "@eslint/js": "^9.37.0", "@noble/ciphers": "^1.3.0", "@noble/curves": "^2.0.1", - "@noble/hashes": "^1.8.0", + "@noble/hashes": "^2.0.1", "@openpgp/jsdoc": "^3.6.11", "@openpgp/seek-bzip": "^1.0.5-git", "@openpgp/tweetnacl": "^1.0.4-2", diff --git a/src/crypto/hash/md5.ts b/src/crypto/hash/md5.ts deleted file mode 100644 index 80f0261c..00000000 --- a/src/crypto/hash/md5.ts +++ /dev/null @@ -1,77 +0,0 @@ -// Copied from https://github.com/paulmillr/noble-hashes/blob/main/test/misc/md5.ts - -import { HashMD } from '@noble/hashes/_md'; -import { rotl, wrapConstructor } from '@noble/hashes/utils'; - -// Per-round constants -const K = Array.from({ length: 64 }, (_, i) => Math.floor(2 ** 32 * Math.abs(Math.sin(i + 1)))); -// Choice: a ? b : c -const Chi = (a: number, b: number, c: number) => (a & b) ^ (~a & c); -// Initial state (same as sha1, but 4 u32 instead of 5) -const IV = /* @__PURE__ */ new Uint32Array([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]); -// Temporary buffer, not used to store anything between runs -// Named this way for SHA1 compat -const MD5_W = /* @__PURE__ */ new Uint32Array(16); -class MD5 extends HashMD { - private A = IV[0] | 0; - private B = IV[1] | 0; - private C = IV[2] | 0; - private D = IV[3] | 0; - constructor() { - super(64, 16, 8, true); - } - protected get(): [number, number, number, number] { - const { A, B, C, D } = this; - return [A, B, C, D]; - } - protected set(A: number, B: number, C: number, D: number) { - this.A = A | 0; - this.B = B | 0; - this.C = C | 0; - this.D = D | 0; - } - protected process(view: DataView, offset: number): void { - for (let i = 0; i < 16; i++, offset += 4) MD5_W[i] = view.getUint32(offset, true); - // Compression function main loop, 64 rounds - let { A, B, C, D } = this; - for (let i = 0; i < 64; i++) { - let F, g, s; - if (i < 16) { - F = Chi(B, C, D); - g = i; - s = [7, 12, 17, 22]; - } else if (i < 32) { - F = Chi(D, B, C); - g = (5 * i + 1) % 16; - s = [5, 9, 14, 20]; - } else if (i < 48) { - F = B ^ C ^ D; - g = (3 * i + 5) % 16; - s = [4, 11, 16, 23]; - } else { - F = C ^ (B | ~D); - g = (7 * i) % 16; - s = [6, 10, 15, 21]; - } - F = F + A + K[i] + MD5_W[g]; - A = D; - D = C; - C = B; - B = B + rotl(F, s[i % 4]); - } - // Add the compressed chunk to the current hash value - A = (A + this.A) | 0; - B = (B + this.B) | 0; - C = (C + this.C) | 0; - D = (D + this.D) | 0; - this.set(A, B, C, D); - } - protected roundClean() { - MD5_W.fill(0); - } - destroy() { - this.set(0, 0, 0, 0); - this.buffer.fill(0); - } -} -export const md5 = /* @__PURE__ */ wrapConstructor(() => new MD5()); diff --git a/src/crypto/hash/noble_hashes.js b/src/crypto/hash/noble_hashes.js index 605afa29..3c0cff91 100644 --- a/src/crypto/hash/noble_hashes.js +++ b/src/crypto/hash/noble_hashes.js @@ -4,12 +4,9 @@ * which share a lot of code anyway. */ -import { sha1 } from '@noble/hashes/sha1'; -import { sha224, sha256 } from '@noble/hashes/sha256'; -import { sha384, sha512 } from '@noble/hashes/sha512'; -import { sha3_256, sha3_512 } from '@noble/hashes/sha3'; -import { ripemd160 } from '@noble/hashes/ripemd160'; -import { md5 } from './md5'; +import { sha224, sha256, sha384, sha512 } from '@noble/hashes/sha2.js'; +import { sha3_256, sha3_512 } from '@noble/hashes/sha3.js'; +import { md5, ripemd160, sha1 } from '@noble/hashes/legacy.js'; export const nobleHashes = new Map(Object.entries({ md5, From d378219031988ac24fba31fd9489486ab21dc20a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:48:23 +0000 Subject: [PATCH 3/4] Bump @noble/ciphers to v2 --- package-lock.json | 10 +++++----- package.json | 2 +- src/crypto/aes_kw.js | 2 +- src/crypto/cipherMode/cfb.js | 2 +- src/crypto/cipherMode/eax.js | 2 +- src/crypto/cipherMode/gcm.js | 2 +- src/crypto/cipherMode/ocb.js | 2 +- src/crypto/cmac.js | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a7dd67f..4755d979 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "LGPL-3.0+", "devDependencies": { "@eslint/js": "^9.37.0", - "@noble/ciphers": "^1.3.0", + "@noble/ciphers": "^2.0.1", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "@openpgp/jsdoc": "^3.6.11", @@ -1028,13 +1028,13 @@ } }, "node_modules/@noble/ciphers": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", - "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.0.1.tgz", + "integrity": "sha512-xHK3XHPUW8DTAobU+G0XT+/w+JLM7/8k1UFdB5xg/zTFPnFCobhftzw8wl4Lw2aq/Rvir5pxfZV5fEazmeCJ2g==", "dev": true, "license": "MIT", "engines": { - "node": "^14.21.3 || >=16" + "node": ">= 20.19.0" }, "funding": { "url": "https://paulmillr.com/funding/" diff --git a/package.json b/package.json index 3a72bb22..5e4429a2 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ }, "devDependencies": { "@eslint/js": "^9.37.0", - "@noble/ciphers": "^1.3.0", + "@noble/ciphers": "^2.0.1", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "@openpgp/jsdoc": "^3.6.11", diff --git a/src/crypto/aes_kw.js b/src/crypto/aes_kw.js index 87a1c9fd..204833f7 100644 --- a/src/crypto/aes_kw.js +++ b/src/crypto/aes_kw.js @@ -21,7 +21,7 @@ * @module crypto/aes_kw */ -import { aeskw as nobleAesKW } from '@noble/ciphers/aes'; +import { aeskw as nobleAesKW } from '@noble/ciphers/aes.js'; import { getCipherParams } from './cipher'; import util from '../util'; diff --git a/src/crypto/cipherMode/cfb.js b/src/crypto/cipherMode/cfb.js index 79bcdb2c..8771133f 100644 --- a/src/crypto/cipherMode/cfb.js +++ b/src/crypto/cipherMode/cfb.js @@ -21,7 +21,7 @@ * @module crypto/mode/cfb */ -import { cfb as nobleAesCfb, unsafe as nobleAesHelpers } from '@noble/ciphers/aes'; +import { cfb as nobleAesCfb, unsafe as nobleAesHelpers } from '@noble/ciphers/aes.js'; import { transform as streamTransform } from '@openpgp/web-stream-tools'; import util from '../../util'; diff --git a/src/crypto/cipherMode/eax.js b/src/crypto/cipherMode/eax.js index bcdb266b..ccfde650 100644 --- a/src/crypto/cipherMode/eax.js +++ b/src/crypto/cipherMode/eax.js @@ -21,7 +21,7 @@ * @module crypto/mode/eax */ -import { ctr as nobleAesCtr } from '@noble/ciphers/aes'; +import { ctr as nobleAesCtr } from '@noble/ciphers/aes.js'; import CMAC from '../cmac'; import util from '../../util'; import enums from '../../enums'; diff --git a/src/crypto/cipherMode/gcm.js b/src/crypto/cipherMode/gcm.js index 226d3eb9..171d4d6a 100644 --- a/src/crypto/cipherMode/gcm.js +++ b/src/crypto/cipherMode/gcm.js @@ -21,7 +21,7 @@ * @module crypto/mode/gcm */ -import { gcm as nobleAesGcm } from '@noble/ciphers/aes'; +import { gcm as nobleAesGcm } from '@noble/ciphers/aes.js'; import util from '../../util'; import enums from '../../enums'; diff --git a/src/crypto/cipherMode/ocb.js b/src/crypto/cipherMode/ocb.js index 7b989426..598b4609 100644 --- a/src/crypto/cipherMode/ocb.js +++ b/src/crypto/cipherMode/ocb.js @@ -20,7 +20,7 @@ * @module crypto/mode/ocb */ -import { cbc as nobleAesCbc } from '@noble/ciphers/aes'; +import { cbc as nobleAesCbc } from '@noble/ciphers/aes.js'; import { getCipherParams } from '../cipher'; import util from '../../util'; diff --git a/src/crypto/cmac.js b/src/crypto/cmac.js index 8dbf6a99..6ab25fd4 100644 --- a/src/crypto/cmac.js +++ b/src/crypto/cmac.js @@ -4,7 +4,7 @@ * @module crypto/cmac */ -import { cbc as nobleAesCbc } from '@noble/ciphers/aes'; +import { cbc as nobleAesCbc } from '@noble/ciphers/aes.js'; import util from '../util'; const webCrypto = util.getWebCrypto(); From 89e05c5aa9a6558d30e435351b4fc5e558a2c830 Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Mon, 20 Oct 2025 17:50:04 +0200 Subject: [PATCH 4/4] Drop support for Node v18 (require v20.19+) Node v18 has been EOL since March 2025. The noble libraries require v20.19+, so we align with those to avoid development warnings. --- .github/workflows/tests.yml | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c3f0e656..5fa84f37 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: false # if tests for one version fail, continue with the rest matrix: - node-version: [18.x, 20.x, 22.x, 24.x] + node-version: [20.x, 22.x, 24.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ name: Node ${{ matrix.node-version }} diff --git a/package-lock.json b/package-lock.json index 4755d979..881b3cd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,7 +56,7 @@ "web-streams-polyfill": "^4.2.0" }, "engines": { - "node": ">= 18.0.0" + "node": ">= 20.19.0" } }, "node_modules/@babel/code-frame": { diff --git a/package.json b/package.json index 5e4429a2..47ec2c5e 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "license": "LGPL-3.0+", "homepage": "https://openpgpjs.org/", "engines": { - "node": ">= 18.0.0" + "node": ">= 20.19.0" }, "keywords": [ "crypto",