supercop.ts

cross-compiled javascript implementation of ed25519 based on supercop-ref10
git clone git://git.finwo.net/lib/supercop.ts
Log | Files | Refs | README | LICENSE

commit 4bd9bb679577d66d2565caf15b8c910933d234cd
parent 120fd5eb7285e88dda9093e97c3f6ebaea1b77b7
Author: finwo <finwo@pm.me>
Date:   Sat, 27 May 2023 23:12:20 +0200

Main ts module building

Diffstat:
Mpackage-lock.json | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackage.json | 8+++++---
Msrc/index.ts | 122++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
3 files changed, 299 insertions(+), 44 deletions(-)

diff --git a/package-lock.json b/package-lock.json @@ -18,6 +18,7 @@ "@typescript-eslint/eslint-plugin": "^5.59.7", "@typescript-eslint/parser": "^5.56.0", "eslint": "^8.41.0", + "nodemon": "^2.0.22", "tap": "^16.3.4", "tape": "^5.0.1" }, @@ -894,6 +895,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", @@ -2551,6 +2558,12 @@ "node": ">= 4" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -3377,6 +3390,67 @@ "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", "dev": true }, + "node_modules/nodemon": { + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3697,6 +3771,12 @@ "node": ">=8" } }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -3935,6 +4015,27 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6223,6 +6324,18 @@ "node": ">=8.0" } }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, "node_modules/trivial-deferred": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/trivial-deferred/-/trivial-deferred-1.1.2.tgz", @@ -6326,6 +6439,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "node_modules/unicode-length": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.1.0.tgz", @@ -7274,6 +7393,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", @@ -8448,6 +8573,12 @@ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -9044,6 +9175,50 @@ "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", "dev": true }, + "nodemon": { + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -9283,6 +9458,12 @@ "fromentries": "^1.2.0" } }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -9441,6 +9622,23 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -10967,6 +11165,15 @@ "is-number": "^7.0.0" } }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + } + }, "trivial-deferred": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/trivial-deferred/-/trivial-deferred-1.1.2.tgz", @@ -11042,6 +11249,12 @@ "which-boxed-primitive": "^1.0.2" } }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "unicode-length": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-2.1.0.tgz", diff --git a/package.json b/package.json @@ -27,7 +27,8 @@ "build:esm": "tsc -p ./config/tsconfig.esm.json && mv dist/esm/index.js dist/esm/index.mjs && mv dist/esm/index.js.map dist/esm/index.mjs.map", "build:test": "tsc -p ./config/tsconfig.test.json", "linter": "eslint src", - "postpublishonly": "PACKAGE_VERSION=$(jq -r .version < package.json) && PACKAGE_NAME=$(jq -r .name < package.json) && npm deprecate \"${PACKAGE_NAME}@<${PACKAGE_VERSION}\" \"Rolling release, please update to ${PACKAGE_VERSION}\"" + "postpublishonly": "PACKAGE_VERSION=$(jq -r .version < package.json) && PACKAGE_NAME=$(jq -r .name < package.json) && npm deprecate \"${PACKAGE_NAME}@<${PACKAGE_VERSION}\" \"Rolling release, please update to ${PACKAGE_VERSION}\"", + "watch": "nodemon --watch src --ext ts --exec npm -- run build" }, "repository": { "type": "git", @@ -36,11 +37,12 @@ "author": "Yersa Nordman <finwo@pm.me>", "license": "MIT", "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.59.7", - "@typescript-eslint/parser": "^5.56.0", "@types/node": "^20.2.5", "@types/tap": "^15.0.8", + "@typescript-eslint/eslint-plugin": "^5.59.7", + "@typescript-eslint/parser": "^5.56.0", "eslint": "^8.41.0", + "nodemon": "^2.0.22", "tap": "^16.3.4", "tape": "^5.0.1" }, diff --git a/src/index.ts b/src/index.ts @@ -1,15 +1,7 @@ import isBuffer = require('is-buffer'); import { binary } from './supercop.wasm'; -let Module: null | { - memory : WebAssembly.Memory; - instance: WebAssembly.Instance; - exports : {[index:string]:any}; -} = null; - -async function instantiateModule() { - if (Module) return; - +const Module = (async () => { const memory = new WebAssembly.Memory({initial: 2}); const imports = {env: {memory}}; @@ -19,12 +11,17 @@ async function instantiateModule() { const program = await WebAssembly.instantiate(binary, imports); - Module = { + return { memory : memory, instance: program.instance, exports : program.instance.exports, + } as { + memory : WebAssembly.Memory; + instance: WebAssembly.Instance; + exports : {[index:string]:any}; }; -} +})(); + function randomBytes(length: number) { return Buffer.from(new Array(length).fill(0).map(()=>Math.floor(Math.random()*256))); @@ -64,35 +61,57 @@ export function isSecretKey(data: unknown): data is SecretKey { } export class KeyPair { - publicKey: PublicKey; - secretKey: SecretKey; + publicKey?: PublicKey; + secretKey?: SecretKey; constructor() { // Intentionally empty } + // Passes signing on to the exported stand-alone method + // Async, so the error = promise rejection async sign(message: string) { - // TODO: call main sign fn + if (!isSecretKey(this.secretKey)) throw new Error('No secret key on this keypair, only verification is possible'); + if (!isPublicKey(this.publicKey)) throw new Error('Invalid public key'); + return sign(message, this.publicKey, this.secretKey); + } + + // Passes verification on to the exported stand-alone method + verify(signature: number[] | Signature, message: string) { + if (!isPublicKey(this.publicKey)) throw new Error('Invalid public key'); + return verify(signature, message, this.publicKey); + } + + keyExchange(theirPublicKey: number[] | PublicKey) { + if (!isSecretKey(this.secretKey)) throw new Error('Invalid secret key'); + return keyExchange(theirPublicKey, this.secretKey); } - async verify(signature: Signature, message: string) { - // TODO: call main verify fn + static create(seed: number[] | Seed) { + return createKeyPair(seed); + } + + static from( data: { publicKey: number[] | PublicKey, secretKey?: number[] | SecretKey } ) { + return keyPairFrom(data); } } -export function keyPairFrom( data: { publicKey: PublicKey, secretKey: SecretKey } ): false | KeyPair { +export function keyPairFrom( data: { publicKey: number[] | PublicKey, secretKey?: number[] | SecretKey } ): false | KeyPair { if ('object' !== typeof data) return false; if (!data) return false; + // Sanitization and sanity checking + data = { ...data }; + if (Array.isArray(data.publicKey)) data.publicKey = Buffer.from(data.publicKey); + if (Array.isArray(data.secretKey)) data.secretKey = Buffer.from(data.secretKey); if (!isPublicKey(data.publicKey)) return false; - if (!isSecretKey(data.secretKey)) return false; + // Not checking the secretKey, allowed to be missing return Object.create(KeyPair, data); } -export async function createKeyPair( seed: Seed | Array<number> ): Promise<false | KeyPair> { - await instantiateModule(); +export async function createKeyPair( seed: number[] | Seed ): Promise<false | KeyPair> { // Pre-fetch module components const fn = (await Module).exports; @@ -125,24 +144,24 @@ export async function createKeyPair( seed: Seed | Array<number> ): Promise<false }); } -export async function sign(message: string | Buffer, publicKey: PublicKey, secretKey: SecretKey): Promise<Signature> { - await instantiateModule(); +export async function sign( + message: string | Buffer, + publicKey: number[] | PublicKey, + secretKey: number[] | SecretKey +): Promise<Signature> { // Pre-fetch module components const fn = (await Module).exports; const mem = (await Module).memory; - // Sanity checking + // Sanitization and sanity checking + if (Array.isArray(publicKey)) publicKey = Buffer.from(publicKey); + if (Array.isArray(secretKey)) secretKey = Buffer.from(secretKey); if (!isPublicKey(publicKey)) throw new Error('Invalid public key'); if (!isSecretKey(secretKey)) throw new Error('Invalid secret key'); - - - - if ('string' === typeof message) message = Buffer.from(message); - // checkArguments({message,publicKey,secretKey}); - + // Allocate memory on the wasm side to transfer variables const messageLen = message.length; const messageArrPtr = fn._malloc(messageLen); const messageArr = new Uint8Array(mem.buffer, messageArrPtr, messageLen); @@ -159,6 +178,7 @@ export async function sign(message: string | Buffer, publicKey: PublicKey, secre await fn.sign(sigPtr, messageArrPtr, messageLen, publicKeyArrPtr, secretKeyArrPtr); + // Free used memory on wasm side fn._free(messageArrPtr); fn._free(publicKeyArrPtr); fn._free(secretKeyArrPtr); @@ -167,15 +187,23 @@ export async function sign(message: string | Buffer, publicKey: PublicKey, secre return Buffer.from(sig); } -exports.verify = async function(signature, message, publicKey){ - await instantiateModule(); +export async function verify( + signature: number[] | Signature, + message: string | Buffer, + publicKey: number[] | PublicKey +): Promise<boolean> { + const fn = (await Module).exports; const mem = (await Module).memory; - if ('string' === typeof message) message = Buffer.from(message); + + // Sanitization and sanity checking if (Array.isArray(signature)) signature = Buffer.from(signature); if (Array.isArray(publicKey)) publicKey = Buffer.from(publicKey); - checkArguments({signature,message,publicKey}); + if (!isPublicKey(publicKey)) throw new Error('Invalid public key'); + if (!isSignature(signature)) throw new Error('Invalid signature'); + if ('string' === typeof message) message = Buffer.from(message); + // Allocate memory on the wasm side to transfer variables const messageLen = message.length; const messageArrPtr = fn._malloc(messageLen); const messageArr = new Uint8Array(mem.buffer, messageArrPtr, messageLen); @@ -188,23 +216,31 @@ exports.verify = async function(signature, message, publicKey){ signatureArr.set(signature); publicKeyArr.set(publicKey); - const res = fn.verify(signatureArrPtr, messageArrPtr, messageLen, publicKeyArrPtr) === 1; + const res = fn.verify(signatureArrPtr, messageArrPtr, messageLen, publicKeyArrPtr) === 1; + // Free used memory on wasm side fn._free(messageArrPtr); fn._free(signatureArrPtr); fn._free(publicKeyArrPtr); return res; -}; +} + +export async function keyExchange( + theirPublicKey: number[] | PublicKey, + ourSecretKey: number[] | SecretKey +): Promise<Buffer> { -exports.keyExchange = async function(publicKey, secretKey) { - await instantiateModule(); const fn = (await Module).exports; const mem = (await Module).memory; - if (Array.isArray(publicKey)) publicKey = Buffer.from(publicKey); - if (Array.isArray(secretKey)) secretKey = Buffer.from(secretKey); - checkArguments({publicKey,secretKey}); + // Sanitization and sanity checking + if (Array.isArray(theirPublicKey)) theirPublicKey = Buffer.from(theirPublicKey); + if (Array.isArray(ourSecretKey)) ourSecretKey = Buffer.from(ourSecretKey); + if (!isPublicKey(theirPublicKey)) throw new Error('Invalid public key'); + if (!isSecretKey(ourSecretKey)) throw new Error('Invalid secret key'); + + // Allocate memory on the wasm side to transfer variables const sharedSecretArrPtr = fn._malloc(32); const sharedSecretArr = new Uint8Array(mem.buffer, sharedSecretArrPtr, 32); const publicKeyArrPtr = fn._malloc(32); @@ -212,11 +248,15 @@ exports.keyExchange = async function(publicKey, secretKey) { const secretKeyArrPtr = fn._malloc(32); const secretKeyArr = new Uint8Array(mem.buffer, sharedSecretArrPtr, 64); + publicKeyArr.set(theirPublicKey); + secretKeyArr.set(ourSecretKey); + fn.key_exchange(sharedSecretArrPtr, publicKeyArrPtr, secretKeyArrPtr); + // Free used memory on wasm side fn._free(sharedSecretArrPtr); fn._free(publicKeyArrPtr); fn._free(secretKeyArrPtr); return Buffer.from(sharedSecretArr); -}; +}