//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
+import { BLOCKHASH_BYTELENGTH, KEY_BYTELENGTH } from '.'
import { Blake2b } from './blake2b'
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_sub_p3 } from './p'
const blake2b = new Blake2b()
// algorithm variables
-const h = new StaticArray<u8>(64)
-const check = new ge_p3()
-const expected_r = new ge_p3()
const A = new ge_p3()
-const sb_ah = new ge_p3()
const S = new StaticArray<u8>(32)
+const expected_r = new ge_p3()
+const h = new StaticArray<u8>(64)
+const sb_ah = new ge_p3()
+const check = new ge_p3()
/**
* Verify public key `pub` is canonical, non-malleable, and correct.
}
/**
- * Verify signature `s` was made by signing message `M` using public key `pub`.
+ * Verify signature `s` was made by signing block hash `M` using public key
+ * `pub`.
*
* IMPORTANT: Callers MUST call `crypto_verify_pubkey` first in order to 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>, mlen: i32, pub: StaticArray<u8>): i32 {
+export function crypto_verify_relaxed (s: StaticArray<u8>, M: StaticArray<u8>, pub: StaticArray<u8>): i32 {
// fail if private scalar `S` is non-canonical (`L ≤ S`)
memory.copy(changetype<usize>(S), changetype<usize>(s) + 32, 32)
// 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(s, 32).update(pub, 32).update(M, mlen).digest(h)
+ 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)
* @returns -1 if signature fails to verify, else return 0 if signature is good
*/
export function crypto_verify_strict (s: StaticArray<u8>, M: StaticArray<u8>, mlen: i32, pub: StaticArray<u8>): i32 {
+ // Check public key is valid
if (crypto_verify_pubkey(pub) != 0) return -1
// fail if private scalar `S` is non-canonical (`L ≤ S`)
if (crypto_verify_pubkey(pub) == 0) {
// Iterate over block hash/signature pairs
- for (let i = 0, j = changetype<usize>(MESSAGE_BUFFER); i < count; i++, j += 96) {
- // Copy message buffer to local block hash/signature buffers
- memory.copy(changetype<usize>(h), j, BLOCKHASH_BYTELENGTH)
- memory.copy(changetype<usize>(sig), j + BLOCKHASH_BYTELENGTH, SIGNATURE_BYTELENGTH)
+ for (let i = 0, ptr = changetype<usize>(MESSAGE_BUFFER); i < count; i++, ptr += 96) {
+ // Copy block hash/signature from message buffer to locals
+ memory.copy(changetype<usize>(h), ptr, BLOCKHASH_BYTELENGTH)
+ memory.copy(changetype<usize>(sig), ptr + BLOCKHASH_BYTELENGTH, SIGNATURE_BYTELENGTH)
// Verify hash and signature, then write result to output buffer
- OUTPUT_BUFFER[i] = u8(crypto_verify_relaxed(sig, h, BLOCKHASH_BYTELENGTH, pub))
+ OUTPUT_BUFFER[i] = u8(crypto_verify_relaxed(sig, h, pub))
}
}