Browse Source

adding WASM scrypt WebWorker from pow-captcha

v2
forest 9 months ago
parent
commit
1c627e9244
7 changed files with 563 additions and 1 deletions
  1. +5
    -1
      .gitignore
  2. +347
    -0
      static/scryptWebWorker.js
  3. +66
    -0
      static/scryptWebWorkerStub.js
  4. +13
    -0
      wasm_build/package-lock.json
  5. +14
    -0
      wasm_build/package.json
  6. +54
    -0
      wasm_build/wasm_build.sh
  7. +64
    -0
      wasm_build/wasm_build_webworker.js

+ 5
- 1
.gitignore View File

@ -1,4 +1,8 @@
.env
node_modules
data
sequentialread-password-manager
test-server.key
test-server.pem
test-server.pem
wasm_build/node_modules
wasm_build/scrypt-wasm

+ 347
- 0
static/scryptWebWorker.js
File diff suppressed because it is too large
View File


+ 66
- 0
static/scryptWebWorkerStub.js View File

@ -0,0 +1,66 @@
// IN ORDER FOR CHANGES TO THIS FILE TO "TAKE" AND BE USED IN THE APP, THE BUILD IN wasm_build HAS TO BE RE-RUN
// scrypt and scryptPromise will be filled out by js code that gets appended below this script by the wasm_build process
let scrypt;
let scryptPromise;
onmessage = function(e) {
const errors = [];
if(!e.data.data) {
errors.push("the 'data' field is required.")
}
if(!e.data.data.toLowerCase().match(/^[a-f0-9]*$/)) {
errors.push("the 'data' field must be hexadecimal.")
}
if(!e.data.salt) {
errors.push("the 'salt' field is required.")
}
if(!e.data.salt.toLowerCase().match(/^[a-f0-9]*$/)) {
errors.push("the 'salt' field must be hexadecimal.")
}
if(e.data.cpuAndMemoryCost === null || e.data.cpuAndMemoryCost === undefined) {
errors.push("the 'cpuAndMemoryCost' field is required.")
} else if(typeof e.data.cpuAndMemoryCost != "number") {
errors.push("the 'cpuAndMemoryCost' field must be a number.")
}
if(e.data.blockSize === null || e.data.blockSize === undefined) {
errors.push("the 'blockSize' field is required.")
} else if(typeof e.data.blockSize != "number") {
errors.push("the 'blockSize' field must be a number.")
}
if(e.data.keyLength === null || e.data.keyLength === undefined) {
errors.push("the 'keyLength' field is required.")
} else if(typeof e.data.keyLength != "number") {
errors.push("the 'keyLength' field must be a number.")
}
if(errors.length != 0) {
postMessage({ data: e.data.data, errors: errors });
return;
}
const doTheThing = () => {
postMessage({
data: e.data.data,
result: scrypt(
e.data.data.toLowerCase(),
e.data.salt.toLowerCase(),
e.data.cpuAndMemoryCost,
e.data.blockSize,
1,
e.data.keyLength
)
});
}
if(scrypt) {
doTheThing()
} else {
scryptPromise.then(() => {
doTheThing();
});
}
}

+ 13
- 0
wasm_build/package-lock.json View File

@ -0,0 +1,13 @@
{
"name": "wasm_build",
"version": "0.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"base32768": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/base32768/-/base32768-2.0.1.tgz",
"integrity": "sha512-DfpYn6XUE8YSsooJ4rj61EiTKkPJM1exxxbJB0byWvRc39ogWDZtrOSY0PVvGQe+DI1FZt10ES7xBifxmirqwQ=="
}
}
}

+ 14
- 0
wasm_build/package.json View File

@ -0,0 +1,14 @@
{
"name": "wasm_build",
"version": "0.0.0",
"description": "build wasm module into webworker",
"main": "build_wasm_webworker.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "GPL-3.0-or-later",
"dependencies": {
"base32768": "^2.0.1"
}
}

+ 54
- 0
wasm_build/wasm_build.sh View File

