import { BLOCKHASH_BYTELENGTH, KEY_BYTELENGTH } from './constants'
import { Blake2b } from './ed25519/blake2b'
+import { fe } from './ed25519/fe'
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_p3, ge_p3_tobytes, ge_sub_p3 } from './ed25519/p'
+import { ge_cached, ge_p1p1, 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'
const sb_ah = new ge_p3()
const check = new ge_p3()
const check_r = new StaticArray<u8>(32)
+const fe_scratch = fe()
+const ge_cached_scratch = new ge_cached()
+const ge_p1p1_scratch = new ge_p1p1()
/**
* Verify public key `pub` can be decoded.
sc_reduce(h)
ge_double_scalarmult_vartime_to_p3(sb_ah, h, A, S)
- ge_sub_p3(check, expected_r, sb_ah)
+ ge_sub_p3(check, expected_r, sb_ah, fe_scratch, ge_cached_scratch, ge_p1p1_scratch)
return ge_has_small_order(check)
}
sc_reduce(h)
ge_double_scalarmult_vartime_to_p3(sb_ah, h, A, S)
- ge_sub_p3(check, expected_r, sb_ah)
+ ge_sub_p3(check, expected_r, sb_ah, fe_scratch, ge_cached_scratch, ge_p1p1_scratch)
ge_p3_tobytes(check_r, sb_ah)
return equalbytes(sig, check_r, KEY_BYTELENGTH)
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()
+const ge_double_scalarmult_vartime_fe_scratch: FieldElement = fe()
/**
* r = a * A + b * B
* where a = a[0]+256*a[1]+...+256^31 a[31].
const t = ge_double_scalarmult_vartime_t
const u = ge_double_scalarmult_vartime_u
const A2 = ge_double_scalarmult_vartime_A2
+ const fe_scratch = ge_double_scalarmult_vartime_fe_scratch
let i: i32 = 0
slide_vartime(aslide, a)
ge_p3_dbl(t, A)
ge_p1p1_to_p3(A2, t)
- ge_add_cached(t, A2, Ai[0])
+ ge_add_cached(t, A2, Ai[0], fe_scratch)
ge_p1p1_to_p3(u, t)
ge_p3_to_cached(Ai[1], u)
- ge_add_cached(t, A2, Ai[1])
+ ge_add_cached(t, A2, Ai[1], fe_scratch)
ge_p1p1_to_p3(u, t)
ge_p3_to_cached(Ai[2], u)
- ge_add_cached(t, A2, Ai[2])
+ ge_add_cached(t, A2, Ai[2], fe_scratch)
ge_p1p1_to_p3(u, t)
ge_p3_to_cached(Ai[3], u)
- ge_add_cached(t, A2, Ai[3])
+ ge_add_cached(t, A2, Ai[3], fe_scratch)
ge_p1p1_to_p3(u, t)
ge_p3_to_cached(Ai[4], u)
- ge_add_cached(t, A2, Ai[4])
+ ge_add_cached(t, A2, Ai[4], fe_scratch)
ge_p1p1_to_p3(u, t)
ge_p3_to_cached(Ai[5], u)
- ge_add_cached(t, A2, Ai[5])
+ ge_add_cached(t, A2, Ai[5], fe_scratch)
ge_p1p1_to_p3(u, t)
ge_p3_to_cached(Ai[6], u)
- ge_add_cached(t, A2, Ai[6])
+ ge_add_cached(t, A2, Ai[6], fe_scratch)
ge_p1p1_to_p3(u, t)
ge_p3_to_cached(Ai[7], u)
if (aslide[i] > 0) {
ge_p1p1_to_p3(u, t)
- ge_add_cached(t, u, Ai[aslide[i] / 2])
+ ge_add_cached(t, u, Ai[aslide[i] / 2], fe_scratch)
} else if (aslide[i] < 0) {
ge_p1p1_to_p3(u, t)
ge_sub_cached(t, u, Ai[(-aslide[i]) / 2])
fe_sub(r.T, r.T, r.Z)
}
-const ge_add_cached_t0: FieldElement = fe()
/**
* r = p + q
*/
-export function ge_add_cached (r: ge_p1p1, p: ge_p3, q: ge_cached): void {
- const t0 = ge_add_cached_t0
+export function ge_add_cached (r: ge_p1p1, p: ge_p3, q: ge_cached, fe_scratch: FieldElement): void {
+ const t0 = fe_scratch
fe_add(r.X, p.Y, p.X)
fe_sub(r.Y, p.Y, p.X)
fe_mul(r.Z, r.X, q.YplusX)
fe_sub(r.T, p.Z, r.T)
}
-const ge_sub_p3_q_cached = new ge_cached()
-const ge_sub_p3_p1p1 = new ge_p1p1()
/* r = p-q */
-export function ge_sub_p3 (r: ge_p3, p: ge_p3, q: ge_p3): void {
- const q_cached = ge_sub_p3_q_cached
- const p1p1 = ge_sub_p3_p1p1
-
+export function ge_sub_p3 (r: ge_p3, p: ge_p3, q: ge_p3, fe_scratch: FieldElement, ge_cached_scratch: ge_cached, ge_p1p1_scratch: ge_p1p1): void {
fe_neg(r.X, q.X)
fe_copy(r.Y, q.Y)
fe_copy(r.Z, q.Z)
fe_neg(r.T, q.T)
- ge_p3_to_cached(q_cached, r)
- ge_add_cached(p1p1, p, q_cached)
- ge_p1p1_to_p3(r, p1p1)
+ ge_p3_to_cached(ge_cached_scratch, r)
+ ge_add_cached(ge_p1p1_scratch, p, ge_cached_scratch, fe_scratch)
+ ge_p1p1_to_p3(r, ge_p1p1_scratch)
}
/**