Skip to content

Commit

Permalink
#1 Add method to perform PBKDF2 in WebAssembly to help support experi…
Browse files Browse the repository at this point in the history
…ence in MS Edge
  • Loading branch information
Ernie Turner committed Jan 7, 2019
1 parent 3553414 commit c23df75
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 1 deletion.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ crate-type = ["cdylib"]
wasm-bindgen = {version = "~0.2.29", features = ["serde-serialize"]}
serde = "~1.0.82"
js-sys = "~0.3.6"
pbkdf2 = { version = "0.3", default-features = false }
hmac = "0.7"
sha2 = "0.8"
serde_derive = "~1.0.82"
rand = { version = "~0.6.1", features = ["wasm-bindgen"] }
rand = { version = "=0.6.1", features = ["wasm-bindgen"] }
recrypt = { git = "https://github.com/IronCoreLabs/recrypt-rs", tag = "0.5.1"}

# The recrypt Ed25519 library that we use (https://github.com/dalek-cryptography/ed25519-dalek) depends on this clear_on_drop
Expand Down
6 changes: 6 additions & 0 deletions benchmark/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import transformLevelTwo from "./transformLevelTwo";
import decryptLevelZero from "./decryptLevelZero";
import decryptLevelOne from "./decryptLevelOne";
import decryptLevelTwo from "./decryptLevelTwo";
import pbkdf2SHA256 from "./pbkdf2SHA256";

const resultsDiv = document.createElement("div");
document.body.appendChild(resultsDiv);
Expand Down Expand Up @@ -38,6 +39,7 @@ import("../lib/Api256Shim").then((Recrypt) => {
const decryptLevelZeroBenchmark = decryptLevelZero(Recrypt, logBenchmarkResult);
const decryptLevelOneBenchmark = decryptLevelOne(Recrypt, logBenchmarkResult);
const decryptLevelTwoBenchmark = decryptLevelTwo(Recrypt, logBenchmarkResult);
const pbkdf2SHA256Benchmark = pbkdf2SHA256(Recrypt, logBenchmarkResult);

genKeyPairBenchmark.on("complete", () => {
genEd25519KeyPairbenchmark.run({async: true});
Expand Down Expand Up @@ -84,6 +86,10 @@ import("../lib/Api256Shim").then((Recrypt) => {
});

decryptLevelTwoBenchmark.on("complete", () => {
pbkdf2SHA256Benchmark.run({async: true});
});

pbkdf2SHA256Benchmark.on("complete", () => {
logBenchmarkResult("Benchmark Complete");
});

Expand Down
22 changes: 22 additions & 0 deletions benchmark/pbkdf2SHA256.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
declare const Benchmark: any;

export default (Recrypt: typeof import("../lib/Api256Shim"), logResult: (results: string) => void) => {
//prettier-ignore
const salt = new Uint8Array([138, 136, 227, 221, 116, 9, 241, 149, 253, 82, 219, 45, 60, 186, 93, 114, 202, 103, 9, 191, 29, 148, 18, 27, 243, 116, 136, 1, 180, 15, 111, 92]);
const iterations = 250000;
const password = new Uint8Array([112, 97, 115, 115, 119, 111, 114, 100]);

return new Benchmark("pbkdf2SHA256", {
fn: () => {
Recrypt.pbkdf2SHA256(salt, password, iterations);
},
onError: (err: Error) => {
console.log(err);
},
onComplete: (result: any) => {
const resultString = result.currentTarget.toString();
logResult(resultString);
console.log(result.currentTarget.toString());
},
});
};
7 changes: 7 additions & 0 deletions lib/Api256Shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,10 @@ export function augmentPublicKey256(currentPublicKey: PublicKey, otherPublicKey:
const augmentedKey = Recrypt.augmentPublicKey256(publicKeyBytesToArray(currentPublicKey), publicKeyBytesToArray(otherPublicKey));
return publicKeyArrayToBytes(augmentedKey);
}

/**
* Create a derived 32-byte key from the provided password bytes.
*/
export function pbkdf2SHA256(salt: Uint8Array, password: Uint8Array, iterations: number) {
return Recrypt.pbkdf2SHA256(salt, password, iterations);
}
14 changes: 14 additions & 0 deletions lib/tests/Api256Shim.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,20 @@ import("../Api256Shim").then((Recrypt) => {
expect(augPublicKey).not.to.deep.equal(pub1);
});
});

describe("pbkdf2SHA256", () => {
it("creates the expected derived key", () => {
//prettier-ignore
const salt = new Uint8Array([138, 136, 227, 221, 116, 9, 241, 149, 253, 82, 219, 45, 60, 186, 93, 114, 202, 103, 9, 191, 29, 148, 18, 27, 243, 116, 136, 1, 180, 15, 111, 92]);
const iterations = 250000;
const password = new Uint8Array([112, 97, 115, 115, 119, 111, 114, 100]);

expect(Recrypt.pbkdf2SHA256(salt, password, iterations)).to.deep.equal(
//prettier-ignore
new Uint8Array([33, 169, 177, 104, 32, 121, 170, 221, 21, 229, 188, 159, 140, 164, 44, 173, 30, 151, 210, 60, 34, 10, 160, 186, 168, 36, 102, 174, 64, 110, 227, 170])
);
});
});
});
mocha.checkLeaks();
mocha.run();
Expand Down
1 change: 1 addition & 0 deletions recrypt_wasm_binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ export class Api256 {
export function transformKeyToBytes256(transformKey: TransformKey): Uint8Array;
export function augmentTransformKey256(transformKey: TransformKey, privateKey: PrivateKey): TransformKey;
export function augmentPublicKey256(currentPublicKey: PublicKey, otherPublicKey: PublicKey): PublicKey;
export function pbkdf2SHA256(salt: Uint8Array, password: Uint8Array, iterations: number): Uint8Array;
14 changes: 14 additions & 0 deletions src/api256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use recrypt::api::{
use util;
use util::{JsError, WasmError};
use wasm_bindgen::prelude::*;
use sha2;
use hmac::Hmac;
use pbkdf2::pbkdf2;

#[wasm_bindgen]
pub struct Api256 {
Expand Down Expand Up @@ -362,3 +365,14 @@ pub fn augmentPublicKey256(
.map_err(WasmError::new)?,
)
}

/**
* PBKDF2 algorithm which uses SHA-256 as the hashing algorithm. Takes password to create a derived key from,
* 32 bytes of salt, and an iteration count and returns a vector of bytes which can be used as a secure derived key.
*/
#[wasm_bindgen]
pub fn pbkdf2SHA256(salt: &[u8], password: &[u8], iterations: u32) -> Vec<u8> {
let mut derived_key = [0u8; 32];
pbkdf2::<Hmac<sha2::Sha256>>(password, salt, iterations as usize, &mut derived_key);
derived_key.to_vec()
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ extern crate serde_derive;
extern crate rand;
extern crate recrypt;
extern crate wasm_bindgen;
extern crate sha2;
extern crate hmac;
extern crate pbkdf2;

pub mod api256;
mod util;

0 comments on commit c23df75

Please sign in to comment.