From 6621053c7d05afcb661335fb871205132487fe9b Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Thu, 4 May 2023 23:39:53 +0000 Subject: [PATCH] edwards: ensure Point.fromHex fails when x=0 and first x bit is 1. gh-40 --- src/abstract/edwards.ts | 14 +++++++++++--- test/ed25519.test.js | 13 +++++++++++++ test/ed25519/edge-cases.json | 1 + 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 test/ed25519/edge-cases.json diff --git a/src/abstract/edwards.ts b/src/abstract/edwards.ts index 3eae5f3..5834400 100644 --- a/src/abstract/edwards.ts +++ b/src/abstract/edwards.ts @@ -75,8 +75,13 @@ export interface ExtPointConstructor extends GroupConstructor { export type CurveFn = { CURVE: ReturnType; getPublicKey: (privateKey: Hex) => Uint8Array; - sign: (message: Hex, privateKey: Hex) => Uint8Array; - verify: (sig: Hex, message: Hex, publicKey: Hex) => boolean; + sign: (message: Hex, privateKey: Hex, options?: { context?: Hex }) => Uint8Array; + verify: ( + sig: Hex, + message: Hex, + publicKey: Hex, + options?: { context?: Hex; zip215: boolean } + ) => boolean; ExtendedPoint: ExtPointConstructor; utils: { randomPrivateKey: () => Uint8Array; @@ -379,7 +384,10 @@ export function twistedEdwards(curveDef: CurveType): CurveFn { let { isValid, value: x } = uvRatio(u, v); // √(u/v) if (!isValid) throw new Error('Point.fromHex: invalid y coordinate'); const isXOdd = (x & _1n) === _1n; // There are 2 square roots. Use x_0 bit to select proper - const isLastByteOdd = (lastByte & 0x80) !== 0; // if x=0 and x_0 = 1, fail + const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit + if (!zip215 && x === _0n && isLastByteOdd) + // if x=0 and x_0 = 1, fail + throw new Error('Point.fromHex: x=0 and x_0=1'); if (isLastByteOdd !== isXOdd) x = modP(-x); // if x_0 != x mod 2, set x = p-x return Point.fromAffine({ x, y }); } diff --git a/test/ed25519.test.js b/test/ed25519.test.js index 2096214..d4a07ce 100644 --- a/test/ed25519.test.js +++ b/test/ed25519.test.js @@ -8,6 +8,7 @@ import { ed25519 as ed, ED25519_TORSION_SUBGROUP, numberToBytesLE } from './ed25 import { default as ed25519vectors_OLD } from './ed25519/ed25519_test_OLD.json' assert { type: 'json' }; import { default as ed25519vectors } from './wycheproof/ed25519_test.json' assert { type: 'json' }; import { default as zip215 } from './ed25519/zip215.json' assert { type: 'json' }; +import { default as edgeCases } from './ed25519/edge-cases.json' assert { type: 'json' }; // Any changes to the file will need to be aware of the fact // the file is shared between noble-curves and noble-ed25519. @@ -409,6 +410,18 @@ describe('ed25519', () => { } }); + should('not verify when x=0 and x_0 = 1 (RFC8032)', () => { + const list = [edgeCases[8], edgeCases[10], edgeCases[11]]; + for (let v of list) { + const result = ed.verify(v.signature, v.message, v.pub_key, { zip215: true }); + strictEqual(result, true, `zip215: true must validate: ${v.signature}`); + } + for (let v of list) { + const result = ed.verify(v.signature, v.message, v.pub_key, { zip215: false }); + strictEqual(result, false, `zip215: false must not validate: ${v.signature}`); + } + }); + should('not verify when sig.s >= CURVE.n', () => { const privateKey = ed.utils.randomPrivateKey(); const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]); diff --git a/test/ed25519/edge-cases.json b/test/ed25519/edge-cases.json new file mode 100644 index 0000000..cecf591 --- /dev/null +++ b/test/ed25519/edge-cases.json @@ -0,0 +1 @@ +[{"message":"8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6","pub_key":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa","signature":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a0000000000000000000000000000000000000000000000000000000000000000"},{"message":"9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79","pub_key":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa","signature":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43a5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"},{"message":"aebf3f2601a0c8c5d39cc7d8911642f740b78168218da8471772b35f9d35b9ab","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa8c4bd45aecaca5b24fb97bc10ac27ac8751a7dfe1baff8b953ec9f5833ca260e"},{"message":"9bd9f44f4dcc75bd531b56b2cd280b0bb38fc1cd6d1230e14861d861de092e79","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"9046a64750444938de19f227bb80485e92b83fdb4b6506c160484c016cc1852f87909e14428a7a1d62e9f22f3d3ad7802db02eb2e688b6c52fcd6648a98bd009"},{"message":"e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"160a1cb0dc9c0258cd0a7d23e94d8fa878bcb1925f2c64246b2dee1796bed5125ec6bc982a269b723e0668e540911a9a6a58921d6925e434ab10aa7940551a09"},{"message":"e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec4011eaccd55b53f56c","pub_key":"cdb267ce40c5cd45306fa5d2f29731459387dbf9eb933b7bd5aed9a765b88d4d","signature":"21122a84e0b5fca4052f5b1235c80a537878b38f3142356b2c2384ebad4668b7e40bc836dac0f71076f9abe3a53f9c03c1ceeeddb658d0030494ace586687405"},{"message":"85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40","pub_key":"442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623","signature":"e96f66be976d82e60150baecff9906684aebb1ef181f67a7189ac78ea23b6c0e547f7690a0e2ddcd04d87dbc3490dc19b3b3052f7ff0538cb68afb369ba3a514"},{"message":"85e241a07d148b41e47d62c63f830dc7a6851a0b1f33ae4bb2f507fb6cffec40","pub_key":"442aad9f089ad9e14647b1ef9099a1ff4798d78589e66f28eca69c11f582a623","signature":"8ce5b96c8f26d0ab6c47958c9e68b937104cd36e13c33566acd2fe8d38aa19427e71f98a473474f2f13f06f97c20d58cc3f54b8bd0d272f42b695dd7e89a8c22"},{"message":"9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f"},{"message":"9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41","pub_key":"f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43","signature":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908"},{"message":"e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b","pub_key":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","signature":"a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"},{"message":"39a591f5321bbe07fd5a23dc2f39d025d74526615746727ceefd6e82ae65c06f","pub_key":"ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff","signature":"a9d55260f765261eb9b84e106f665e00b867287a761990d7135963ee0a7d59dca5bb704786be79fc476f91d3f3f89b03984d8068dcf1bb7dfc6637b45450ac04"}]