@ -0,0 +1,54 @@
#!/bin/bash -e
if [ ! -f wasm_build.sh ]; then
printf "Please run this script from the wasm_build folder.\n"
fi
if [ ! -d scrypt-wasm ]; then
printf "Cloning https://github.com/MyEtherWallet/scrypt-wasm... \n"
git clone https://github.com/MyEtherWallet/scrypt-wasm
fi
cd scrypt-wasm
rust_is_installed="$(which rustc | wc -l)"
if [ "$rust_is_installed" == "0" ]; then
printf "rust language compilers & tools will need to be installed."
printf "using rustup.rs: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh \n"
read -p "is this ok? [y] " -n 1 -r
printf "\n"
if [[ $REPLY =~ ^[Yy]$ ]]
then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
else
printf "exiting due to no rust compiler"
exit 1
fi
fi
if [ ! -d pkg ]; then
printf "running Makefile for MyEtherWallet/scrypt-wasm... \n"
make
fi
cd ../
nodejs_is_installed="$(which node | wc -l)"
npm_is_installed="$(which npm | wc -l)"
if [ "$nodejs_is_installed" == "0" ] || [ "$npm_is_installed" == "0" ]; then
printf "nodejs and npm are required for the next step. Please install them manually 😇"
exit 1
fi
if [ ! -d node_modules ]; then
printf "running npm install \n"
npm install
fi
node wasm_build_webworker.js > "../static/scryptWebWorker.js"
printf "\n\nbuilt ../static/scryptWebWorker.js successfully!\n\n"

+ 64
- 0
wasm_build/wasm_build_webworker.js View File

@ -0,0 +1,64 @@
const base32768 = require('base32768');
const fs = require('fs');
const base32768WASM = base32768.encode(fs.readFileSync("scrypt-wasm/pkg/scrypt_wasm_bg.wasm"));
const wasmWrappperJS = fs.readFileSync("scrypt-wasm/pkg/scrypt_wasm_bg.js", { encoding: "utf8" });
let lines = wasmWrappperJS.split("\n");
// filter out the first line "import * as wasm from './scrypt_wasm_bg.wasm';"
// because we are using global namespace, not es6 modules
lines = lines.filter(line => !line.includes("scrypt_wasm_bg.wasm"))
// replace export with global namespace for the same reason.
lines = lines.map(line => {
if(line.startsWith("export function scrypt")) {
return line.replace("export function scrypt", "scrypt = function");
}
return line;
});
const customWASMWrappperJS = lines.join("\n");
// --------------------------------------------------------------------------
// Output the composited webworker JS
// first, include the warning about this file being automatically generated
console.log(`
// THIS FILE IS GENERATED AUTOMATICALLY
// Don't edit this file by hand.
// Either edit scryptWebWorkerStub.js or edit the build located in the wasm_build folder.
`)
// add the actual webworker logic at the top, while filtering out comments
const stubJS = fs.readFileSync("../static/scryptWebWorkerStub.js", { encoding: "utf8" });
console.log(stubJS.split("\n").filter(x => !x.startsWith("//")).join("\n"));
console.log(`
// Everything below this line is created by the build scripts in the wasm_build folder.
`)
// Now its time to load the wasm module.
// first, load the base32768 module into a global variable called "base32768"
console.log(fs.readFileSync("node_modules/base32768/dist/iife/base32768.js", { encoding: "utf8" }))
// now, decode the base32768 string into an ArrayBuffer and tell WebAssembly to load it
console.log(`
const base32768WASM = "${base32768WASM}";
const wasmBinary = base32768.decode(base32768WASM);
scryptPromise = WebAssembly.instantiate(wasmBinary, {}).then(instantiatedModule => {
const wasm = instantiatedModule.instance.exports;
`);
// Output the WASM wrapper JS code that came from the Rust WASM compiler,
// slightly modified to use global namespace instead of es6 modules
console.log(customWASMWrappperJS.split("\n").map(x => ` ${x}`).join("\n"));
// finish off by closing scryptPromise
console.log("});");

Loading…
Cancel
Save