* The public key is written to the output buffer.
*/
export function derive (): void {
+ // Clear output buffer so errors do not retain stale prior data
+ OUTPUT_BUFFER.fill(0)
+
// Clear local buffers
derive_prv.fill(0)
derive_pub.fill(0)
crypto_derive(derive_pub, derive_prv)
derive_prv.fill(0)
- // Clear output buffer of prior data, then copy local result to output buffer
- OUTPUT_BUFFER.fill(0)
+ // Copy local result to output buffer
memory.copy(changetype<usize>(OUTPUT_BUFFER), changetype<usize>(derive_pub), KEY_BYTELENGTH)
// Clear local result
* @param {i32} mlen Byte length of message to be signed, up to 32768
*/
export function sign (mlen: i32): void {
- if (mlen < 0 || mlen > MESSAGE_BUFFER_BYTELENGTH) {
- PRV_BUFFER.fill(0)
- PUB_BUFFER.fill(0)
- MESSAGE_BUFFER.fill(0)
- throw new Error('invalid message length')
- }
+ // Clear output buffer so errors do not retain stale prior data
+ OUTPUT_BUFFER.fill(0)
// Clear local buffers
sign_prv.fill(0)
sign_pub.fill(0)
sign_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)
+ throw new Error('Invalid message length')
+ }
+
// Copy input buffers to local parameters, then clear input buffer
memory.copy(changetype<usize>(sign_prv), changetype<usize>(PRV_BUFFER), KEY_BYTELENGTH)
PRV_BUFFER.fill(0)
// Sign message from buffer, then clear local input
crypto_sign(sign_sig, MESSAGE_BUFFER, mlen, sign_prv, sign_pub)
- MESSAGE_BUFFER.fill(0)
sign_prv.fill(0)
sign_pub.fill(0)
+ MESSAGE_BUFFER.fill(0)
- // Clear output buffer of prior data, then copy local result to output buffer
- OUTPUT_BUFFER.fill(0)
+ // Copy local result to output buffer
memory.copy(changetype<usize>(OUTPUT_BUFFER), changetype<usize>(sign_sig), SIGNATURE_BYTELENGTH)
// Clear local result
* @returns {boolean} True if message was signed by public key's private key
*/
export function verify (mlen: i32): void {
- if (mlen < 0 || mlen > MESSAGE_BUFFER_BYTELENGTH) {
- PRV_BUFFER.fill(0)
- PUB_BUFFER.fill(0)
- MESSAGE_BUFFER.fill(0)
- throw new Error('invalid message length')
- }
+ // Set all output to false so errors fail closed
+ OUTPUT_BUFFER.fill(255)
// Clear local buffers
verify_pub.fill(0)
verify_sig.fill(0)
+ // Check message length
+ if (mlen < 0 || mlen > MESSAGE_BUFFER_BYTELENGTH) {
+ MESSAGE_BUFFER.fill(0)
+ PUB_BUFFER.fill(0)
+ throw new Error('Invalid message length')
+ }
+
// Copy input buffer to local parameters, then clear input buffer
memory.copy(changetype<usize>(verify_pub), changetype<usize>(PUB_BUFFER), KEY_BYTELENGTH)
PUB_BUFFER.fill(0)
memory.copy(changetype<usize>(verify_sig), changetype<usize>(SIGNATURE_BUFFER), SIGNATURE_BYTELENGTH)
SIGNATURE_BUFFER.fill(0)
- // Verify message from buffer, then clear local input
- const verified = crypto_verify_strict(verify_sig, MESSAGE_BUFFER, mlen, verify_pub)
+ // Verify message from buffer, then write result to output buffer
+ OUTPUT_BUFFER[0] = u8(crypto_verify_strict(verify_sig, MESSAGE_BUFFER, mlen, verify_pub))
+
+ // Clear message buffer and input locals
MESSAGE_BUFFER.fill(0)
verify_pub.fill(0)
verify_sig.fill(0)
-
- // Clear output buffer of prior data, then copy local result to output buffer
- OUTPUT_BUFFER.fill(0)
- OUTPUT_BUFFER[0] = u8(verified)
}
* @param {i32} count Number of signatures to verify, up to 341
*/
export function verify_blocks (count: i32): void {
- if (count < 1 || OUTPUT_BUFFER_BYTELENGTH < count) {
- PRV_BUFFER.fill(0)
- PUB_BUFFER.fill(0)
- MESSAGE_BUFFER.fill(0)
- throw new Error('invalid block count')
- }
+ // Set all output to false so errors fail closed
+ OUTPUT_BUFFER.fill(255)
// Clear local buffers
+ verify_blocks_msg.fill(0)
verify_blocks_pub.fill(0)
+ verify_blocks_sig.fill(0)
+
+ // Check number of blocks is valid
+ if (count < 1 || OUTPUT_BUFFER_BYTELENGTH < count) {
+ MESSAGE_BUFFER.fill(0)
+ PUB_BUFFER.fill(0)
+ throw new Error('Invalid block count')
+ }
// Copy public key input buffer to local parameter, then clear input buffer
memory.copy(changetype<usize>(verify_blocks_pub), changetype<usize>(PUB_BUFFER), KEY_BYTELENGTH)
PUB_BUFFER.fill(0)
- // Set all output to false so errors fail closed
- OUTPUT_BUFFER.fill(255)
-
// Verify public key before proceeding with signature verification
if (crypto_verify_pubkey(verify_blocks_pub) == 0) {
-
+
// Iterate over block hash/signature pairs
- for (let i = 0; i < count; i++) {
+ 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>(verify_blocks_msg), changetype<usize>(MESSAGE_BUFFER) + (96 * i), BLOCKHASH_BYTELENGTH)
- memory.copy(changetype<usize>(verify_blocks_sig), changetype<usize>(MESSAGE_BUFFER) + BLOCKHASH_BYTELENGTH + (96 * i), SIGNATURE_BYTELENGTH)
+ memory.copy(changetype<usize>(verify_blocks_msg), j, BLOCKHASH_BYTELENGTH)
+ memory.copy(changetype<usize>(verify_blocks_sig), j + BLOCKHASH_BYTELENGTH, SIGNATURE_BYTELENGTH)
- // Verify hash and signature
+ // Verify hash and signature, then write result to output buffer
OUTPUT_BUFFER[i] = u8(crypto_verify_relaxed(verify_blocks_sig, verify_blocks_msg, BLOCKHASH_BYTELENGTH, verify_blocks_pub))
- }
+ }
}
- // Clear local input
+ // Clear message buffer and input locals
MESSAGE_BUFFER.fill(0)
+ verify_blocks_msg.fill(0)
verify_blocks_pub.fill(0)
verify_blocks_sig.fill(0)
}