From: Chris Duncan Date: Thu, 1 Oct 2026 02:11:05 +0000 (-0700) Subject: Merge single-use vartime verify function into caller. Swap vector squaring parameter... X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=bfce66bd3c9a0a249dadbb8d03e239a1dfd13c59;p=nano25519.git Merge single-use vartime verify function into caller. Swap vector squaring parameter order. Copy point doubling algorithm instead of calling to define a fe instead of a p2. Fix identity functions based on new branded point types. --- diff --git a/src/assembly/crypto_verify.ts b/src/assembly/crypto_verify.ts index 6540c5c..9ea8dd6 100644 --- a/src/assembly/crypto_verify.ts +++ b/src/assembly/crypto_verify.ts @@ -3,7 +3,7 @@ import { BLOCKHASH_BYTELENGTH, KEY_BYTELENGTH } from './constants' import { Blake2b } from './ed25519/blake2b' -import { ge_double_scalarmult_vartime_to_p3, ge_frombytes, ge_frombytes_negate_vartime, ge_has_small_order, ge_is_canonical } from './ed25519/ge' +import { ge_double_scalarmult_vartime, ge_frombytes, ge_frombytes_negate_vartime, ge_has_small_order, ge_is_canonical } from './ed25519/ge' import { ge_p3, ge_p3_tobytes, ge_sub_p3 } from './ed25519/p' import { sc_is_canonical, sc_reduce } from './ed25519/sc' import { equalbytes } from './ed25519/utils' @@ -56,7 +56,7 @@ export function crypto_verify_donna (sig: StaticArray, M: StaticArray, A blake2b.init().update(sig, 32).update(pub, KEY_BYTELENGTH).update(M, BLOCKHASH_BYTELENGTH).digest(h) sc_reduce(h) - ge_double_scalarmult_vartime_to_p3(sb_ah, h, A, S) + ge_double_scalarmult_vartime(sb_ah, h, A, S) ge_p3_tobytes(check_r, sb_ah) return equalbytes(sig, check_r, KEY_BYTELENGTH) @@ -88,7 +88,7 @@ export function crypto_verify_sodium (sig: StaticArray, M: StaticArray, blake2b.init().update(sig, 32).update(pub, 32).update(M, mlen).digest(h) sc_reduce(h) - ge_double_scalarmult_vartime_to_p3(sb_ah, h, A, S) + ge_double_scalarmult_vartime(sb_ah, h, A, S) ge_sub_p3(check, expected_r, sb_ah) return ge_has_small_order(check) @@ -121,7 +121,7 @@ export function crypto_verify_strict (sig: StaticArray, M: StaticArray, blake2b.init().update(sig, 32).update(pub, 32).update(M, mlen).digest(h) sc_reduce(h) - ge_double_scalarmult_vartime_to_p3(sb_ah, h, A, S) + ge_double_scalarmult_vartime(sb_ah, h, A, S) ge_sub_p3(check, expected_r, sb_ah) ge_p3_tobytes(check_r, sb_ah) diff --git a/src/assembly/ed25519/fe.ts b/src/assembly/ed25519/fe.ts index 9e071de..a239260 100644 --- a/src/assembly/ed25519/fe.ts +++ b/src/assembly/ed25519/fe.ts @@ -920,7 +920,7 @@ export function fe_sq (h: FieldElement, f: FieldElement): void { * @param hx FieldElement power destination * @param fx FieldElement base source */ -export function fe_sq_vec (hx: FieldElement, fx: FieldElement, hy: FieldElement, fy: FieldElement): void { +export function fe_sq_vec (hx: FieldElement, hy: FieldElement, fx: FieldElement, fy: FieldElement): void { const fx_ptr: usize = changetype(fx) const fy_ptr: usize = changetype(fy) const f0: v128 = i32x4(load(fx_ptr, 0), load(fy_ptr, 0), 0, 0) diff --git a/src/assembly/ed25519/ge.ts b/src/assembly/ed25519/ge.ts index 37e3f67..8ab0702 100644 --- a/src/assembly/ed25519/ge.ts +++ b/src/assembly/ed25519/ge.ts @@ -6,7 +6,7 @@ * * Here the group is the set of pairs (x,y) of field elements satisfying * - * -x² + y² = 1 + d x²y² + * -x² + y² = 1 + dx²y² * * where d = -121665/121666. * @@ -307,6 +307,7 @@ const ge_double_scalarmult_vartime_Ai: StaticArray = StaticArray.from new ge_cached(), new ge_cached() ]) /* A,3A,5A,7A,9A,11A,13A,15A */ +const ge_double_scalarmult_vartime_p: ge_p2 = new ge_p2() const ge_double_scalarmult_vartime_t: ge_p1p1 = new ge_p1p1() const ge_double_scalarmult_vartime_u: ge_p3 = new ge_p3() const ge_double_scalarmult_vartime_A2: ge_p3 = new ge_p3() @@ -318,11 +319,12 @@ const ge_double_scalarmult_vartime_A2: ge_p3 = new ge_p3() * * Only used for signatures verification. */ -function ge_double_scalarmult_vartime (r: ge_p2, a: StaticArray, A: ge_p3, b: StaticArray): void { +export function ge_double_scalarmult_vartime (r: ge_p3, a: StaticArray, A: ge_p3, b: StaticArray): void { const Bi = base2 const aslide = ge_double_scalarmult_vartime_aslide const bslide = ge_double_scalarmult_vartime_bslide const Ai = ge_double_scalarmult_vartime_Ai /* A,3A,5A,7A,9A,11A,13A,15A */ + const p = ge_double_scalarmult_vartime_p const t = ge_double_scalarmult_vartime_t const u = ge_double_scalarmult_vartime_u const A2 = ge_double_scalarmult_vartime_A2 @@ -364,7 +366,7 @@ function ge_double_scalarmult_vartime (r: ge_p2, a: StaticArray, A: ge_p3, b ge_p1p1_to_p3(u, t) ge_p3_to_cached(Ai[7], u) - ge_p2_0(r) + ge_p2_0(p) for (i = 255; i >= 0; --i) { if (aslide[i] || bslide[i]) { @@ -373,7 +375,7 @@ function ge_double_scalarmult_vartime (r: ge_p2, a: StaticArray, A: ge_p3, b } for (; i >= 0; --i) { - ge_p2_dbl(t, r) + ge_p2_dbl(t, p) if (aslide[i] > 0) { ge_p1p1_to_p3(u, t) @@ -391,14 +393,9 @@ function ge_double_scalarmult_vartime (r: ge_p2, a: StaticArray, A: ge_p3, b ge_sub_precomp(t, u, Bi[(-bslide[i]) / 2]) } - ge_p1p1_to_p2(r, t) + ge_p1p1_to_p2(p, t) } -} -const ge_double_scalarmult_vartime_p: ge_p2 = new ge_p2() -export function ge_double_scalarmult_vartime_to_p3 (r: ge_p3, a: StaticArray, A: ge_p3, b: StaticArray): void { - const p = ge_double_scalarmult_vartime_p - ge_double_scalarmult_vartime(p, a, A, b) ge_p2_to_p3(r, p) } diff --git a/src/assembly/ed25519/p.ts b/src/assembly/ed25519/p.ts index 96dfd49..c7c4e6b 100644 --- a/src/assembly/ed25519/p.ts +++ b/src/assembly/ed25519/p.ts @@ -51,18 +51,21 @@ export function ge_p2_0 (h: ge_p2): void { fe_1(h.Z) } -const ge_p2_dbl_t0: FieldElement = fe() +const ge_p2_dbl_t: FieldElement = fe() +/** + * r = 2 * p + */ //@ts-expect-error @inline export function ge_p2_dbl (r: ge_p1p1, p: ge_p2): void { - const t0 = ge_p2_dbl_t0 - fe_sq_vec(r.X, p.X, r.Z, p.Y) + const t = ge_p2_dbl_t + fe_sq_vec(r.X, r.Z, p.X, p.Y) fe_sq2(r.T, p.Z) fe_add(r.Y, p.X, p.Y) - fe_sq(t0, r.Y) + fe_sq(t, r.Y) fe_add(r.Y, r.Z, r.X) fe_sub(r.Z, r.Z, r.X) - fe_sub(r.X, t0, r.Y) + fe_sub(r.X, t, r.Y) fe_sub(r.T, r.T, r.Z) } @@ -101,27 +104,38 @@ export function ge_p1p1_to_p3 (r: ge_p3, p: ge_p1p1): void { //@ts-expect-error @inline export function ge_p1p1_0 (h: ge_p1p1): void { - ge_p2_0(h) + fe_0(h.X) + fe_1(h.Y) + fe_1(h.Z) fe_0(h.T) } //@ts-expect-error @inline export function ge_p3_0 (h: ge_p3): void { - ge_p2_0(h) + fe_0(h.X) + fe_1(h.Y) + fe_1(h.Z) fe_0(h.T) } -const ge_p3_dbl_q: ge_p2 = new ge_p2() +const ge_p3_dbl_t: FieldElement = fe() /** * r = 2 * p + * + * p.T is used as the temporary holder for r.Y² because the parameter is unused + * hereafter at all call sites and it eliminates an extra `t` buffer. */ export function ge_p3_dbl (r: ge_p1p1, p: ge_p3): void { - const q = ge_p3_dbl_q - fe_copy(q.X, p.X) - fe_copy(q.Y, p.Y) - fe_copy(q.Z, p.Z) - ge_p2_dbl(r, q) + const t = ge_p3_dbl_t + fe_sq_vec(r.X, r.Z, p.X, p.Y) + fe_sq2(r.T, p.Z) + fe_add(r.Y, p.X, p.Y) + fe_sq(t, r.Y) + fe_add(r.Y, r.Z, r.X) + fe_sub(r.Z, r.Z, r.X) + fe_sub(r.X, t, r.Y) + fe_sub(r.T, r.T, r.Z) } const ge_p3_tobytes_recip: FieldElement = fe()