|
|
2 weeks ago | |
|---|---|---|
| src | 2 weeks ago | |
| webworker | 2 weeks ago | |
| .gitignore | 3 weeks ago | |
| Cargo.toml | 2 weeks ago | |
| README.md | 2 weeks ago | |
| build.sh | 2 weeks ago | |
| demo.html | 2 weeks ago | |
README.md
scrypt-x25519-wasm
Originally forked from https://github.com/MyEtherWallet/scrypt-wasm (last commit: 2018)
This is a minimal (less than 100kb, 30kb gzipped) webassembly blob which provides cryptography functions neccesary for:
- passphrase-based key derivation
Scryptmemory-hard hash function
- asymetric-key cryptography (public and private key)
- X25519 Scalar Multiplication (ability to obtain public key from private key)
- NaCl-compatible
crypto_box(X25519 Diffie-Hellman key agreement, with a good Authenticated Encryption (AEAD) cypher on top)
dev-dependencies
IDK if you have to run this? You might.
rustup target add wasm32-unknown-unknown
Build WebWorker
./build.sh
Then the output of this build should be in the webworker folder.
This build script converts the wasm-bindgen output, which was designed to be an ECMAScript module, into a WebWorker. It needs to be a WebWorker because for large values of cpuAndMemoryCost for the scrypt hash function, it would cause the JavaScript vm to hang (thus blocking the UI thread in the browser), which is no good. We want to be able to display a loading animaton while the computer is performing the key derivation from the users seed.
Test
After building, python3 -m http.server -b 127.0.0.1 8080
Then navigate to http://localhost:8080/demo.html
Usage
Host the files inside the webworker folder at ./static/ on your web server:
/static/scryptWebWorker.js
/static/scrypt.wasm
Load the webworker and set up access to it on your HTML page like this:
<script>
function randomBytesBase64(byteCount) {
const array = new Uint8Array(byteCount);
crypto.getRandomValues(array);
return btoa(String.fromCharCode.apply(null, array));
}
scryptWebWorker = new Worker("./static/scryptWebWorker.js"); // , {"type": "module"}s
scryptWebWorkerPromises = {};
callScryptWebWorkerAsync = (functionName, parameters) => {
const functionCallId = randomBytesBase64(4);
let promise;
promise = new Promise((resolve, reject) => {
this.scryptWebWorkerPromises[functionCallId] = { promise, resolve, reject };
});
this.scryptWebWorker.postMessage({
functionCallId: functionCallId,
functionName: functionName,
parameters: parameters
});
return promise;
};
scryptWebWorker.onmessage = (e) => {
this.scryptWebWorkerPromises[e.data.functionCallId].resolve(e.data.result);
};
// ----------------------------------------------
// Then you may call it like this:
// ----------------------------------------------
function utf8Base64(str) {
const encoder = new TextEncoder();
const uint8Array = encoder.encode(str);
let binaryString = "";
for (let i = 0; i < uint8Array.length; i++) {
binaryString += String.fromCharCode(uint8Array[i]);
}
return window.btoa(binaryString);
}
testScryptHash = async () => {
console.log(1)
const cpuAndMemoryCost = 8192;
const blockSize = 64;
const parallelism = 1;
const keyLength = 32;
const result = await callScryptWebWorkerAsync(
'scrypt', [
utf8Base64("this is the string to be hashed"),
utf8Base64("this is the salt"),
cpuAndMemoryCost,
blockSize,
parallelism,
keyLength
]
)
console.log(2)
console.log(result)
};
testScryptHash();
</script>