From ca9883aa0dee454ea40fe406076391fc1f6f413f Mon Sep 17 00:00:00 2001 From: "[1000i100] Millicent Billette" <git@1000i100.fr> Date: Sun, 20 Nov 2022 17:24:38 +0100 Subject: [PATCH] v3.4.1 FIX: checkKey now throw named errors --- CHANGELOG.fr.md | 7 ++++++- npm/package.json | 2 +- src/crypto.mjs | 37 +++++++++++++++++++++++++++++++------ src/crypto.test.mjs | 8 ++++++-- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.fr.md b/CHANGELOG.fr.md index bdda49c..448826a 100644 --- a/CHANGELOG.fr.md +++ b/CHANGELOG.fr.md @@ -13,6 +13,10 @@ et ce projet adhère au [versionnage sémantique](https://semver.org/spec/v2.0.0 ## [Non-publié/Non-Stabilisé] (par [1000i100]) +## [Version 3.4.1] - 2022-11-20 (par [1000i100]) +### Corrections +- checkKey envoi désormais des erreurs nommées, utilisable pour guider les usagers. + ## [Version 3.4.0] - 2022-11-15 (par [1000i100]) ### Ajouté - crypto.textEncrypt(jsonMessage, senderPrivateKey, receiverPubKey) retourne un json format cesium+ avec `jsonMessage.title` et `jsonMessage.content` chiffrés. @@ -101,8 +105,9 @@ et ce projet adhère au [versionnage sémantique](https://semver.org/spec/v2.0.0 - intégration des librairies de crypto nécessaires - calcul de la clef publique correspondant à chaque combinaison de secrets saisie, et comparaison à la clef publique de référence. -[Non-publié/Non-Stabilisé]: https://git.duniter.org/libs/g1lib.js/-/compare/v3.4.0...main +[Non-publié/Non-Stabilisé]: https://git.duniter.org/libs/g1lib.js/-/compare/v3.4.1...main +[Version 3.4.1]: https://git.duniter.org/libs/g1lib.js/-/compare/v3.4.0...v3.4.1 [Version 3.4.0]: https://git.duniter.org/libs/g1lib.js/-/compare/v3.3.3...v3.4.0 [Version 3.3.3]: https://git.duniter.org/libs/g1lib.js/-/compare/v3.3.2...v3.3.3 [Version 3.3.2]: https://git.duniter.org/libs/g1lib.js/-/compare/v3.3.1...v3.3.2 diff --git a/npm/package.json b/npm/package.json index df79b1f..2770980 100644 --- a/npm/package.json +++ b/npm/package.json @@ -1,6 +1,6 @@ { "name": "g1lib", - "version": "3.4.0", + "version": "3.4.1", "description": "An ubiquitous static javascript toolbox lib for Ǧ1 / Duniter ecosystem with reliability in mind.", "main": "nodejs/all.mjs", "browser": "browser/all.mjs", diff --git a/src/crypto.mjs b/src/crypto.mjs index cac959e..36d66f6 100644 --- a/src/crypto.mjs +++ b/src/crypto.mjs @@ -121,14 +121,25 @@ export function onlyPubKey(pubKeyWithChecksum){ if (pubKey2checksum(b58pubKey, true, false, false) === checkSum) return b58pubKey; if (pubKey2checksum(b58pubKey, false, true, false) === checkSum) return b58pubKey; if (pubKey2checksum(b58pubKey, true, true, false) === checkSum) return b58pubKey; - throw new Error('Bad checksum'); + throw new CustomError('bad_checksum','Bad checksum'); } export function isDuniterPubKey(b58pubKey){ return /^[A-HJ-NP-Za-km-z1-9]{43,44}$/.test(b58pubKey) && b58.decode(b58pubKey).length <=32; } +export function checkDuniterPubKey(b58pubKey){ + if(b58pubKey.length<43) throw new CustomError('too_short','Too short, see rfc/0009_Duniter_Blockchain_Protocol_V11.md#public-key for details.'); + if(b58pubKey.length>44) throw new CustomError('too_long','Base58 string too long, see rfc/0009_Duniter_Blockchain_Protocol_V11.md#public-key for details.'); + if(!/^[A-HJ-NP-Za-km-z1-9]+$/.test(b58pubKey)) throw new CustomError('not_b58', 'Character out of base 58, see rfc/0009_Duniter_Blockchain_Protocol_V11.md#public-key for details.'); + if(b58.decode(b58pubKey).length > 32) throw new CustomError('too_long','binary key too long, see rfc/0009_Duniter_Blockchain_Protocol_V11.md#public-key for details.'); + return true; +} export function checkEd25519PubKey(b58pubKey){ const binPubKey = pubKey2bin(b58pubKey); - ed25519.Point.fromHex(binPubKey); + try{ + ed25519.Point.fromHex(binPubKey); + } catch (err){ + throw new CustomError('bad_ed25519_point',`Invalid public key : not a valid ed25519 point RFC8032 5.1.3 https://www.rfc-editor.org/rfc/rfc8032#page-11 Internal:${err}`); + } return true; } export function isEd25519PubKey(b58pubKey){ @@ -138,11 +149,19 @@ export function isEd25519PubKey(b58pubKey){ } export function checkKey(pubKey, checkRawPubKey= true) { - const binPubKey = pubKey2bin(pubKey) - const b58pubKey = b58.encode(binPubKey); + if(!pubKey) throw new CustomError('empty','Invalid public key : empty input.') + let b58pubKey; + try { + const binPubKey = pubKey2bin(pubKey) + b58pubKey = b58.encode(binPubKey); + } catch (err){ + if(err.message.match(/base58/)) throw new CustomError('not_b58', 'Character out of base 58, see rfc/0009_Duniter_Blockchain_Protocol_V11.md#public-key for details.'); + if(err.message.match(/out of bounds/)) throw new CustomError('too_long','Binary key too long, see rfc/0009_Duniter_Blockchain_Protocol_V11.md#public-key for details.'); + throw err; + } if(!checkRawPubKey) return true; - if(!isDuniterPubKey(b58pubKey)) throw new Error("Invalid public key : this string don't follow rfc/0009_Duniter_Blockchain_Protocol_V11.md#public-key"); - if(!isEd25519PubKey(b58pubKey)) throw new Error("Invalid public key : not a valid ed25519 point RFC8032 5.1.3 https://www.rfc-editor.org/rfc/rfc8032#page-11"); + checkDuniterPubKey(b58pubKey); + checkEd25519PubKey(b58pubKey); return true; } export function isPubKey(pubKey){ @@ -229,3 +248,9 @@ export function textDecrypt(jsonMessage, receiverPrivateKey){ if(jsonMessage.title) res.title = decrypt(jsonMessage.title); return res; } +class CustomError extends Error { + constructor(name, message) { + super(message); + this.name = name; + } +} diff --git a/src/crypto.test.mjs b/src/crypto.test.mjs index 2c45600..6c07e9b 100644 --- a/src/crypto.test.mjs +++ b/src/crypto.test.mjs @@ -128,8 +128,12 @@ test("isEd25519PubKey fail if point is not on ed25519", (t) => t.false(app.isEd2 test('checkKey accept valid pubKey with no checksum', t => t.true(app.checkKey(pubKey))); -test('checkKey throw if invalid pubkey is given', t => t.throws(() => app.checkKey(pubKey.replace(/6/,'9')))); -test('checkKey throw if empty pubkey is given', t => t.throws(() => app.checkKey(''))); +test('checkKey throw if empty pubkey is given', t => t.throws(() => app.checkKey(''),{name:'empty'})); +test('checkKey throw if under_sized string is given', t => t.throws(() => app.checkKey('test'),{name:'too_short'})); +test('checkKey throw if over_sized string is given', t => t.throws(() => app.checkKey(pubKey+pubKey),{name:'too_long'})); +test('checkKey throw if invalid pubkey is given (not on ed25519 curve)', t => t.throws(() => app.checkKey(pubKey.replace(/6/,'9')),{name:'bad_ed25519_point'})); +test('checkKey throw if checksum is incorrect', t => t.throws(() => app.checkKey(`${pubKey}:111`),{name:'bad_checksum'})); +test('checkKey throw if not b58 string is given', t => t.throws(() => app.checkKey(`___`),{name:'not_b58'})); test('checkKey accept valid binary pubKey', t => t.true(app.checkKey(app.b58.decode(pubKey)))); -- GitLab