edwards: ensure Point.fromHex fails when x=0 and first x bit is 1. gh-40
This commit is contained in:
parent
9bee88888f
commit
6621053c7d
@ -75,8 +75,13 @@ export interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
|
|||||||
export type CurveFn = {
|
export type CurveFn = {
|
||||||
CURVE: ReturnType<typeof validateOpts>;
|
CURVE: ReturnType<typeof validateOpts>;
|
||||||
getPublicKey: (privateKey: Hex) => Uint8Array;
|
getPublicKey: (privateKey: Hex) => Uint8Array;
|
||||||
sign: (message: Hex, privateKey: Hex) => Uint8Array;
|
sign: (message: Hex, privateKey: Hex, options?: { context?: Hex }) => Uint8Array;
|
||||||
verify: (sig: Hex, message: Hex, publicKey: Hex) => boolean;
|
verify: (
|
||||||
|
sig: Hex,
|
||||||
|
message: Hex,
|
||||||
|
publicKey: Hex,
|
||||||
|
options?: { context?: Hex; zip215: boolean }
|
||||||
|
) => boolean;
|
||||||
ExtendedPoint: ExtPointConstructor;
|
ExtendedPoint: ExtPointConstructor;
|
||||||
utils: {
|
utils: {
|
||||||
randomPrivateKey: () => Uint8Array;
|
randomPrivateKey: () => Uint8Array;
|
||||||
@ -379,7 +384,10 @@ export function twistedEdwards(curveDef: CurveType): CurveFn {
|
|||||||
let { isValid, value: x } = uvRatio(u, v); // √(u/v)
|
let { isValid, value: x } = uvRatio(u, v); // √(u/v)
|
||||||
if (!isValid) throw new Error('Point.fromHex: invalid y coordinate');
|
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 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
|
if (isLastByteOdd !== isXOdd) x = modP(-x); // if x_0 != x mod 2, set x = p-x
|
||||||
return Point.fromAffine({ x, y });
|
return Point.fromAffine({ x, y });
|
||||||
}
|
}
|
||||||
|
@ -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_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 ed25519vectors } from './wycheproof/ed25519_test.json' assert { type: 'json' };
|
||||||
import { default as zip215 } from './ed25519/zip215.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
|
// Any changes to the file will need to be aware of the fact
|
||||||
// the file is shared between noble-curves and noble-ed25519.
|
// 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', () => {
|
should('not verify when sig.s >= CURVE.n', () => {
|
||||||
const privateKey = ed.utils.randomPrivateKey();
|
const privateKey = ed.utils.randomPrivateKey();
|
||||||
const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]);
|
const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]);
|
||||||
|
1
test/ed25519/edge-cases.json
Normal file
1
test/ed25519/edge-cases.json
Normal file
@ -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"}]
|
Loading…
Reference in New Issue
Block a user