export const BLOCKHASH_BYTELENGTH: i32 = 32
export const KEY_BYTELENGTH: i32 = 32
+export const MAX_VERIFY_BLOCKS: i32 = 32
+export const MAX_MESSAGE_BYTELENGTH: i32 = MAX_VERIFY_BLOCKS << 10
export const SIGNATURE_BYTELENGTH: i32 = 64
export const SIGNEDBLOCK_BYTELENGTH: i32 = BLOCKHASH_BYTELENGTH + SIGNATURE_BYTELENGTH
-export const MESSAGE_BUFFER_BYTELENGTH: i32 = BLOCKHASH_BYTELENGTH << 10
-export const PRV_BUFFER_BYTELENGTH: i32 = KEY_BYTELENGTH
-export const PUB_BUFFER_BYTELENGTH: i32 = KEY_BYTELENGTH
-export const OUTPUT_BUFFER_BYTELENGTH: i32 = MESSAGE_BUFFER_BYTELENGTH / SIGNEDBLOCK_BYTELENGTH
-export const SIGNATURE_BUFFER_BYTELENGTH: i32 = SIGNATURE_BYTELENGTH
-
// Static I/O buffers
-const MESSAGE_BUFFER = new StaticArray<u8>(MESSAGE_BUFFER_BYTELENGTH)
-const OUTPUT_BUFFER = new StaticArray<u8>(OUTPUT_BUFFER_BYTELENGTH)
-const PRV_BUFFER = new StaticArray<u8>(PRV_BUFFER_BYTELENGTH)
-const PUB_BUFFER = new StaticArray<u8>(PUB_BUFFER_BYTELENGTH)
-const SIGNATURE_BUFFER = new StaticArray<u8>(SIGNATURE_BUFFER_BYTELENGTH)
+const INPUT_MSG = new StaticArray<u8>(MAX_MESSAGE_BYTELENGTH)
+const INPUT_PRV = new StaticArray<u8>(KEY_BYTELENGTH)
+const INPUT_PUB = new StaticArray<u8>(KEY_BYTELENGTH)
+const INPUT_SIG = new StaticArray<u8>(SIGNATURE_BYTELENGTH)
-/** Returns the pointer to the static message input buffer (32 KiB). */
-export function getMessagePointer (): usize {
- return changetype<usize>(MESSAGE_BUFFER)
-}
+const OUTPUT_DERIVE = new StaticArray<u8>(KEY_BYTELENGTH)
+const OUTPUT_SIGN = new StaticArray<u8>(SIGNATURE_BYTELENGTH)
+const OUTPUT_VERIFY = new StaticArray<u8>(MAX_VERIFY_BLOCKS)
-/** Returns the pointer to the static output buffer (341 bytes). */
-export function getOutputPointer (): usize {
- return changetype<usize>(OUTPUT_BUFFER)
+/** Returns the pointer to the static message input buffer (32 KiB). */
+export function ptrInputMsg (): usize {
+ return changetype<usize>(INPUT_MSG)
}
/** Returns the pointer to the static private key input buffer (32 bytes). */
-export function getPrivateKeyPointer (): usize {
- return changetype<usize>(PRV_BUFFER)
+export function ptrInputPrv (): usize {
+ return changetype<usize>(INPUT_PRV)
}
/** Returns the pointer to the static public key input buffer (32 bytes). */
-export function getPublicKeyPointer (): usize {
- return changetype<usize>(PUB_BUFFER)
+export function ptrInputPub (): usize {
+ return changetype<usize>(INPUT_PUB)
}
/** Returns the pointer to the static signature input buffer (64 bytes). */
-export function getSignaturePointer (): usize {
- return changetype<usize>(SIGNATURE_BUFFER)
+export function ptrInputSig (): usize {
+ return changetype<usize>(INPUT_SIG)
+}
+
+/** Returns the pointer to the derive() static output buffer (64 bytes). */
+export function ptrOutputDerive (): usize {
+ return changetype<usize>(OUTPUT_DERIVE)
+}
+
+/** Returns the pointer to the sign() static output buffer (64 bytes). */
+export function ptrOutputSign (): usize {
+ return changetype<usize>(OUTPUT_SIGN)
+}
+
+/** Returns the pointer to the verify() static output buffer (64 bytes). */
+export function ptrOutputVerify (): usize {
+ return changetype<usize>(OUTPUT_VERIFY)
}
const h = new StaticArray<u8>(BLOCKHASH_BYTELENGTH)
*/
export function derive (): void {
// Clear output buffer so errors do not retain stale prior data
- OUTPUT_BUFFER.fill(0)
+ OUTPUT_DERIVE.fill(0)
// Clear local buffers
prv.fill(0)
pub.fill(0)
// Copy input buffer to local parameterss, then clear input buffer
- memory.copy(changetype<usize>(prv), changetype<usize>(PRV_BUFFER), KEY_BYTELENGTH)
- PRV_BUFFER.fill(0)
+ memory.copy(changetype<usize>(prv), changetype<usize>(INPUT_PRV), KEY_BYTELENGTH)
+ INPUT_PRV.fill(0)
// Derive, then clear local input
crypto_derive(pub, prv)
prv.fill(0)
// Copy local result to output buffer
- memory.copy(changetype<usize>(OUTPUT_BUFFER), changetype<usize>(pub), KEY_BYTELENGTH)
+ memory.copy(changetype<usize>(OUTPUT_DERIVE), changetype<usize>(pub), KEY_BYTELENGTH)
// Clear local result
pub.fill(0)
*/
export function sign (mlen: i32): void {
// Clear output buffer so errors do not retain stale prior data
- OUTPUT_BUFFER.fill(0)
+ OUTPUT_SIGN.fill(0)
// Clear local buffers
prv.fill(0)
sig.fill(0)
// Check message length
- if (mlen < 0 || mlen > MESSAGE_BUFFER_BYTELENGTH) {
- PRV_BUFFER.fill(0)
- PUB_BUFFER.fill(0)
- MESSAGE_BUFFER.fill(0)
+ if (mlen < 0 || mlen > MAX_MESSAGE_BYTELENGTH) {
+ INPUT_PRV.fill(0)
+ INPUT_PUB.fill(0)
+ INPUT_MSG.fill(0)
throw new Error('Invalid message length')
}
// Copy input buffers to local parameters, then clear input buffer
- memory.copy(changetype<usize>(prv), changetype<usize>(PRV_BUFFER), KEY_BYTELENGTH)
- PRV_BUFFER.fill(0)
- memory.copy(changetype<usize>(pub), changetype<usize>(PUB_BUFFER), KEY_BYTELENGTH)
- PUB_BUFFER.fill(0)
+ memory.copy(changetype<usize>(prv), changetype<usize>(INPUT_PRV), KEY_BYTELENGTH)
+ INPUT_PRV.fill(0)
+ memory.copy(changetype<usize>(pub), changetype<usize>(INPUT_PUB), KEY_BYTELENGTH)
+ INPUT_PUB.fill(0)
// Sign message from buffer, then clear local input
- crypto_sign(sig, MESSAGE_BUFFER, mlen, prv, pub)
+ crypto_sign(sig, INPUT_MSG, mlen, prv, pub)
prv.fill(0)
pub.fill(0)
- MESSAGE_BUFFER.fill(0)
+ INPUT_MSG.fill(0)
// Copy local result to output buffer
- memory.copy(changetype<usize>(OUTPUT_BUFFER), changetype<usize>(sig), SIGNATURE_BYTELENGTH)
+ memory.copy(changetype<usize>(OUTPUT_SIGN), changetype<usize>(sig), SIGNATURE_BYTELENGTH)
// Clear local result
sig.fill(0)
*/
export function verify (mlen: i32): void {
// Set all output to false so errors fail closed
- OUTPUT_BUFFER.fill(255)
+ OUTPUT_VERIFY.fill(255)
// Clear local buffers
pub.fill(0)
sig.fill(0)
// Check message length
- if (mlen < 0 || mlen > MESSAGE_BUFFER_BYTELENGTH) {
- MESSAGE_BUFFER.fill(0)
- PUB_BUFFER.fill(0)
+ if (mlen < 0 || mlen > MAX_MESSAGE_BYTELENGTH) {
+ INPUT_MSG.fill(0)
+ INPUT_PUB.fill(0)
throw new Error('Invalid message length')
}
// Copy input buffer to local parameters, then clear input buffer
- memory.copy(changetype<usize>(pub), changetype<usize>(PUB_BUFFER), KEY_BYTELENGTH)
- PUB_BUFFER.fill(0)
- memory.copy(changetype<usize>(sig), changetype<usize>(SIGNATURE_BUFFER), SIGNATURE_BYTELENGTH)
- SIGNATURE_BUFFER.fill(0)
+ memory.copy(changetype<usize>(pub), changetype<usize>(INPUT_PUB), KEY_BYTELENGTH)
+ INPUT_PUB.fill(0)
+ memory.copy(changetype<usize>(sig), changetype<usize>(INPUT_SIG), SIGNATURE_BYTELENGTH)
+ INPUT_SIG.fill(0)
// Verify message from buffer, then write result to output buffer
- OUTPUT_BUFFER[0] = u8(crypto_verify_strict(sig, MESSAGE_BUFFER, mlen, pub))
+ OUTPUT_VERIFY[0] = u8(crypto_verify_strict(sig, INPUT_MSG, mlen, pub))
// Clear message buffer and input locals
- MESSAGE_BUFFER.fill(0)
+ INPUT_MSG.fill(0)
pub.fill(0)
sig.fill(0)
}
* 32-byte public key. Input parameters are read as bytes from separate buffers.
*
* The message buffer holds both the signature and the block hash as a 96-byte
- * concatenated value. The 32 KiB message buffer cannot be divided evenly by 96,
- * so up to 341 block signature/hash pairs are supported with an extra 32 bytes
- * left at the end.
+ * concatenated value. The performance gain of verifying in bulk scales as
+ * `(1-(1/n)) x (k/(k+r))` where `n` is block count, `k` is the time required to
+ * verify the public key, and `r` is the time required to compute all the
+ * remaining verification steps. Testing shows `k` to be ~8.5% the total
+ * verification time, so batching up to 32 block signature/hash pairs reaches
+ * ~96% of that gain; any more blocks would simply add latency returning the
+ * final results.
*
* All pairs are verified against a single public key. The results are written
* to the output buffer in the same order they were received.
- * @param {i32} count Number of signatures to verify, up to 341
+ * @param {i32} count Number of signatures to verify, up to 32
*/
export function verify_blocks (count: i32): void {
// Set all output to false so errors fail closed
- OUTPUT_BUFFER.fill(255)
+ OUTPUT_VERIFY.fill(255)
// Clear local buffers
h.fill(0)
sig.fill(0)
// Check number of blocks is valid
- if (count < 1 || OUTPUT_BUFFER_BYTELENGTH < count) {
- MESSAGE_BUFFER.fill(0)
- PUB_BUFFER.fill(0)
+ if (count < 1 || MAX_VERIFY_BLOCKS < count) {
+ INPUT_MSG.fill(0)
+ INPUT_PUB.fill(0)
throw new Error('Invalid block count')
}
// Copy public key input buffer to local parameter, then clear input buffer
- memory.copy(changetype<usize>(pub), changetype<usize>(PUB_BUFFER), KEY_BYTELENGTH)
- PUB_BUFFER.fill(0)
+ memory.copy(changetype<usize>(pub), changetype<usize>(INPUT_PUB), KEY_BYTELENGTH)
+ INPUT_PUB.fill(0)
// Verify public key before proceeding with signature verification
if (crypto_verify_pubkey(pub) == 0) {
// Iterate over block signature/hash pairs
- for (let i = 0, ptr = changetype<usize>(MESSAGE_BUFFER); i < count; i++, ptr += 96) {
+ for (let i = 0, ptr = changetype<usize>(INPUT_MSG); i < count; i++, ptr += 96) {
// 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_BUFFER[i] = u8(crypto_verify_relaxed(sig, h, pub))
+ OUTPUT_VERIFY[i] = u8(crypto_verify_relaxed(sig, h, pub))
}
}
// Clear message buffer and input locals
- MESSAGE_BUFFER.fill(0)
+ INPUT_MSG.fill(0)
h.fill(0)
pub.fill(0)
sig.fill(0)
/**
* Nano block signature bulk verification using WebAssembly.
* @param {Uint8Array<ArrayBuffer>} publicKey - 32-byte public key
- * @param {object[]} blocks - Array of up to 341 block signature/hash pairs
+ * @param {object[]} blocks - Array of up to 32 block signature/hash pairs
* @param {Uint8Array<ArrayBuffer>} blocks.signature - 64-byte block signature
* @param {Uint8Array<ArrayBuffer>} blocks.hash - 32-byte block hash
* @returns Array of results with, for each case, true if signature matches block hash and public key, else false
/**
* Nano block signature bulk verification using WebAssembly.
* @param {string} publicKey - 64-character hexadecimal public key
- * @param {object[]} blocks - Array of up to 341 block signature/hash pairs
+ * @param {object[]} blocks - Array of up to 32 block signature/hash pairs
* @param {string} blocks.signature - 128-character hexadecimal block signature
* @param {string} blocks.hash - 64-character hexadecimal block hash
* @returns Array of results with, for each case, true if signature matches block hash and public key, else false
//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { clear, exports, isBytes, KEY_LEN, normalize, OUT_PTR, PRV_PTR } from './wasm'
+import { clear, exports, INPUT_PRV, isBytes, KEY_BYTELENGTH, normalize, OUTPUT_DERIVE } from './wasm'
export function derive (prv: unknown, out?: unknown): string | Uint8Array<ArrayBuffer> | void {
- if (typeof out !== 'undefined' && !(isBytes(out) && out.byteLength === KEY_LEN)) {
+ if (typeof out !== 'undefined' && !(isBytes(out) && out.byteLength === KEY_BYTELENGTH)) {
throw new TypeError('Derive output buffer must be 32-byte Uint8Array<ArrayBuffer>')
}
- const privateKey = normalize('private key', KEY_LEN, KEY_LEN, prv)
- const publicKey = new Uint8Array(KEY_LEN)
+ const privateKey = normalize('private key', KEY_BYTELENGTH, KEY_BYTELENGTH, prv)
+ const publicKey = new Uint8Array(KEY_BYTELENGTH)
let buffer = new Uint8Array(exports.memory.buffer)
try {
- for (let i = 0; i < KEY_LEN; i++) {
- buffer[PRV_PTR + i] = privateKey[i]
+ for (let i = 0; i < KEY_BYTELENGTH; i++) {
+ buffer[INPUT_PRV + i] = privateKey[i]
}
exports.derive()
buffer = new Uint8Array(exports.memory.buffer)
- for (let i = 0; i < KEY_LEN; i++) {
- publicKey[i] = buffer[OUT_PTR + i]
+ for (let i = 0; i < KEY_BYTELENGTH; i++) {
+ publicKey[i] = buffer[OUTPUT_DERIVE + i]
}
if (typeof prv === 'string') {
let hex = ''
//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { clear, exports, isBytes, KEY_LEN, MSG_BUF_LEN, MSG_PTR, normalize, OUT_PTR, PRV_PTR, PUB_PTR, SIG_LEN } from './wasm'
+import { clear, exports, INPUT_MSG, INPUT_PRV, INPUT_PUB, isBytes, KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, normalize, OUTPUT_SIGN, SIGNATURE_BYTELENGTH } from './wasm'
export function sign (msg: unknown, prv: unknown, pub: unknown, out?: unknown): string | Uint8Array<ArrayBuffer> | void {
if (typeof out !== 'undefined' && !(isBytes(out) && out.byteLength === 64)) {
throw new TypeError('Sign output buffer must be 64-byte Uint8Array<ArrayBuffer>')
}
- const message = normalize('message', 0, MSG_BUF_LEN, msg)
- const privateKey = normalize('private key', KEY_LEN, KEY_LEN, prv)
- const publicKey = normalize('public key', KEY_LEN, KEY_LEN, pub)
- const signature = new Uint8Array(SIG_LEN)
+ const message = normalize('message', 0, MAX_MESSAGE_BYTELENGTH, msg)
+ const privateKey = normalize('private key', KEY_BYTELENGTH, KEY_BYTELENGTH, prv)
+ const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub)
+ const signature = new Uint8Array(SIGNATURE_BYTELENGTH)
let buffer = new Uint8Array(exports.memory.buffer)
try {
for (let i = 0; i < message.byteLength; i++) {
- buffer[MSG_PTR + i] = message[i]
+ buffer[INPUT_MSG + i] = message[i]
}
- for (let i = 0; i < KEY_LEN; i++) {
- buffer[PRV_PTR + i] = privateKey[i]
+ for (let i = 0; i < KEY_BYTELENGTH; i++) {
+ buffer[INPUT_PRV + i] = privateKey[i]
}
- for (let i = 0; i < KEY_LEN; i++) {
- buffer[PUB_PTR + i] = publicKey[i]
+ for (let i = 0; i < KEY_BYTELENGTH; i++) {
+ buffer[INPUT_PUB + i] = publicKey[i]
}
exports.sign(message.byteLength)
buffer = new Uint8Array(exports.memory.buffer)
- for (let i = 0; i < SIG_LEN; i++) {
- signature[i] = buffer[OUT_PTR + i]
+ for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) {
+ signature[i] = buffer[OUTPUT_SIGN + i]
}
if (typeof prv === 'string') {
let hex = ''
//! SPDX-FileCopyrightText: 2026 Chris Duncan <chris@codecow.com>
//! SPDX-License-Identifier: GPL-3.0-or-later
-import { BLK_LEN, KEY_LEN, MSG_BUF_LEN, MSG_PTR, OUT_BUF_LEN, OUT_PTR, PUB_PTR, SIG_LEN, SIG_PTR, clear, exports, normalize } from './wasm'
+import { BLOCKHASH_BYTELENGTH, INPUT_MSG, INPUT_PUB, INPUT_SIG, KEY_BYTELENGTH, MAX_MESSAGE_BYTELENGTH, MAX_VERIFY_BLOCKS, OUTPUT_VERIFY, SIGNATURE_BYTELENGTH, clear, exports, normalize } from './wasm'
export function verify (sig: unknown, msg: unknown, pub: unknown): boolean {
let buffer = new Uint8Array(exports.memory.buffer)
try {
- const message = normalize('message', 0, MSG_BUF_LEN, msg)
- const publicKey = normalize('public key', KEY_LEN, KEY_LEN, pub)
- const signature = normalize('signature', SIG_LEN, SIG_LEN, sig)
+ 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[MSG_PTR + i] = message[i]
+ buffer[INPUT_MSG + i] = message[i]
}
- for (let i = 0; i < KEY_LEN; i++) {
- buffer[PUB_PTR + i] = publicKey[i]
+ for (let i = 0; i < KEY_BYTELENGTH; i++) {
+ buffer[INPUT_PUB + i] = publicKey[i]
}
- for (let i = 0; i < SIG_LEN; i++) {
- buffer[SIG_PTR + i] = signature[i]
+ for (let i = 0; i < SIGNATURE_BYTELENGTH; i++) {
+ buffer[INPUT_SIG + i] = signature[i]
}
exports.verify(message.byteLength)
buffer = new Uint8Array(exports.memory.buffer)
- const verified = buffer[OUT_PTR]
+ const verified = buffer[OUTPUT_VERIFY]
return verified === 0
} finally {
clear(buffer)
if (count < 1) {
throw new RangeError('Must pass at least one block', { cause: data })
}
- if (OUT_BUF_LEN < count) {
- throw new RangeError(`Bulk Nano block verification must be no more than ${OUT_BUF_LEN} blocks`, { cause: count })
+ if (MAX_VERIFY_BLOCKS < count) {
+ throw new RangeError(`Bulk Nano block verification must be no more than ${MAX_VERIFY_BLOCKS} blocks`, { cause: count })
}
const verified = new Uint8Array(count)
let buffer = new Uint8Array(exports.memory.buffer)
try {
- const publicKey = normalize('public key', KEY_LEN, KEY_LEN, pub)
- for (let i = 0; i < KEY_LEN; i++) {
- buffer[PUB_PTR + i] = publicKey[i]
+ const publicKey = normalize('public key', KEY_BYTELENGTH, KEY_BYTELENGTH, pub)
+ for (let i = 0; i < KEY_BYTELENGTH; i++) {
+ buffer[INPUT_PUB + i] = publicKey[i]
}
- for (let b = 0, p = MSG_PTR; b < count; b++) {
+ for (let b = 0, p = INPUT_MSG; b < count; b++) {
const block = blocks[b]
if (block == null || typeof block !== 'object') {
throw new TypeError('Invalid block', { cause: block })
if (!('hash' in block)) {
throw new TypeError('Block hash is required to verify', { cause: block })
}
- const signature = normalize('signature', SIG_LEN, SIG_LEN, block.signature)
- const hash = normalize('hash', BLK_LEN, BLK_LEN, block.hash)
- for (let i = 0; i < SIG_LEN; i++) {
+ 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]
}
- p += SIG_LEN
- for (let i = 0; i < BLK_LEN; i++) {
+ p += SIGNATURE_BYTELENGTH
+ for (let i = 0; i < BLOCKHASH_BYTELENGTH; i++) {
buffer[p + i] = hash[i]
}
- p += BLK_LEN
+ p += BLOCKHASH_BYTELENGTH
}
exports.verify_blocks(blocks.length)
for (let i = 0; i < count; i++) {
- verified[i] = buffer[OUT_PTR + i]
+ verified[i] = buffer[OUTPUT_VERIFY + i]
}
return [...verified].map(v => v === 0)
} finally {
sign: (mlen: number) => void
verify: (mlen: number) => void
verify_blocks: (count: number) => void
- getMessagePointer: () => number
- getOutputPointer: () => number
- getPrivateKeyPointer: () => number
- getPublicKeyPointer: () => number
- getSignaturePointer: () => number
+ ptrInputMsg: () => number
+ ptrInputPrv: () => number
+ ptrInputPub: () => number
+ ptrInputSig: () => number
+ ptrOutputDerive: () => number
+ ptrOutputSign: () => number
+ ptrOutputVerify: () => number
BLOCKHASH_BYTELENGTH: WebAssembly.Global
KEY_BYTELENGTH: WebAssembly.Global
+ MAX_VERIFY_BLOCKS: WebAssembly.Global
+ MAX_MESSAGE_BYTELENGTH: WebAssembly.Global
SIGNATURE_BYTELENGTH: WebAssembly.Global
- MESSAGE_BUFFER_BYTELENGTH: WebAssembly.Global
- OUTPUT_BUFFER_BYTELENGTH: WebAssembly.Global
- PRV_BUFFER_BYTELENGTH: WebAssembly.Global
- PUB_BUFFER_BYTELENGTH: WebAssembly.Global
- SIGNATURE_BUFFER_BYTELENGTH: WebAssembly.Global
+ SIGNEDBLOCK_BYTELENGTH: WebAssembly.Global
memory: WebAssembly.Memory
}
}
}
}) as Exports
-export const BLK_LEN = exports.BLOCKHASH_BYTELENGTH.value
-export const KEY_LEN = exports.KEY_BYTELENGTH.value
-export const SIG_LEN = exports.SIGNATURE_BYTELENGTH.value
+export const BLOCKHASH_BYTELENGTH = exports.BLOCKHASH_BYTELENGTH.value
+export const KEY_BYTELENGTH = exports.KEY_BYTELENGTH.value
+export const MAX_MESSAGE_BYTELENGTH = exports.MAX_MESSAGE_BYTELENGTH.value
+export const MAX_VERIFY_BLOCKS = exports.MAX_VERIFY_BLOCKS.value
+export const SIGNATURE_BYTELENGTH = exports.SIGNATURE_BYTELENGTH.value
+export const SIGNEDBLOCK_BYTELENGTH = exports.SIGNEDBLOCK_BYTELENGTH.value
-export const MSG_BUF_LEN = exports.MESSAGE_BUFFER_BYTELENGTH.value
-export const OUT_BUF_LEN = exports.OUTPUT_BUFFER_BYTELENGTH.value
-export const PRV_BUF_LEN = exports.PRV_BUFFER_BYTELENGTH.value
-export const PUB_BUF_LEN = exports.PUB_BUFFER_BYTELENGTH.value
-export const SIG_BUF_LEN = exports.SIGNATURE_BUFFER_BYTELENGTH.value
-
-export const MSG_PTR = exports.getMessagePointer()
-export const OUT_PTR = exports.getOutputPointer()
-export const PRV_PTR = exports.getPrivateKeyPointer()
-export const PUB_PTR = exports.getPublicKeyPointer()
-export const SIG_PTR = exports.getSignaturePointer()
+export const INPUT_MSG = exports.ptrInputMsg()
+export const INPUT_PRV = exports.ptrInputPrv()
+export const INPUT_PUB = exports.ptrInputPub()
+export const INPUT_SIG = exports.ptrInputSig()
+export const OUTPUT_DERIVE = exports.ptrOutputDerive()
+export const OUTPUT_SIGN = exports.ptrOutputSign()
+export const OUTPUT_VERIFY = exports.ptrOutputVerify()
export function clear (memory: Uint8Array): void {
- memory.fill(0, MSG_PTR, MSG_PTR + MSG_BUF_LEN)
- memory.fill(0, OUT_PTR, OUT_PTR + OUT_BUF_LEN)
- memory.fill(0, PRV_PTR, PRV_PTR + KEY_LEN)
- memory.fill(0, PUB_PTR, PUB_PTR + KEY_LEN)
- memory.fill(0, SIG_PTR, SIG_PTR + SIG_LEN)
+ memory.fill(0, INPUT_MSG, INPUT_MSG + MAX_MESSAGE_BYTELENGTH)
+ memory.fill(0, INPUT_PRV, INPUT_PRV + KEY_BYTELENGTH)
+ memory.fill(0, INPUT_PUB, INPUT_PUB + KEY_BYTELENGTH)
+ memory.fill(0, INPUT_SIG, INPUT_SIG + SIGNATURE_BYTELENGTH)
+ memory.fill(0, OUTPUT_DERIVE, OUTPUT_DERIVE + KEY_BYTELENGTH)
+ memory.fill(0, OUTPUT_SIGN, OUTPUT_SIGN + SIGNATURE_BYTELENGTH)
+ memory.fill(0, OUTPUT_VERIFY, OUTPUT_VERIFY + MAX_VERIFY_BLOCKS)
}
export function isBytes (a: unknown): a is Uint8Array<ArrayBuffer> {
if (api === 'nano25519 with bulk block verification') {
publicKey = derive(privateKey, 'nano25519')
const blocks = []
- for (let i = 0; i < 341; i++) {
+ for (let i = 0; i < 32; i++) {
blockHash = random()
signature = sign(blockHash, privateKey, publicKey, 'nano25519')
blocks[i] = { hash: blockHash, signature }
if (verified.some(v => v !== true)) {
throw new Error(`invalid result\nsignature: ${signature}\nblock hash: ${blockHash}\npublic key: ${publicKey}`)
}
- duration = (end - start) / 341
+ duration = (end - start) / 32
deriveTimes[i].push(0)
signTimes[i].push(0)
verifyTimes[i].push(duration)
try {
const blocks = []
- for (let i = 0; i < 341; i++) {
+ for (let i = 0; i < 32; i++) {
blocks[i] = { hash: NANO_ORG_VECTOR.blockHashBytes, signature: NANO_ORG_VECTOR.signatureBytes }
}
const verified = verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, blocks)
result = false
}
test = result === true
-check(`verify_blocks 341 max`, test)
+check(`verify_blocks 32 max`, test)
passes += +test
failures += +!test
try {
const blocks = []
- for (let i = 0; i < 342; i++) {
+ for (let i = 0; i < 33; i++) {
blocks[i] = { hash: NANO_ORG_VECTOR.blockHashBytes, signature: NANO_ORG_VECTOR.signatureBytes }
}
verify_blocks(NANO_ORG_VECTOR.publicKeyBytes, blocks)
result = false
} catch (err) {
if (err != null && typeof err === 'object' && 'message' in err) {
- result = err.message === 'Bulk Nano block verification must be no more than 341 blocks'
+ result = err.message === 'Bulk Nano block verification must be no more than 32 blocks'
} else {
result = false
}