import { BLOCKHASH_BYTELENGTH, KEY_BYTELENGTH } from '.'
import { Blake2b } from './blake2b'
-import { fe_0 } from './fe'
import { ge_double_scalarmult_vartime_to_p3, ge_frombytes, ge_frombytes_negate_vartime, ge_has_small_order, ge_is_canonical } from './ge'
import { ge_p3, ge_p3_tobytes, ge_sub_p3 } from './p'
import { sc_is_canonical, sc_reduce } from './sc'
/**
* Verify public key `pub` can be decoded.
- * @returns -1 if public key fails to decode, else return 0
+ * @returns 0 if public key fails to decode, else return pointer to A
*/
-export function crypto_verify_decodepubkey (pub: StaticArray<u8>): i32 {
- fe_0(A.X)
- fe_0(A.Y)
- fe_0(A.Z)
- fe_0(A.T)
+export function crypto_verify_decodepubkey (pub: StaticArray<u8>): usize {
// fail if public key cannot be decoded
- return ge_frombytes_negate_vartime(A, pub)
+ if (ge_frombytes_negate_vartime(A, pub) != 0) return 0
+ return changetype<usize>(A)
}
/**
* set `A` for the scalar multiplication step before checking `sB = R + hA`.
* @returns -1 if signature fails to verify, else return 0 if signature is good
*/
-export function crypto_verify_relaxed (s: StaticArray<u8>, M: StaticArray<u8>, pub: StaticArray<u8>): i32 {
+export function crypto_verify_relaxed (s: StaticArray<u8>, M: StaticArray<u8>, A: usize, pub: StaticArray<u8>): i32 {
// fail if private scalar `S` is out of range (`2²⁵³ ≤ S`)
if ((s[63] & 224) != 0) return -1
blake2b.init().update(s, 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_to_p3(sb_ah, h, changetype<ge_p3>(A), S)
ge_p3_tobytes(check_r, sb_ah)
return equalbytes(s, check_r, 32) - 1
if (!ge_is_canonical(pub)) return -1
// fail if public key cannot be decoded
- if (crypto_verify_decodepubkey(pub) != 0) return -1
+ if (ge_frombytes_negate_vartime(A, pub) != 0) return -1
// fail if public key `k` is small order
if (ge_has_small_order(A) != 0) return -1
INPUT_PUB.fill(0)
// Verify public key before proceeding with signature verification
- if (crypto_verify_decodepubkey(pub) == 0) {
-
+ const A = crypto_verify_decodepubkey(pub)
+ if (A != 0) {
// Iterate over block signature/hash pairs
- for (let i = 0, ptr = changetype<usize>(INPUT_MSG); i < count; i++, ptr += 96) {
+ for (let i = 0, ptr = changetype<usize>(INPUT_MSG); i < count; i++, ptr += SIGNEDBLOCK_BYTELENGTH) {
// Copy block signature/hash from message buffer to locals
memory.copy(changetype<usize>(sig), ptr, SIGNATURE_BYTELENGTH)
memory.copy(changetype<usize>(h), ptr + SIGNATURE_BYTELENGTH, BLOCKHASH_BYTELENGTH)
// Verify hash and signature, then write result to output buffer
- OUTPUT_VERIFY[i] = u8(crypto_verify_relaxed(sig, h, pub))
+ OUTPUT_VERIFY[i] = u8(crypto_verify_relaxed(sig, h, A, pub))
}
}