Ethereum-js Integration
I love integrating JavaScript with cryptography — as it allows me to demonstrate things to students in a convenient way. Today, I converted ethereum-js into a single pure JavaScript form. Here is a test with PBKDF2 [here]:
With PBKDF2 (Password-Based Key Derivation Function 2), we hash for a given number of rounds:
Code
The following is the code [here]:
<style>
.dropdown {
font-size: 16px;
border: 2px solid grey;
width: 100%;
border-left: 12px solid green;
border-radius: 5px;
padding: 14px;
}
pre {
font-size: 16px;
border: 2px solid grey;
width: 100%;
border-left: 12px solid green;
border-radius: 5px;
padding: 14px;
}
textarea {
font-size: 20px;
border: 2px solid grey;
width: 100%;
border-radius: 5px;
padding: 14px;
}
</style>
<script src="../ethjs.js"></script>
<div class="indented">
<table width="100%">
<tr>
<th width="15%">Method</th>
<td style="text-align:left">
<p>
<input id="genkey" class="btn btn-large btn-primary" type="button" value="Gen New PBKDF2" />
</p>
</td>
</tr>
<tr>
<th width="15%">Message</th>
<td>
<textarea cols="20" id="message" name="message" rows="2" style="width:100%"></textarea>
</td>
</tr>
<tr>
<th width="15%">Salt</th>
<td>
<textarea cols="20" id="salt" name="salt" rows="2" style="width:100%"></textarea>
</td>
</tr>
<tr>
<th width="15%">Hash method</th>
<td style="text-align:left">
<div class="dropdown">
<select name="hashmethod" id="hashmethod">
<option value="sha256">sha256</option>
<option value="sha512">sha512</option>
</select>
</div>
</td>
</tr>
<tr>
<th width="15%">Key size</th>
<td style="text-align:left">
<div class="dropdown">
<select name="keysize" id="keysize">
<option value="16 bytes">16</option>
<option value="24 bytes">24</option>
<option value="32 bytes">32</option>
</select>
</div>
</td>
</tr>
<tr>
<th width="15%">Iterations</th>
<td style="text-align:left">
<div class="dropdown">
<select name="iterations" id="iterations">
<option value="1">1</option>
<option value="100">100</option>
<option value="200">200</option>
<option value="300">300</option>
<option value="400">400</option>
<option value="500">500</option>
<option value="600">600</option>
<option value="1000">1000</option>
<option value="2000">2000</option>
<option value="3000">3000</option>
<option value="4000">4000</option>
<option value="5000">5000</option>
</select>
</div>
</td>
</tr>
</table>
<h2>Keys</h2>
<table width="100%">
<tr>
<th valign="top" width="15%">Secret key</th>
<td>
<pre id="key"></pre>
</td>
</tr>
</table>
</div>
<script>
(async function () {
function toHexString(byteArray) {
return Array.from(byteArray, function (byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('')
}
async function pbkdf2() {
var message = document.getElementById("message").value;
var keysize = parseInt(document.getElementById("keysize").value);
var saltval = document.getElementById("salt").value;
var hashmethod = document.getElementById("hashmethod").value;
var iter = parseInt(document.getElementById("iterations").value);
console.log("Message ", message);
console.log("Salt ", saltval);
console.log("Iter ", iter);
console.log("Key size ", keysize);
const pass = ethjs.utf8ToBytes(message);
const salt = ethjs.utf8ToBytes(saltval);
const iters = iter;
const outLength = keysize;
var hash = await ethjs.pbkdf2(pass, salt, iters, outLength, hashmethod);
document.getElementById("key").innerHTML = "Type:\t\tPBKDF2";
document.getElementById("key").innerHTML += "\nMessage:\t" + message;
document.getElementById("key").innerHTML += "\nHash method:\t" + hashmethod;
document.getElementById("key").innerHTML += "\nIterations:\t" + iter;
document.getElementById("key").innerHTML += "\nSalt:\t\t" + saltval;
document.getElementById("key").innerHTML += "\n\nKey:\t\t" + toHexString(hash);
}
document.getElementById('message').innerHTML = "Hello 123";
document.getElementById('salt').innerHTML = "salt";
await pbkdf2();
document.getElementById("salt").addEventListener("input", pbkdf2);
document.getElementById("keysize").addEventListener("click", pbkdf2);
document.getElementById("hashmethod").addEventListener("click", pbkdf2);
document.getElementById("genkey").addEventListener("click", pbkdf2);
document.getElementById("iterations").addEventListener("click", pbkdf2);
document.getElementById("message").addEventListener("input", pbkdf2);
message.focus();
})();
</script>
The JavaScript source code is [here].
Building the JavaScript file
So the steps for reference were to create an entry file with:
export * from './esm/utils.js';
export * from './esm/sha512.js';
export * from './esm/sha256.js';and so on for all the files, and then create rollup.config.js with:
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
input: ['entry.js'],
output: {
file: 'ethjs.js',
format: 'iife',
name: 'ethjs',
},
plugins: [
resolve({ browser: true }),
commonjs(),
],
};and then run:
rollup -c rollup.config.jsYou may need to “npm install rollup” and “npm install @rollup/plugin-commonjs” and @rollup/plugin-node-resolve. We then create a single file library called ethjs.js and is then referenced with the namespace ethjs inside the html file.
