diff --git a/packages/wasm-crypto/Cargo.lock b/packages/wasm-crypto/Cargo.lock index 5d627c7e..62a6075d 100644 --- a/packages/wasm-crypto/Cargo.lock +++ b/packages/wasm-crypto/Cargo.lock @@ -468,6 +468,18 @@ name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scrypt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde" version = "1.0.114" @@ -631,6 +643,7 @@ dependencies = [ "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "schnorrkel 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-bip39 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -800,6 +813,7 @@ dependencies = [ "checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" "checksum schnorrkel 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +"checksum scrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656c79d0e90d0ab28ac86bf3c3d10bfbbac91450d3f190113b4e76d9fec3cfdd" "checksum serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3" "checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" "checksum signature 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65211b7b6fc3f14ff9fc7a2011a434e3e6880585bd2e9e9396315ae24cbf7852" diff --git a/packages/wasm-crypto/Cargo.toml b/packages/wasm-crypto/Cargo.toml index 6ec117fa..e43124d6 100644 --- a/packages/wasm-crypto/Cargo.toml +++ b/packages/wasm-crypto/Cargo.toml @@ -23,6 +23,7 @@ hmac = "0.7.0" # libsecp256k1 = "0.2.2" pbkdf2 = { version = "0.3.0", default-features = false } schnorrkel = { version = "0.9.1", features = ["nightly", "preaudit_deprecated", "u64_backend"] } +scrypt = { version = "0.2", default-features = false } sha2 = "0.8.1" subtle = "2.2.3" tiny-bip39 = { version = "0.7", default-features = false } diff --git a/packages/wasm-crypto/src/hashing.rs b/packages/wasm-crypto/src/hashing.rs index 25a05c55..5ccfce9c 100644 --- a/packages/wasm-crypto/src/hashing.rs +++ b/packages/wasm-crypto/src/hashing.rs @@ -6,6 +6,7 @@ use blake2_rfc::blake2b::blake2b; use byteorder::{ByteOrder, LittleEndian}; use hmac::Hmac; use pbkdf2::pbkdf2; +use scrypt::{ScryptParams, scrypt}; use sha2::{Digest, Sha512}; // use secp256k1; use tiny_keccak::{Hasher, Keccak}; @@ -58,13 +59,13 @@ pub fn ext_keccak256(data: &[u8]) -> Vec { result.to_vec() } -/// pbkdf2 hash from an input, salt for the number of specified rounds +/// pbkdf2 kdf from an input, salt for the number of specified rounds /// /// * data: Arbitrary data to be hashed /// * salt: Salt for this hash /// * rounds: The number of rounds to perform /// -/// Returns a vecor with the hash result +/// Returns a vector with the hashed result #[wasm_bindgen] pub fn ext_pbkdf2(data: &[u8], salt: &[u8], rounds: u32) -> Vec { let mut result = [0u8; 64]; @@ -75,6 +76,26 @@ pub fn ext_pbkdf2(data: &[u8], salt: &[u8], rounds: u32) -> Vec { result.to_vec() } +/// scrypt kdf from input, salt and config +/// +/// * password: Password to hash +/// * salt: Salt for this hash +/// * log2_n: log2(n) +/// * r: r +/// * p: p +/// +/// Returns vector with the hashed result +#[wasm_bindgen] +pub fn ext_scrypt(password: &[u8], salt: &[u8], log2_n: u8, r: u32, p: u32) -> Vec { + let params = ScryptParams::new(log2_n, r, p).unwrap(); + let mut result = [0u8; 64]; + + match scrypt(password, salt, ¶ms, &mut result) { + Ok(_) => return result.to_vec(), + Err(_) => panic!("Invalid scrypt hash.") + } +} + // /// Checks for the recoverability of a signature from message // /// // /// * message: The message @@ -215,6 +236,16 @@ pub mod tests { assert_eq!(hash[..], expected[..]); } + #[test] + fn can_scrypt() { + let password = b"password"; + let salt = b"salt"; + let expected = hex!("745731af4484f323968969eda289aeee005b5903ac561e64a5aca121797bf7734ef9fd58422e2e22183bcacba9ec87ba0c83b7a2e788f03ce0da06463433cda6"); + let hash = ext_scrypt(password, salt, 14, 8, 1); + + assert_eq!(hash[..], expected[..]); + } + // #[test] // fn can_secp256k1_real_eth_sig() { // let sig = hex!("7505f2880114da51b3f5d535f8687953c0ab9af4ab81e592eaebebf53b728d2b6dfd9b5bcd70fee412b1f31360e7c2774009305cb84fc50c1d0ff8034dfa5fff1c"); diff --git a/packages/wasm-crypto/src/js/exports.js b/packages/wasm-crypto/src/js/exports.js index 221fec75..10e930f7 100644 --- a/packages/wasm-crypto/src/js/exports.js +++ b/packages/wasm-crypto/src/js/exports.js @@ -37,6 +37,7 @@ module.exports = function (stubbed) { blake2b: wrapReady(stubbed.ext_blake2b), keccak256: wrapReady(stubbed.ext_keccak256), pbkdf2: wrapReady(stubbed.ext_pbkdf2), + scrypt: wrapReady(stubbed.ext_scrypt), // secp256k1IsRecoverable: wrapReady(stubbed.ext_secp256k1_is_recoverable); // secp256k1Recover: wrapReady(stubbed.ext_secp256k1_recover); diff --git a/packages/wasm-crypto/test/all/hashing.js b/packages/wasm-crypto/test/all/hashing.js index 6aefc09f..3bdc8a49 100644 --- a/packages/wasm-crypto/test/all/hashing.js +++ b/packages/wasm-crypto/test/all/hashing.js @@ -41,6 +41,14 @@ function pbkdf2Hash (wasm) { // assert(pk === '0x91d366769d44a7c7690428bfdf67ec7eae23d2459694685257b6fc59d1baa1fe', 'ERROR: secp256k1Recover does not match'); // } +function scryptHash (wasm) { + const hash = u8aToHex(wasm.scrypt(stringToU8a('password'), stringToU8a('salt'), 14, 8, 1)); + + console.log('\tRES', hash); + + assert(hash === '0x745731af4484f323968969eda289aeee005b5903ac561e64a5aca121797bf7734ef9fd58422e2e22183bcacba9ec87ba0c83b7a2e788f03ce0da06463433cda6', 'ERROR: scryptHash does not match'); +} + function sha512Hash (wasm) { const hash = u8aToHex(wasm.sha512(stringToU8a('hello world'))); @@ -63,6 +71,7 @@ module.exports = { blake2bHash, keccak256, pbkdf2Hash, + scryptHash, // secp256k1Recover, sha512Hash, twoxHash