"sourceMap": false,
"debug": false,
"initialMemory": 4,
- "importMemory": true,
+ "importMemory": false,
+ "noExportMemory": true,
"runtime": "stub",
"exportRuntime": false,
"enable": [
"simd"
],
"disable": [
- "mutable-globals",
- "sign-extension",
- "nontrapping-f2i"
+ "mutable-globals"
],
"noColors": true
}
c |= A[i] ^ pub[i]
}
// Return early if `A` does not match public key
- if (c != 0) return 1
+ if (c != 0) return -1
// Hash private key to `h`
blake2b.init().update(prv, KEY_BYTELENGTH).digest(h)
*/
export function crypto_verify_sodium (sig: StaticArray<u8>, M: StaticArray<u8>, mlen: i32, pub: StaticArray<u8>): i32 {
- // fail if public key `k` is non-canonical (`p = 2²⁵⁵-19 ≤ k`)
- if (!ge_is_canonical(pub)) return 0
-
- // fail if public key cannot be decoded
- if (ge_frombytes_negate_vartime(A, pub) != 0) return 0
-
- // fail if public key `k` is small order
- if (ge_has_small_order(A) != 0) return 0
+ if (!verify_pubkey(pub)) return 0
// fail if private scalar `S` is non-canonical (`L ≤ S`)
memory.copy(changetype<usize>(S), changetype<usize>(sig) + 32, 32)
ge_sub_p3(check, expected_r, sb_ah)
return ge_has_small_order(check)
+}
+
+/**
+ * Verify signature `sig` was made by signing message `M` using public key
+ * `pub`.
+ *
+ * Unlike the other `crypto_verify` methods above, this function is intended for
+ * identity verification and signature deduplication, so malleable signatures
+ * are rejected using a byte-wise comparison.
+ * @returns 0 if signature fails to verify, else return 1 if signature is good
+ */
+export function crypto_verify_strict (sig: StaticArray<u8>, M: StaticArray<u8>, mlen: i32, pub: StaticArray<u8>): i32 {
+
+ if (!verify_pubkey(pub)) return 0
+
+ // fail if scalar `S` is non-canonical (`L ≤ S`)
+ memory.copy(changetype<usize>(S), changetype<usize>(sig) + 32, 32)
+ if (!sc_is_canonical(S)) return 0
+
+ if (ge_frombytes(expected_r, sig) != 0) return 0
+ if (ge_has_small_order(expected_r) != 0) return 0
+
+ // signature is nonce point R and scalar S (R || S)
+ // 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(sig, 32).update(pub, 32).update(M, mlen).digest(h)
+ sc_reduce(h)
+
+ ge_double_scalarmult_vartime_to_p3(sb_ah, h, A, S)
+ ge_sub_p3(check, expected_r, sb_ah)
+
+ ge_p3_tobytes(check_r, sb_ah)
+ return equalbytes(sig, check_r, KEY_BYTELENGTH)
+}
+
+/**
+ * Verify public key `k` is canonical, decodeable, and not small order. Used by
+ * `crypto_verify_sodium` and `crypto_verify_strict`.
+ * @returns 0 if pubkey fails checks, else return 1 if pubkey is good
+ */
+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
+
+ // fail if public key cannot be decoded
+ if (ge_frombytes_negate_vartime(A, pub) != 0) return false
+
+ // fail if public key `k` is small order
+ if (ge_has_small_order(A) != 0) return false
- // ge_p3_tobytes(check_r, sb_ah)
- // return equalbytes(sig, check_r, KEY_BYTELENGTH)
+ return true
}
import { crypto_derive, } from './crypto_derive'
import { crypto_sign, } from './crypto_sign'
import { crypto_verify_decodepubkey, crypto_verify_donna, crypto_verify_sodium, } from './crypto_verify'
-import { errors, } from './errors'
import './tests'
export { BLOCKHASH_BYTELENGTH, KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, MAX_VERIFY_BLOCKS, MAX_VERIFY_BLOCKS_BYTELENGTH, SIGNATURE_BYTELENGTH }
const OUTPUT_SIGN = new StaticArray<u8>(SIGNATURE_BYTELENGTH)
const OUTPUT_VERIFY = new StaticArray<u8>(MAX_VERIFY_BLOCKS)
-/** Returns a pointer to the static message input buffer. */
-export function ptrInputMsg (): usize {
- return changetype<usize>(INPUT_MSG)
+/** Sets a byte in the static message input buffer. */
+export function setInputMsgByte (index: i32, v0: i32): i32 {
+ if (index < 0 || MAX_MESSAGE_BYTELENGTH <= index) {
+ return -1
+ }
+ if (v0 < 0 || 0xff < v0) {
+ return -2
+ }
+ INPUT_MSG[index] = u8(v0)
+ return 0
}
-/** Returns a pointer to the static private key input buffer (32 bytes). */
-export function ptrInputPrv (): usize {
- return changetype<usize>(INPUT_PRV)
+/** Sets a byte in the static private key input buffer (32 bytes). */
+export function setInputPrvByte (index: i32, value: i32): i32 {
+ if (index < 0 || KEY_BYTELENGTH <= index) {
+ return -1
+ }
+ if (value < 0 || 0xff < value) {
+ return -2
+ }
+ INPUT_PRV[index] = u8(value)
+ return 0
}
-/** Returns a pointer to the static public key input buffer (32 bytes). */
-export function ptrInputPub (): usize {
- return changetype<usize>(INPUT_PUB)
+/** Sets a byte in the static public key input buffer (32 bytes). */
+export function setInputPubByte (index: i32, value: i32): i32 {
+ if (index < 0 || KEY_BYTELENGTH <= index) {
+ return -1
+ }
+ if (value < 0 || 0xff < value) {
+ return -2
+ }
+ INPUT_PUB[index] = u8(value)
+ return 0
}
-/** Returns a pointer to the static signature input buffer (64 bytes). */
-export function ptrInputSig (): usize {
- return changetype<usize>(INPUT_SIG)
+/** Sets a byte in the static signature input buffer (64 bytes). */
+export function setInputSigByte (index: i32, value: i32): i32 {
+ if (index < 0 || SIGNATURE_BYTELENGTH <= index) {
+ return -1
+ }
+ if (value < 0 || 0xff < value) {
+ return -2
+ }
+ INPUT_SIG[index] = u8(value)
+ return 0
}
-/** Returns a pointer to the derive() static output buffer (32 bytes). */
-export function ptrOutputDerive (): usize {
- return changetype<usize>(OUTPUT_DERIVE)
+/** Gets a byte from the derive() static output buffer (32 bytes). */
+export function getOutputDeriveByte (index: i32): i32 {
+ if (index < 0 || KEY_BYTELENGTH <= index) {
+ return -1
+ }
+ return OUTPUT_DERIVE[index]
}
-/** Returns a pointer to the sign() static output buffer (64 bytes). */
-export function ptrOutputSign (): usize {
- return changetype<usize>(OUTPUT_SIGN)
+/** Gets a byte from the sign() static output buffer (64 bytes). */
+export function getOutputSignByte (index: i32): i32 {
+ if (index < 0 || SIGNATURE_BYTELENGTH <= index) {
+ return -1
+ }
+ return OUTPUT_SIGN[index]
}
-/** Returns a pointer to the verify() static output buffer (64 bytes). */
-export function ptrOutputVerify (): usize {
- return changetype<usize>(OUTPUT_VERIFY)
+/** Gets a byte from the verify() static output buffer (64 bytes). */
+export function getOutputVerifyByte (index: i32): i32 {
+ if (index < 0 || MAX_VERIFY_BLOCKS <= index) {
+ return -1
+ }
+ return OUTPUT_VERIFY[index]
}
const h = new StaticArray<u8>(BLOCKHASH_BYTELENGTH)
* from the message and written to the output buffer.
* @param {i32} mlen Byte length of message to be signed, up to 65536
*/
-export function sign (mlen: i32): void {
+export function sign (mlen: i32): i32 {
// Clear output buffer so errors do not retain stale prior data
OUTPUT_SIGN.fill(0)
INPUT_PRV.fill(0)
INPUT_PUB.fill(0)
INPUT_MSG.fill(0)
- throw new Error(errors[2])
+ return -2
}
// Copy input buffers to local parameters, then clear input buffer
// Clear signature output buffer if signing failed
if (result != 0) {
OUTPUT_SIGN.fill(0)
- throw new Error(errors[result])
}
+ return result
}
/**
* @param {i32} mlen Byte length of message that was signed, up to 65536
* @returns {boolean} True if message was signed by public key's private key
*/
-export function verify (mlen: i32): void {
+export function verify (mlen: i32): i32 {
// Clear output buffer so errors do not retain stale prior data
OUTPUT_VERIFY.fill(0)
if (mlen < 0 || mlen > MAX_MESSAGE_BYTELENGTH) {
INPUT_MSG.fill(0)
INPUT_PUB.fill(0)
- throw new Error(errors[2])
+ return -2
}
// Copy input buffer to local parameters, then clear input buffer
INPUT_MSG.fill(0)
pub.fill(0)
sig.fill(0)
+ return 0
}
/**
* to the output buffer in the same order they were received.
* @param {i32} count Number of signatures to verify, up to 64
*/
-export function verify_blocks (count: i32): void {
+export function verify_blocks (count: i32): i32 {
// Clear output buffer so errors do not retain stale prior data
OUTPUT_VERIFY.fill(0)
if (count < 1 || MAX_VERIFY_BLOCKS < count) {
INPUT_MSG.fill(0)
INPUT_PUB.fill(0)
- throw new Error(errors[3])
+ return -3
}
// Copy public key input buffer to local parameter, then clear input buffer
h.fill(0)
pub.fill(0)
sig.fill(0)
+ return 0
}
//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { allocate, byteLength, bytesToHex, copy, fill, isBytes, memoryBuffer, normalize, validateMemoryBuffer, view, } from './primordials'
-import { Mutex, Pointers, clearMemory, constants, exports, memory, } from './wasm'
+import { allocate, byteLength, bytesToHex, copy, fill, isBytes, normalize } from './primordials'
+import { MemoryBuffers, Mutex, clearMemory, constants, derive as wasm_derive, } from './wasm'
const { KEY_BYTELENGTH, } = constants
}
const privateKey = normalize('private key', KEY_BYTELENGTH, KEY_BYTELENGTH, prv)
const publicKey = allocate(KEY_BYTELENGTH)
- let buffer = view(memoryBuffer(memory))
Mutex.lock()
try {
for (let i = 0; i < KEY_BYTELENGTH; i++) {
- buffer[Pointers.INPUT_PRV + i] = privateKey[i]
+ MemoryBuffers.INPUT_PRV(i)(privateKey[i])
}
- exports.derive()
- validateMemoryBuffer(memory, buffer)
+ wasm_derive()
for (let i = 0; i < KEY_BYTELENGTH; i++) {
- publicKey[i] = buffer[Pointers.OUTPUT_DERIVE + i]
+ publicKey[i] = MemoryBuffers.OUTPUT_DERIVE(i)
}
if (out != null) {
copy(out, publicKey)
/** Declared here to avoid import loops. */
export class Nano25519TypeError extends TypeError { }
+export class Nano25519WasmError extends Error { }
const isArray = Array.isArray
//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { allocate, byteLength, bytesToHex, copy, fill, isBytes, memoryBuffer, normalize, validateMemoryBuffer, view, } from './primordials'
-import { Mutex, Pointers, clearMemory, constants, exports, memory, } from './wasm'
+import { allocate, byteLength, bytesToHex, copy, fill, isBytes, Nano25519WasmError, normalize } from './primordials'
+import { clearMemory, constants, MemoryBuffers, Mutex, sign as wasm_sign } from './wasm'
const { KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, SIGNATURE_BYTELENGTH, } = constants
const privateKey = normalize('private key', KEY_BYTELENGTH, KEY_BYTELENGTH, prv)
const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub)
const signature = allocate(SIGNATURE_BYTELENGTH)
- let buffer = view(memoryBuffer(memory))
Mutex.lock()
try {
for (let i = 0; i < message.byteLength; i++) {
- buffer[Pointers.INPUT_MSG + i] = message[i]
+ MemoryBuffers.INPUT_MSG(i)(message[i])
}
for (let i = 0; i < KEY_BYTELENGTH; i++) {
- buffer[Pointers.INPUT_PRV + i] = privateKey[i]
+ MemoryBuffers.INPUT_PRV(i)(privateKey[i])
}
for (let i = 0; i < KEY_BYTELENGTH; i++) {
- buffer[Pointers.INPUT_PUB + i] = publicKey[i]
+ MemoryBuffers.INPUT_PUB(i)(publicKey[i])
+ }
+ const result = wasm_sign(message.byteLength)
+ if (result !== 0) {
+ throw new Nano25519WasmError('Invalid public key')
}
- exports.sign(message.byteLength)
- validateMemoryBuffer(memory, buffer)
for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) {
- signature[i] = buffer[Pointers.OUTPUT_SIGN + i]
+ signature[i] = MemoryBuffers.OUTPUT_SIGN(i)
}
if (out != null) {
copy(out, signature)
//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { isArray, memoryBuffer, normalize, validateMemoryBuffer, view } from './primordials'
-import { Mutex, Pointers, clearMemory, constants, exports, memory, } from './wasm'
+import { isArray, normalize } from './primordials'
+import { clearMemory, constants, MemoryBuffers, Mutex, verify as wasm_verify, verify_blocks as wasm_verify_blocks, } from './wasm'
const { BLOCKHASH_BYTELENGTH, KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, MAX_VERIFY_BLOCKS, SIGNATURE_BYTELENGTH, } = constants
export function verify (sig: unknown, msg: unknown, pub: unknown): boolean {
- let buffer = view(memoryBuffer(memory))
Mutex.lock()
try {
const message = normalize('message', 0, MAX_MESSAGE_BYTELENGTH, msg)
const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub)
const signature = normalize('signature', SIGNATURE_BYTELENGTH, SIGNATURE_BYTELENGTH, sig)
for (let i = 0; i < message.byteLength; i++) {
- buffer[Pointers.INPUT_MSG + i] = message[i]
+ MemoryBuffers.INPUT_MSG(i)(message[i])
}
for (let i = 0; i < KEY_BYTELENGTH; i++) {
- buffer[Pointers.INPUT_PUB + i] = publicKey[i]
+ MemoryBuffers.INPUT_PUB(i)(publicKey[i])
}
for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) {
- buffer[Pointers.INPUT_SIG + i] = signature[i]
+ MemoryBuffers.INPUT_SIG(i)(signature[i])
}
- exports.verify(message.byteLength)
- validateMemoryBuffer(memory, buffer)
- const verified = buffer[Pointers.OUTPUT_VERIFY]
+ wasm_verify(message.byteLength)
+ const verified = MemoryBuffers.OUTPUT_VERIFY(0)
return verified === 1
} finally {
clearMemory()
throw new RangeError(`Bulk Nano block verification must be no more than ${MAX_VERIFY_BLOCKS} blocks`, { cause: count })
}
const verified: boolean[] = []
- let buffer = view(memoryBuffer(memory))
Mutex.lock()
try {
const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub)
for (let i = 0; i < KEY_BYTELENGTH; i++) {
- buffer[Pointers.INPUT_PUB + i] = publicKey[i]
+ MemoryBuffers.INPUT_PUB(i)(publicKey[i])
}
- for (let b = 0, p = Pointers.INPUT_MSG; b < count; b++) {
+ for (let b = 0, p = 0; b < count; b++) {
const block = blocks[b]
if (block == null || typeof block !== 'object') {
throw new TypeError('Invalid block', { cause: block })
const signature = normalize('signature', SIGNATURE_BYTELENGTH, SIGNATURE_BYTELENGTH, block.signature)
const hash = normalize('hash', BLOCKHASH_BYTELENGTH, BLOCKHASH_BYTELENGTH, block.hash)
for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) {
- buffer[p + i] = signature[i]
+ MemoryBuffers.INPUT_MSG(p + i)(signature[i])
}
p += SIGNATURE_BYTELENGTH
for (let i = 0; i < BLOCKHASH_BYTELENGTH; i++) {
- buffer[p + i] = hash[i]
+ MemoryBuffers.INPUT_MSG(p + i)(hash[i])
}
p += BLOCKHASH_BYTELENGTH
}
- exports.verify_blocks(count)
- validateMemoryBuffer(memory, buffer)
+ wasm_verify_blocks(count)
for (let i = 0; i < count; i++) {
- verified[i] = buffer[Pointers.OUTPUT_VERIFY + i] === 1
+ verified[i] = MemoryBuffers.OUTPUT_VERIFY(i) === 1
}
return verified
} finally {
//@ts-expect-error
import nano25519_wasm from '../../build/nano25519.wasm'
-import { Nano25519TypeError, copy, fill, memoryBuffer, readLong, utf16, view, } from './primordials'
+import { Nano25519TypeError, copy } from './primordials'
-type Exports = {
- exports: {
- derive: () => void
- sign: (mlen: number) => void
- verify: (mlen: number) => void
- verify_blocks: (count: number) => void
- ptrInputMsg: () => number
- ptrInputPrv: () => number
- ptrInputPub: () => number
- ptrInputSig: () => number
- ptrOutputDerive: () => number
- ptrOutputSign: () => number
- ptrOutputVerify: () => number
- BLOCKHASH_BYTELENGTH: WebAssembly.Global
- KEY_BYTELENGTH: WebAssembly.Global
- SIGNATURE_BYTELENGTH: WebAssembly.Global
- MAX_VERIFY_BLOCKS: WebAssembly.Global
- MAX_VERIFY_BLOCKS_BYTELENGTH: WebAssembly.Global
- MAX_MESSAGE_BYTELENGTH: WebAssembly.Global
- }
+type Exports = WebAssembly.Instance['exports'] & {
+ derive: () => void
+ sign: (mlen: number) => number
+ verify: (mlen: number) => number
+ verify_blocks: (count: number) => number
+ setInputMsgByte: (index: number, value: number) => number
+ setInputPrvByte: (index: number, value: number) => number
+ setInputPubByte: (index: number, value: number) => number
+ setInputSigByte: (index: number, value: number) => number
+ getOutputDeriveByte: (index: number) => number
+ getOutputSignByte: (index: number) => number
+ getOutputVerifyByte: (index: number) => number
+ BLOCKHASH_BYTELENGTH: WebAssembly.Global
+ KEY_BYTELENGTH: WebAssembly.Global
+ SIGNATURE_BYTELENGTH: WebAssembly.Global
+ MAX_VERIFY_BLOCKS: WebAssembly.Global
+ MAX_VERIFY_BLOCKS_BYTELENGTH: WebAssembly.Global
+ MAX_MESSAGE_BYTELENGTH: WebAssembly.Global
}
-export { Nano25519TypeError } from './primordials'
-
let locked = false
export const Mutex = {
lock (): void {
}
}
-/**
- * WASM memory created here and imported, instead of building and exporting, so
- * that top-level WASM abort calls work while `exports` is still instantiating.
- * Host-owned memory means abort handler can always read the error message.
- *
- * NOTE: `initial` must match `initialMemory` in `asconfig.json`.
- */
-export const memory = new WebAssembly.Memory({ initial: 4 })
-
const wasm = copy(nano25519_wasm)
const module = new WebAssembly.Module(wasm)
-export const { exports } = new WebAssembly.Instance(module, {
- env: {
- memory,
- abort: (msg: any, file: any, row: any, col: any): never => {
- const str = (pointer: number): string | null => {
- const end = pointer + readLong(memoryBuffer(memory), pointer - 4) >>> 1
- const start = pointer >>> 1
- return utf16(memoryBuffer(memory), start, end - start)
- }
- // ~lib/builtins/abort(~lib/string/String | null?, ~lib/string/String | null?, u32?, u32?) => void
- msg >>>= 0
- file >>>= 0
- row >>>= 0
- col >>>= 0
- const message = `Nano25519WasmError: ${str(msg)}, ${str(file)}, row ${row}, col ${col}`
- throw new Error(message)
- }
- }
-}) as Exports
+const instance = new WebAssembly.Instance(module, { env: { abort: () => { } } })
+const exports = instance.exports as Exports
const BLOCKHASH_BYTELENGTH = exports.BLOCKHASH_BYTELENGTH.value
const KEY_BYTELENGTH = exports.KEY_BYTELENGTH.value
MAX_MESSAGE_BYTELENGTH
}
-const INPUT_MSG = exports.ptrInputMsg()
-const INPUT_PRV = exports.ptrInputPrv()
-const INPUT_PUB = exports.ptrInputPub()
-const INPUT_SIG = exports.ptrInputSig()
-const OUTPUT_DERIVE = exports.ptrOutputDerive()
-const OUTPUT_SIGN = exports.ptrOutputSign()
-const OUTPUT_VERIFY = exports.ptrOutputVerify()
-
-export class Pointers {
- static #get (ptr: number): number {
- if (locked) return ptr
- throw new Nano25519TypeError('Mutex not acquired')
+export class MemoryBuffers {
+ static #check (): void {
+ if (!locked) throw new Nano25519TypeError('Mutex not acquired')
+ }
+ static get INPUT_MSG () {
+ this.#check()
+ return (i: number) => (v: number) => exports.setInputMsgByte(i, v)
+ }
+ static get INPUT_PRV () {
+ this.#check()
+ return (i: number) => (v: number) => exports.setInputPrvByte(i, v)
+ }
+ static get INPUT_PUB () {
+ this.#check()
+ return (i: number) => (v: number) => exports.setInputPubByte(i, v)
+ }
+ static get INPUT_SIG () {
+ this.#check()
+ return (i: number) => (v: number) => exports.setInputSigByte(i, v)
+ }
+ static get OUTPUT_DERIVE () {
+ this.#check()
+ return (i: number) => exports.getOutputDeriveByte(i)
+ }
+ static get OUTPUT_SIGN () {
+ this.#check()
+ return (i: number) => exports.getOutputSignByte(i)
+ }
+ static get OUTPUT_VERIFY () {
+ this.#check()
+ return (i: number) => exports.getOutputVerifyByte(i)
}
- static get INPUT_MSG (): number { return this.#get(INPUT_MSG) }
- static get INPUT_PRV (): number { return this.#get(INPUT_PRV) }
- static get INPUT_PUB (): number { return this.#get(INPUT_PUB) }
- static get INPUT_SIG (): number { return this.#get(INPUT_SIG) }
- static get OUTPUT_DERIVE (): number { return this.#get(OUTPUT_DERIVE) }
- static get OUTPUT_SIGN (): number { return this.#get(OUTPUT_SIGN) }
- static get OUTPUT_VERIFY (): number { return this.#get(OUTPUT_VERIFY) }
}
export function clearMemory (): void {
- const bytes = view(memoryBuffer(memory))
- fill(bytes, 0, INPUT_MSG, INPUT_MSG + MAX_MESSAGE_BYTELENGTH)
- fill(bytes, 0, INPUT_PRV, INPUT_PRV + KEY_BYTELENGTH)
- fill(bytes, 0, INPUT_PUB, INPUT_PUB + KEY_BYTELENGTH)
- fill(bytes, 0, INPUT_SIG, INPUT_SIG + SIGNATURE_BYTELENGTH)
- fill(bytes, 0, OUTPUT_DERIVE, OUTPUT_DERIVE + KEY_BYTELENGTH)
- fill(bytes, 0, OUTPUT_SIGN, OUTPUT_SIGN + SIGNATURE_BYTELENGTH)
- fill(bytes, 0, OUTPUT_VERIFY, OUTPUT_VERIFY + MAX_VERIFY_BLOCKS)
+ for (let i = 0; i < MAX_MESSAGE_BYTELENGTH; i++) {
+ MemoryBuffers.INPUT_MSG(i)(0)
+ }
+ for (let i = 0; i < KEY_BYTELENGTH; i++) {
+ MemoryBuffers.INPUT_PRV(i)(0)
+ }
+ for (let i = 0; i < KEY_BYTELENGTH; i++) {
+ MemoryBuffers.INPUT_PUB(i)(0)
+ }
+ for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) {
+ MemoryBuffers.INPUT_SIG(i)(0)
+ }
locked = false
}
+
+export const { derive, sign, verify, verify_blocks } = exports
result = false
} catch (err) {
if (err != null && typeof err === 'object' && 'message' in err && typeof err.message === 'string') {
- result = err.message.includes('Nano25519WasmError') && err.message.includes('Invalid public key')
+ result = err.constructor.name === 'Nano25519WasmError' && err.message === 'Invalid public key'
} else {
result = false
}