Skip to content

Commit 7447f37

Browse files
committed
Add Argon2 hash operation
1 parent 0670894 commit 7447f37

File tree

6 files changed

+128
-0
lines changed

6 files changed

+128
-0
lines changed

package-lock.json

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"babel-eslint": "^10.0.3",
4444
"babel-loader": "^8.0.6",
4545
"babel-plugin-dynamic-import-node": "^2.3.0",
46+
"base64-loader": "^1.0.0",
4647
"chromedriver": "^76.0.1",
4748
"colors": "^1.3.3",
4849
"copy-webpack-plugin": "^5.0.4",
@@ -85,6 +86,7 @@
8586
"dependencies": {
8687
"@babel/polyfill": "^7.4.4",
8788
"@babel/runtime": "^7.5.5",
89+
"argon2-browser": "^1.11.1",
8890
"arrive": "^2.4.1",
8991
"babel-plugin-transform-builtin-extend": "1.1.2",
9092
"bcryptjs": "^2.4.3",

src/core/config/Categories.json

+1
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@
320320
"Bcrypt compare",
321321
"Bcrypt parse",
322322
"Scrypt",
323+
"Argon2",
323324
"Fletcher-8 Checksum",
324325
"Fletcher-16 Checksum",
325326
"Fletcher-32 Checksum",

src/core/operations/Argon2.mjs

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* @author Tan Zhen Yong [[email protected]]
3+
* @copyright Crown Copyright 2019
4+
* @license Apache-2.0
5+
*/
6+
7+
import Operation from "../Operation.mjs";
8+
import OperationError from "../errors/OperationError.mjs";
9+
import argon2 from "argon2-browser";
10+
11+
/**
12+
* Argon2 operation
13+
*/
14+
class Argon2 extends Operation {
15+
16+
/**
17+
* Argon2 constructor
18+
*/
19+
constructor() {
20+
super();
21+
22+
this.name = "Argon2";
23+
this.module = "Crypto";
24+
this.description = "Argon2 is a key derivation function that was selected as the winner of the Password Hashing Competition in July 2015. It was designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich from the University of Luxembourg.<br><br>Enter the password in the input to generate its hash.";
25+
this.infoURL = "https://wikipedia.org/wiki/Argon2";
26+
this.inputType = "string";
27+
this.outputType = "string";
28+
this.args = [
29+
{
30+
"name": "Salt",
31+
"type": "string",
32+
"value": "somesalt"
33+
},
34+
{
35+
"name": "Iterations",
36+
"type": "number",
37+
"value": 3
38+
},
39+
{
40+
"name": "Memory (KiB)",
41+
"type": "number",
42+
"value": 4096
43+
},
44+
{
45+
"name": "Parallelism",
46+
"type": "number",
47+
"value": 1
48+
},
49+
{
50+
"name": "Hash length (bytes)",
51+
"type": "number",
52+
"value": 32
53+
},
54+
{
55+
"name": "Type",
56+
"type": "option",
57+
"value": ["Argon2i", "Argon2d", "Argon2id"],
58+
"defaultIndex": 0
59+
}
60+
];
61+
}
62+
63+
/**
64+
* @param {string} input
65+
* @param {Object[]} args
66+
* @returns {string}
67+
*/
68+
run(input, args) {
69+
const argon2Types = {
70+
"Argon2i": argon2.ArgonType.Argon2i,
71+
"Argon2d": argon2.ArgonType.Argon2d,
72+
"Argon2id": argon2.ArgonType.Argon2id
73+
};
74+
75+
const salt = args[0],
76+
time = args[1],
77+
mem = args[2],
78+
parallelism = args[3],
79+
hashLen = args[4],
80+
type = argon2Types[args[5]];
81+
82+
return argon2.hash({
83+
pass: input,
84+
salt,
85+
time,
86+
mem,
87+
parallelism,
88+
hashLen,
89+
type,
90+
}).then(res => {
91+
return `Encoded: ${res.encoded}\nHash: ${res.hashHex}`;
92+
}).catch(err => {
93+
throw new OperationError(`Error: ${err.message}`);
94+
});
95+
}
96+
97+
}
98+
99+
export default Argon2;

tests/node/tests/operations.mjs

+6
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ Tiger-128`;
132132
assert.strictEqual(result.toString(), "Szkkb zh z Xozn");
133133
}),
134134

135+
it("Argon2", async () => {
136+
const result = await chef.Argon2("argon2password");
137+
assert.strictEqual(result.toString(), `Encoded: $argon2i$v=19$m=4096,t=3,p=1$c29tZXNhbHQ$s43my9eBljQADuF/LWCG8vGqwAJzOorKQ0Yog8jFvbw
138+
Hash: b38de6cbd7819634000ee17f2d6086f2f1aac002733a8aca43462883c8c5bdbc`);
139+
}),
140+
135141
it("Bcrypt", async () => {
136142
const result = await chef.bcrypt("Put a Sock In It");
137143
assert.strictEqual(result.toString(), "$2a$10$ODeP1.6fMsb.ENk2ngPUCO7qTGVPyHA9TqDVcyupyed8FjsiF65L6");

webpack.config.js

+9
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ module.exports = {
6565
},
6666
},
6767
module: {
68+
// argon2-browser loads argon2.wasm by itself, so Webpack should not load it
69+
noParse: /node_modules\/argon2-browser\/dist\/argon2\.wasm$/,
6870
rules: [
6971
{
7072
test: /\.m?js$/,
@@ -77,6 +79,13 @@ module.exports = {
7779
type: "javascript/auto",
7880
loader: "babel-loader"
7981
},
82+
{
83+
test: /node_modules\/argon2-browser\/dist\/argon2\.wasm$/,
84+
// Load argon2.wasm as base64-encoded binary file
85+
// expected by argon2-browser
86+
loaders: "base64-loader",
87+
type: "javascript/auto"
88+
},
8089
{
8190
test: /forge.min.js$/,
8291
loader: "imports-loader?jQuery=>null"

0 commit comments

Comments
 (0)