}
}) as Exports
- function derive (k: unknown): string | Uint8Array<ArrayBuffer> {
- const privateKey = normalize('private key', 32, 32, k)
- let buffer: DataView | undefined = new DataView(exports.memory.buffer)
+ function derive (prv: unknown, pub?: 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 sk = new Uint8Array(32)
+ const publicKey = new Uint8Array(pub.buffer)
buffer = new DataView(exports.memory.buffer)
for (let i = 0; i < 32; i++) {
- sk[i] = buffer.getUint8(outPtr + i + 32)
+ publicKey[i] = buffer.getUint8(outPtr + i + 32)
}
clear(buffer)
- return typeof k === 'string'
- ? [...sk].map(b => b.toString(16).padStart(2, '0')).join('')
- : sk
+ if (typeof prv === 'string') {
+ let hex = ''
+ for (const byte of publicKey) {
+ hex += byte.toString(16).padStart(2, '0')
+ }
+ return hex
+ } else {
+ return publicKey
+ }
}
function sign (m: unknown, k: unknown): string | Uint8Array<ArrayBuffer> {
* @returns 32-byte public key
*/
export function derive (k: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>
-export function derive (k: string | Uint8Array<ArrayBuffer>): string | Uint8Array<ArrayBuffer> {
- return nano25519.derive(k)
+/**
+ * Nano public key derivation using WebAssembly. Public key 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>} 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`
+ */
+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)
}
/**
console.log(`${test ? '\x1b[32mPASS' : '\x1b[31mFAIL'}\x1b[0m: ${name}`)
}
+/**
+ *
+ * @param {Uint8Array<ArrayBuffer>} a
+ * @param {Uint8Array<ArrayBuffer>} b
+ */
+function overlaps (a, b) {
+ return a.buffer === b.buffer
+ && a.byteOffset === b.byteOffset
+ && a.byteLength === b.byteLength
+ && a.byteLength !== 0
+}
+
let result, test, passes = 0, failures = 0
// Check string input validation
passes += +test
failures += +!test
+// Check sync imports with byte inputs and preallocated output buffer
+const output = new Uint8Array(32)
+result = derive(NANO_ORG_VECTOR.privateKeyBytes, output)
+test = overlaps(result, output) && [...result].map(b => b.toString(16).padStart(2, '0')).join('').toLowerCase() === NANO_ORG_VECTOR.publicKey.toLowerCase()
+check(`derive from private key string ${NANO_ORG_VECTOR.privateKey}`, test)
+passes += +test
+failures += +!test
+
// test both string inputs and byte inputs
for (const { privateKey, publicKey, message, signature } of PYTHON_ED25519_BLAKE2B_VECTORS) {
result = derive(privateKey)