}
}
-export const nano25519_init = (bytes: number[]): { derive: typeof derive, sign: typeof sign, verify: typeof verify } => {
- const wasm: Uint8Array<ArrayBuffer> = Uint8Array.from(bytes)
- const module = new WebAssembly.Module(wasm)
- const { exports } = new WebAssembly.Instance(module, {
- env: {
- abort: (msg: any, file: any, row: any, col: any) => {
- const getString = (pointer: number): string | null => {
- const end = pointer + new Uint32Array(exports.memory.buffer)[pointer - 4 >>> 2] >>> 1
- const buf = new Uint16Array(exports.memory.buffer)
- let start = pointer >>> 1
- let string = ''
- while (end - start > 1024) {
- string += String.fromCharCode(...buf.subarray(start, start += 1024))
- }
- return string + String.fromCharCode(...buf.subarray(start, end))
- }
- // ~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: ${getString(msg)}, ${getString(file)}, row ${row}, col ${col}`
- throw new Error(message)
- },
- "performance.now" () {
- // ~lib/bindings/dom/performance.now() => f64
- return performance.now()
- },
- // ~lib/builtins/trace(~lib/string/String, i32?, f64?, f64?, f64?, f64?, f64?) => void
- trace: (message: any, n?: number, a0?: number, a1?: number, a2?: number, a3?: number, a4?: number): void => {
+const wasm: Uint8Array<ArrayBuffer> = Uint8Array.from(nano25519_wasm)
+const module = new WebAssembly.Module(wasm)
+const { exports } = new WebAssembly.Instance(module, {
+ env: {
+ abort: (msg: any, file: any, row: any, col: any) => {
+ const getString = (pointer: number): string | null => {
+ const end = pointer + new Uint32Array(exports.memory.buffer)[pointer - 4 >>> 2] >>> 1
+ const buf = new Uint16Array(exports.memory.buffer)
+ let start = pointer >>> 1
let string = ''
- const pointer: number = message >>> 0
- if (pointer) {
- const end = pointer + new Uint32Array(exports.memory.buffer)[pointer - 4 >>> 2] >>> 1
- const memU16 = new Uint16Array(exports.memory.buffer)
- let start = pointer >>> 1
- while (end - start > 1024) {
- string += String.fromCharCode(...memU16.subarray(start, start += 1024))
- }
- message = string + String.fromCharCode(...memU16.subarray(start, end))
+ while (end - start > 1024) {
+ string += String.fromCharCode(...buf.subarray(start, start += 1024))
}
- (() => {
- // @external.js
- console.log(message, ...[a0, a1, a2, a3, a4].slice(0, n))
- })()
- },
- memory: new WebAssembly.Memory({ initial: 1, maximum: 1 })
- }
- }) as Exports
-
- function derive (k: unknown, out?: unknown): string | Uint8Array<ArrayBuffer> | void {
- if (typeof out !== 'undefined' && !(isBytes(out) && out.byteLength === 32)) {
- throw new TypeError('Derive output buffer must be 32-byte Uint8Array<ArrayBuffer>')
- }
- const privateKey = new Uint8Array(32)
- const publicKey = new Uint8Array(32)
- let buffer = new Uint8Array(exports.memory.buffer)
- try {
- privateKey.set(normalize('private key', 32, 32, k))
- let inPtr = exports.getInputPointer()
- for (let i = 0; i < 32; i++) {
- buffer[inPtr + i] = privateKey[i]
- }
- exports.derive()
- const outPtr = exports.getOutputPointer()
- buffer = new Uint8Array(exports.memory.buffer)
- for (let i = 0; i < 32; i++) {
- publicKey[i] = buffer[outPtr + i]
+ return string + String.fromCharCode(...buf.subarray(start, end))
}
- if (typeof k === 'string') {
- let hex = ''
- for (const byte of publicKey) {
- hex += byte.toString(16).padStart(2, '0')
+ // ~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: ${getString(msg)}, ${getString(file)}, row ${row}, col ${col}`
+ throw new Error(message)
+ },
+ "performance.now" () {
+ // ~lib/bindings/dom/performance.now() => f64
+ return performance.now()
+ },
+ // ~lib/builtins/trace(~lib/string/String, i32?, f64?, f64?, f64?, f64?, f64?) => void
+ trace: (message: any, n?: number, a0?: number, a1?: number, a2?: number, a3?: number, a4?: number): void => {
+ let string = ''
+ const pointer: number = message >>> 0
+ if (pointer) {
+ const end = pointer + new Uint32Array(exports.memory.buffer)[pointer - 4 >>> 2] >>> 1
+ const memU16 = new Uint16Array(exports.memory.buffer)
+ let start = pointer >>> 1
+ while (end - start > 1024) {
+ string += String.fromCharCode(...memU16.subarray(start, start += 1024))
}
- return hex
- } else if (isBytes(k) && out != null) {
- out.set(publicKey)
- publicKey.fill(0)
- return
- } else {
- return publicKey
+ message = string + String.fromCharCode(...memU16.subarray(start, end))
}
- } finally {
- clear(buffer)
- privateKey.fill(0)
- }
+ (() => {
+ // @external.js
+ console.log(message, ...[a0, a1, a2, a3, a4].slice(0, n))
+ })()
+ },
+ memory: new WebAssembly.Memory({ initial: 1, maximum: 1 })
}
+}) as Exports
- function sign (m: unknown, k: unknown, s?: unknown): string | Uint8Array<ArrayBuffer> | void {
- if (typeof s !== 'undefined' && !(isBytes(s) && s.byteLength === 64)) {
- throw new TypeError('Sign output buffer must be 64-byte Uint8Array<ArrayBuffer>')
+export function derive (k: unknown, out?: unknown): string | Uint8Array<ArrayBuffer> | void {
+ if (typeof out !== 'undefined' && !(isBytes(out) && out.byteLength === 32)) {
+ throw new TypeError('Derive output buffer must be 32-byte Uint8Array<ArrayBuffer>')
+ }
+ const privateKey = new Uint8Array(32)
+ const publicKey = new Uint8Array(32)
+ let buffer = new Uint8Array(exports.memory.buffer)
+ try {
+ privateKey.set(normalize('private key', 32, 32, k))
+ let inPtr = exports.getInputPointer()
+ for (let i = 0; i < 32; i++) {
+ buffer[inPtr + i] = privateKey[i]
}
- const secretKey = new Uint8Array(64)
- const signature = new Uint8Array(64)
- let buffer = new Uint8Array(exports.memory.buffer)
- try {
- secretKey.set(normalize('secret key', 64, 64, k))
- let inPtr = exports.getInputPointer()
- for (let i = 0; i < 64; i++) {
- buffer[inPtr + i] = secretKey[i]
- }
- const message = normalize('message', 0, 32768, m)
- let mPtr = exports.getMessagePointer()
- for (let i = 0; i < message.byteLength; i++) {
- buffer[mPtr + i] = message[i]
- }
- exports.sign(message.byteLength)
- const outPtr = exports.getOutputPointer()
- buffer = new Uint8Array(exports.memory.buffer)
- for (let i = 0; i < 64; i++) {
- signature[i] = buffer[outPtr + i]
- }
- if (typeof k === 'string') {
- let hex = ''
- for (const byte of signature) {
- hex += byte.toString(16).padStart(2, '0')
- }
- return hex
- } else if (isBytes(k) && s != null) {
- s.set(signature)
- signature.fill(0)
- return
- } else {
- return signature
- }
- } finally {
- clear(buffer)
- secretKey.fill(0)
+ exports.derive()
+ const outPtr = exports.getOutputPointer()
+ buffer = new Uint8Array(exports.memory.buffer)
+ for (let i = 0; i < 32; i++) {
+ publicKey[i] = buffer[outPtr + i]
}
- }
-
- function verify (s: unknown, m: unknown, k: unknown): boolean {
- let buffer = new Uint8Array(exports.memory.buffer)
- try {
- const signature = normalize('signature', 64, 64, s)
- const message = normalize('message', 0, 32768, m)
- const publicKey = normalize('public key', 32, 32, k)
- let mPtr = exports.getMessagePointer()
- let inPtr = exports.getInputPointer()
- for (let i = 0; i < message.byteLength; i++) {
- buffer[mPtr + i] = message[i]
- }
- for (let i = 0; i < 64; i++) {
- buffer[inPtr + i] = signature[i]
- }
- inPtr += 64
- for (let i = 0; i < 32; i++) {
- buffer[inPtr + i] = publicKey[i]
+ if (typeof k === 'string') {
+ let hex = ''
+ for (const byte of publicKey) {
+ hex += byte.toString(16).padStart(2, '0')
}
- const v = exports.verify(message.byteLength)
- return v === 0
- } finally {
- clear(buffer)
+ return hex
+ } else if (isBytes(k) && out != null) {
+ out.set(publicKey)
+ publicKey.fill(0)
+ return
+ } else {
+ return publicKey
}
+ } finally {
+ clear(buffer)
+ privateKey.fill(0)
}
+}
- function clear (buffer: Uint8Array): void {
- let inPtr = exports.getInputPointer()
- let outPtr = exports.getOutputPointer()
- buffer.fill(0, inPtr, inPtr + 96)
- buffer.fill(0, outPtr, outPtr + 64)
- }
-
- function isBytes (a: unknown): a is Uint8Array<ArrayBuffer> {
- return a instanceof Uint8Array && a.buffer instanceof ArrayBuffer
+export function sign (m: unknown, k: unknown, s?: unknown): string | Uint8Array<ArrayBuffer> | void {
+ if (typeof s !== 'undefined' && !(isBytes(s) && s.byteLength === 64)) {
+ throw new TypeError('Sign output buffer must be 64-byte Uint8Array<ArrayBuffer>')
}
-
- function normalize (name: string, byteLengthMin: number, byteLengthMax: number, value: unknown): Uint8Array<ArrayBuffer> {
- if (typeof name !== 'string') {
- throw new TypeError(`Invalid name ${name}`)
+ const secretKey = new Uint8Array(64)
+ const signature = new Uint8Array(64)
+ let buffer = new Uint8Array(exports.memory.buffer)
+ try {
+ secretKey.set(normalize('secret key', 64, 64, k))
+ let inPtr = exports.getInputPointer()
+ for (let i = 0; i < 64; i++) {
+ buffer[inPtr + i] = secretKey[i]
}
- if (typeof byteLengthMin !== 'number') {
- throw new TypeError(`Invalid minimum byte length for ${name}`)
+ const message = normalize('message', 0, 32768, m)
+ let mPtr = exports.getMessagePointer()
+ for (let i = 0; i < message.byteLength; i++) {
+ buffer[mPtr + i] = message[i]
}
- if (typeof byteLengthMax !== 'number') {
- throw new TypeError(`Invalid maximum byte length for ${name}`)
+ exports.sign(message.byteLength)
+ const outPtr = exports.getOutputPointer()
+ buffer = new Uint8Array(exports.memory.buffer)
+ for (let i = 0; i < 64; i++) {
+ signature[i] = buffer[outPtr + i]
}
- if (typeof value === 'string') {
- if (/[^0-9a-f]/i.test(value)) {
- throw new TypeError(`Invalid hexadecimal characters in ${name}`)
- }
- if (value.length & 1 || value.length < (byteLengthMin << 1) || value.length > (byteLengthMax << 1)) {
- throw new TypeError(`Invalid hexadecimal length ${value.length} for ${name}`)
+ if (typeof k === 'string') {
+ let hex = ''
+ for (const byte of signature) {
+ hex += byte.toString(16).padStart(2, '0')
}
- value = new Uint8Array(value.match(/[0-9a-f]{2}/gi)?.map(b => parseInt(b, 16)) || [])
+ return hex
+ } else if (isBytes(k) && s != null) {
+ s.set(signature)
+ signature.fill(0)
+ return
+ } else {
+ return signature
}
- if (value instanceof ArrayBuffer) {
- value = new Uint8Array(value)
+ } finally {
+ clear(buffer)
+ secretKey.fill(0)
+ }
+}
+
+export function verify (s: unknown, m: unknown, k: unknown): boolean {
+ let buffer = new Uint8Array(exports.memory.buffer)
+ try {
+ const signature = normalize('signature', 64, 64, s)
+ const message = normalize('message', 0, 32768, m)
+ const publicKey = normalize('public key', 32, 32, k)
+ let mPtr = exports.getMessagePointer()
+ let inPtr = exports.getInputPointer()
+ for (let i = 0; i < message.byteLength; i++) {
+ buffer[mPtr + i] = message[i]
}
- if (!(value instanceof Uint8Array)) {
- throw new TypeError(`${name} must be Uint8Array`)
+ for (let i = 0; i < 64; i++) {
+ buffer[inPtr + i] = signature[i]
}
- if (!('buffer' in value && value.buffer instanceof ArrayBuffer)) {
- throw new TypeError(`${name} must be backed by an ArrayBuffer`)
+ inPtr += 64
+ for (let i = 0; i < 32; i++) {
+ buffer[inPtr + i] = publicKey[i]
}
- if (value.byteLength < byteLengthMin) {
- throw new TypeError(`${name} must be at least ${byteLengthMin} bytes`)
+ const v = exports.verify(message.byteLength)
+ return v === 0
+ } finally {
+ clear(buffer)
+ }
+}
+
+function clear (buffer: Uint8Array): void {
+ let inPtr = exports.getInputPointer()
+ let outPtr = exports.getOutputPointer()
+ buffer.fill(0, inPtr, inPtr + 96)
+ buffer.fill(0, outPtr, outPtr + 64)
+}
+
+function isBytes (a: unknown): a is Uint8Array<ArrayBuffer> {
+ return a instanceof Uint8Array && a.buffer instanceof ArrayBuffer
+}
+
+function normalize (name: string, byteLengthMin: number, byteLengthMax: number, value: unknown): Uint8Array<ArrayBuffer> {
+ if (typeof name !== 'string') {
+ throw new TypeError(`Invalid name ${name}`)
+ }
+ if (typeof byteLengthMin !== 'number') {
+ throw new TypeError(`Invalid minimum byte length for ${name}`)
+ }
+ if (typeof byteLengthMax !== 'number') {
+ throw new TypeError(`Invalid maximum byte length for ${name}`)
+ }
+ if (typeof value === 'string') {
+ if (/[^0-9a-f]/i.test(value)) {
+ throw new TypeError(`Invalid hexadecimal characters in ${name}`)
}
- if (value.byteLength > byteLengthMax) {
- throw new TypeError(`${name} must be no more than ${byteLengthMax} bytes`)
+ if (value.length & 1 || value.length < (byteLengthMin << 1) || value.length > (byteLengthMax << 1)) {
+ throw new TypeError(`Invalid hexadecimal length ${value.length} for ${name}`)
}
- return value as Uint8Array<ArrayBuffer>
+ value = new Uint8Array(value.match(/[0-9a-f]{2}/gi)?.map(b => parseInt(b, 16)) || [])
+ }
+ if (value instanceof ArrayBuffer) {
+ value = new Uint8Array(value)
}
- return { derive, sign, verify }
+ if (!(value instanceof Uint8Array)) {
+ throw new TypeError(`${name} must be Uint8Array`)
+ }
+ if (!('buffer' in value && value.buffer instanceof ArrayBuffer)) {
+ throw new TypeError(`${name} must be backed by an ArrayBuffer`)
+ }
+ if (value.byteLength < byteLengthMin) {
+ throw new TypeError(`${name} must be at least ${byteLengthMin} bytes`)
+ }
+ if (value.byteLength > byteLengthMax) {
+ throw new TypeError(`${name} must be no more than ${byteLengthMax} bytes`)
+ }
+ return value as Uint8Array<ArrayBuffer>
}
-
-export const nano25519 = nano25519_init(nano25519_wasm)