function verify_pubkey (pub: StaticArray<u8>): boolean {
// fail if public key `k` is non-canonical (`p = 2²⁵⁵-19 ≤ k`)
- if (!ge_is_canonical(pub)) return false
+ if (ge_is_canonical(pub) != 0) return false
// fail if public key cannot be decoded
if (ge_frombytes_negate_vartime(A, pub) != 0) return false
}
/**
- * Verify signature `s` is canonical, decodeable, and not small order. Used by
+ * Verify signature `sig` is canonical, decodeable, and not small order. Used by
* `crypto_verify_sodium` and `crypto_verify_strict`.
* @returns 0 if signature fails checks, else return 1 if signature is good
*/
memory.copy(changetype<usize>(S), changetype<usize>(sig) + 32, 32)
if (!sc_is_canonical(S)) return false
- // fail if nonce `R` is not a valid point on the curve
+ // fail if nonce `R` is non-canonical (`p ≤ R`)
+ if (ge_is_canonical(sig) != 0) return false
+
+ // fail if nonce `R` does not decode to a valid curve point
if (ge_frombytes(expected_r, sig) != 0) return false
+
+ // fail if nonce `R` is small order
if (ge_has_small_order(expected_r) != 0) return false
return true
}
/**
- * true if `s < p`
+ * @returns 0 if `s < p`, else -1
*/
-export function ge_is_canonical (s: StaticArray<u8>): u8 {
+export function ge_is_canonical (s: StaticArray<u8>): i32 {
let c: i32 = (s[31] & 0x7f) ^ 0x7f
for (let i = 30; i > 0; i--) {
- c |= s[i] ^ 0xff
+ c |= s[i]
}
c = (c - 1) >> 8
const d: i32 = (0xec - s[0]) >> 8
- return u8(1 - (c & d & 1))
+ return 0 - (c & d & 1)
}
const ge_scalarmult_base_tobytes_h: ge_p3 = new ge_p3()