function crypto_derive (pk: StaticArray<u8>, seed: StaticArray<u8>): void {
const a = crypto_derive_a
const az = crypto_derive_az
- blake2b.init().update(changetype<usize>(seed), 32).digest(az)
+ blake2b.init().update(seed, 32).digest(az)
memory.copy(changetype<usize>(a), changetype<usize>(az), 32)
az.fill(0)
clamp(a)
a.fill(0)
}
+const crypto_sign_a = new StaticArray<u8>(32)
+const crypto_sign_z = new StaticArray<u8>(32)
const crypto_sign_az = new StaticArray<u8>(64)
const crypto_sign_nonce = new StaticArray<u8>(64)
const crypto_sign_hram = new StaticArray<u8>(64)
const crypto_sign_t = new StaticArray<u8>(PRIVATEKEY_BYTES)
function crypto_sign (s: StaticArray<u8>, m: usize, mlen: i32, sk: StaticArray<u8>): void {
+ const a = crypto_sign_a
+ const z = crypto_sign_z
const az = crypto_sign_az
const nonce = crypto_sign_nonce
const hram = crypto_sign_hram
// Hash secret key to private scalar `a` and prefix for nonce derivation `z`
memory.copy(t, changetype<usize>(sk), PRIVATEKEY_BYTES)
blake2b.init().update(t, PRIVATEKEY_BYTES).digest(az)
- clamp(az)
+ memory.copy(changetype<usize>(a), changetype<usize>(az), 32)
+ memory.copy(changetype<usize>(a), changetype<usize>(az) + 32, 32)
+ clamp(a)
// Derive nonce from prefix `z` and message `m`
- blake2b.init().update(changetype<usize>(az) + 32, 32).update(m, mlen).digest(nonce)
+ blake2b.init().update(z, 32).update(changetype<StaticArray<u8>>(m), mlen).digest(nonce)
sc_reduce(nonce)
// Compute R = rB, output to bytes s
// Concatenate public key `A` and message `M` from parameter arguments:
// `A = sk[32,63], M = m`
// Compute challenge hash using `s = (R || A || M)`
- blake2b.init().update(changetype<usize>(s), 32).update(changetype<usize>(sk) + 32, 32).update(m, mlen).digest(hram)
+ blake2b.init().update(s, 32).update(sk + 32, 32).update(m, mlen).digest(hram)
sc_reduce(hram)
// Compute `S = (r + h*a) mod L` and construct final signature `s = (R || S)`
- sc_muladd(changetype<StaticArray<u8>>(changetype<usize>(s) + 32), changetype<StaticArray<u8>>(az), hram, nonce)
+ sc_muladd(changetype<StaticArray<u8>>(changetype<usize>(s) + 32), az, hram, nonce)
// Clean up sensitive data
+ a.fill(0)
+ z.fill(0)
az.fill(0)
hram.fill(0)
nonce.fill(0)
// data to hash is nonce point R, public key A, and message M
// from parameter arguments: R = s[0,32], A = pk, M = m
// R, S, A, and M are all 32-byte values in this implementation
- blake2b.init().update(changetype<usize>(s), 32).update(changetype<usize>(pk), 32).update(m, mlen).digest(h)
+ blake2b.init().update(s, 32).update(pk, 32).update(m, mlen).digest(h)
sc_reduce(h)
ge_double_scalarmult_vartime_to_p3(sb_ah, h, A, S)