]> git.codecow.com Git - nano25519.git/commitdiff
Merge single-use vartime verify function into caller. Swap vector squaring parameter...
authorChris Duncan <chris@codecow.com>
Thu, 1 Oct 2026 02:11:05 +0000 (19:11 -0700)
committerChris Duncan <chris@codecow.com>
Thu, 1 Oct 2026 02:11:05 +0000 (19:11 -0700)
src/assembly/crypto_verify.ts
src/assembly/ed25519/fe.ts
src/assembly/ed25519/ge.ts
src/assembly/ed25519/p.ts

index 6540c5c106156d69e9924ab73208338266a586b7..9ea8dd694218d757fe0779e6c178154587027681 100644 (file)
@@ -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<u8>, M: StaticArray<u8>, 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<u8>, M: StaticArray<u8>,
        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<u8>, M: StaticArray<u8>,
        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)
index 9e071de84e3edbac6f5aa9252a5302fc236630b6..a239260d732cd4ce00e04a3cacb35b9e5e28311f 100644 (file)
@@ -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<usize>(fx)
        const fy_ptr: usize = changetype<usize>(fy)
        const f0: v128 = i32x4(load<i32>(fx_ptr, 0), load<i32>(fy_ptr, 0), 0, 0)
index 37e3f67b0be1f52a5e4caab9585d107dd1b85c98..8ab07025108548ed8aae540c0f4f954d47dde7a0 100644 (file)
@@ -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<ge_cached> = 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<u8>, A: ge_p3, b: StaticArray<u8>): void {
+export function ge_double_scalarmult_vartime (r: ge_p3, a: StaticArray<u8>, A: ge_p3, b: StaticArray<u8>): 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<u8>, 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<u8>, 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<u8>, 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<u8>, A: ge_p3, b: StaticArray<u8>): void {
-       const p = ge_double_scalarmult_vartime_p
-       ge_double_scalarmult_vartime(p, a, A, b)
        ge_p2_to_p3(r, p)
 }
 
index 96dfd49a4f144b148069c0be19a8c6082bdd380c..c7c4e6bf1f67cf70040d4248aabbe8a99e6f108e 100644 (file)
@@ -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()