}
}) as Exports
- function derive (prv: unknown, pub?: unknown): string | Uint8Array<ArrayBuffer> {
+ function derive (k: unknown, out?: unknown): string | Uint8Array<ArrayBuffer> {
let privateKey = new Uint8Array(32)
let buffer = new DataView(exports.memory.buffer)
- pub ??= new Uint8Array(32)
- if (!(pub instanceof Uint8Array && pub.buffer instanceof ArrayBuffer && pub.byteLength === 32)) {
- throw new TypeError('Output buffer must be 32-byte Uint8Array<ArrayBuffer>')
- }
- privateKey.set(normalize('private key', 32, 32, prv))
- let inPtr = exports.getInputPointer()
- for (let i = 0; i < 32; i++) {
- buffer.setUint8(inPtr + i, privateKey[i])
- }
- privateKey.fill(0)
- exports.derive()
- const outPtr = exports.getOutputPointer()
- const publicKey = new Uint8Array(pub.buffer)
- buffer = new DataView(exports.memory.buffer)
- for (let i = 0; i < 32; i++) {
- publicKey[i] = buffer.getUint8(outPtr + i + 32)
- }
- clear(buffer)
- if (typeof prv === 'string') {
- let hex = ''
- for (const byte of publicKey) {
- hex += byte.toString(16).padStart(2, '0')
+ try {
+ out ??= new Uint8Array(32)
+ if (!(out instanceof Uint8Array && out.buffer instanceof ArrayBuffer && out.byteLength === 32)) {
+ throw new TypeError('Derive output buffer must be 32-byte Uint8Array<ArrayBuffer>')
}
- return hex
- } else {
- return publicKey
+ privateKey.set(normalize('private key', 32, 32, k))
+ let inPtr = exports.getInputPointer()
+ for (let i = 0; i < 32; i++) {
+ buffer.setUint8(inPtr + i, privateKey[i])
+ }
+ privateKey.fill(0)
+ exports.derive()
+ const outPtr = exports.getOutputPointer()
+ const publicKey = new Uint8Array(out.buffer)
+ buffer = new DataView(exports.memory.buffer)
+ for (let i = 0; i < 32; i++) {
+ publicKey[i] = buffer.getUint8(outPtr + i + 32)
+ }
+ clear(buffer)
+ if (typeof k === 'string') {
+ let hex = ''
+ for (const byte of publicKey) {
+ hex += byte.toString(16).padStart(2, '0')
+ }
+ return hex
+ } else {
+ return publicKey
+ }
+ } finally {
+ privateKey.fill(0)
+ clear(buffer)
}
}
- function sign (m: unknown, k: unknown): string | Uint8Array<ArrayBuffer> {
- const message = normalize('message', 0, 32768, m)
- const secretKey = normalize('secret key', 64, 64, k)
+ function sign (m: unknown, k: unknown, s?: unknown): string | Uint8Array<ArrayBuffer> {
+ let secretKey = new Uint8Array(64)
let buffer: DataView | undefined = new DataView(exports.memory.buffer)
+ secretKey.set(normalize('secret key', 64, 64, k))
+ const message = normalize('message', 0, 32768, m)
let mPtr = exports.getMessagePointer()
let inPtr = exports.getInputPointer()
for (let i = 0; i < message.byteLength; i++) {
}
exports.sign(message.byteLength)
const outPtr = exports.getOutputPointer()
- const s = new Uint8Array(64)
+ s ??= new Uint8Array(64)
+ if (!(s instanceof Uint8Array && s.buffer instanceof ArrayBuffer && s.byteLength === 64)) {
+ throw new TypeError('Sign output buffer must be 64-byte Uint8Array<ArrayBuffer>')
+ }
+ const signature = new Uint8Array(s.buffer)
buffer = new DataView(exports.memory.buffer)
for (let i = 0; i < 64; i++) {
- s[i] = buffer.getUint8(outPtr + i)
+ signature[i] = buffer.getUint8(outPtr + i)
}
clear(buffer)
return typeof k === 'string'
- ? [...s].map(b => b.toString(16).padStart(2, '0')).join('')
- : s
+ ? [...signature].map(b => b.toString(16).padStart(2, '0')).join('')
+ : signature
}
function verify (s: unknown, m: unknown, k: unknown): boolean {
* Technically, the buffer is also returned for API consistency, but the
* location in memory is the same as the output buffer, so the return value can
* be ignored.
- * @param {Uint8Array<ArrayBuffer>} input - 32-byte private key
- * @param {Uint8Array<ArrayBuffer>} output - buffer to receive 32-byte public key
- * @returns the same buffer allocated in memory to `output`
+ * @param {Uint8Array<ArrayBuffer>} prv - 32-byte private key
+ * @param {Uint8Array<ArrayBuffer>} pub - buffer to receive 32-byte public key
+ * @returns the same buffer allocated in memory to `pub`
*/
-export function derive (input: Uint8Array<ArrayBuffer>, output: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>
-export function derive (prv: string | Uint8Array<ArrayBuffer>, pub?: Uint8Array<ArrayBuffer>): string | Uint8Array<ArrayBuffer> {
- return nano25519.derive(prv, pub)
+export function derive (k: Uint8Array<ArrayBuffer>, out: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>
+export function derive (k: string | Uint8Array<ArrayBuffer>, out?: Uint8Array<ArrayBuffer>): string | Uint8Array<ArrayBuffer> {
+ return nano25519.derive(k, out)
}
/**
* @returns 64-byte detached signature
*/
export function sign (m: Uint8Array<ArrayBuffer>, k: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>
-export function sign (m: string | Uint8Array<ArrayBuffer>, k: string | Uint8Array<ArrayBuffer>): string | Uint8Array<ArrayBuffer> {
- return nano25519.sign(m, k)
+/**
+ * Signing using WebAssembly. To sign Nano blocks, the message should be a
+ * 32-byte block hash. Signature bytes are written to the user-supplied output
+ * buffer instead of being allocated internally. Technically, the buffer is also
+ * returned for API consistency, but the location in memory is the same as the
+ * output buffer, so the return value can be ignored.
+ * @param {Uint8Array<ArrayBuffer>} m - Variable-byte-length message up to 32 KiB
+ * @param {Uint8Array<ArrayBuffer>} k - 64-byte secret key (prv + pub)
+ * @param {Uint8Array<ArrayBuffer>} out - buffer to receive 64-byte detached signature
+ * @returns the same buffer allocated in memory to `s`
+ */
+export function sign (m: Uint8Array<ArrayBuffer>, k: Uint8Array<ArrayBuffer>, out: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>
+export function sign (m: string | Uint8Array<ArrayBuffer>, k: string | Uint8Array<ArrayBuffer>, out?: Uint8Array<ArrayBuffer>): string | Uint8Array<ArrayBuffer> {
+ return nano25519.sign(m, k, out)
}
/**