diff --git a/Cargo.lock b/Cargo.lock index 4fc7823fe..f8c22f8bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1790,6 +1790,7 @@ dependencies = [ "pasta_curves", "rand 0.8.5", "rand_core 0.6.4", + "sha2 0.10.8", "subtle", "thiserror", ] diff --git a/src/sdk/Cargo.toml b/src/sdk/Cargo.toml index 169c5a59f..ffedf08e1 100644 --- a/src/sdk/Cargo.toml +++ b/src/sdk/Cargo.toml @@ -24,7 +24,7 @@ darkfi-serial = {path = "../serial", features = ["crypto"]} # Encoding bs58 = "0.5.0" -sha256 = "1.4.0" +sha2 = "0.10.8" # Cryptography blake2b_simd = "1.0.2" diff --git a/src/sdk/src/crypto/mod.rs b/src/sdk/src/crypto/mod.rs index dcb16dffb..5dbb4a262 100644 --- a/src/sdk/src/crypto/mod.rs +++ b/src/sdk/src/crypto/mod.rs @@ -79,7 +79,7 @@ pub mod pasta_prelude { /// Wallet Import Format pub mod wif; -pub use wif::WIF; +pub use wif::Wif; #[macro_export] macro_rules! fp_from_bs58 { diff --git a/src/sdk/src/crypto/wif.rs b/src/sdk/src/crypto/wif.rs index 78a121e54..cbb3f4d50 100644 --- a/src/sdk/src/crypto/wif.rs +++ b/src/sdk/src/crypto/wif.rs @@ -16,6 +16,11 @@ * along with this program. If not, see . */ +use std::convert::TryInto; + +use pasta_curves::group::ff::PrimeField; +use sha2::{Digest, Sha256}; + use crate::{ crypto::{ constants::{MAINNET_ADDRS_PREFIX, TESTNET_ADDRS_PREFIX}, @@ -23,27 +28,33 @@ use crate::{ }, error::ContractError, }; -use bs58; -use pasta_curves::group::ff::PrimeField; -use sha256; -use std::convert::TryInto; + +fn double_sha256(input: &[u8]) -> [u8; 32] { + let mut hasher = Sha256::new(); + hasher.update(input); + let first = hasher.finalize(); + + let mut hasher = Sha256::new(); + hasher.update(first); + hasher.finalize().into() +} #[derive(Clone, Debug)] -pub struct WIF(String); +pub struct Wif(String); -/// wallet import format https://en.bitcoin.it/wiki/Wallet_import_format -/// encodes pallas-curve base private key to base58 string. -impl WIF { +/// Wallet import format +/// Encodes pallas-curve base field secret key to base58 string. +impl Wif { /// Get inner wrapped object pub fn inner(&self) -> String { self.0.clone() } } -/// convert `SecretKey` to wallet import format `WIF` -impl From for WIF { +/// Convert `SecretKey` to wallet import format `Wif` +impl From<&SecretKey> for Wif { /// Initialize WIF from `SecretKey` - fn from(secretkey: SecretKey) -> Self { + fn from(secretkey: &SecretKey) -> Self { // address to bytes let address: [u8; 32] = secretkey.inner().to_repr(); // address prefix @@ -58,23 +69,19 @@ impl From for WIF { extended_addrs_prefix.copy_from_slice(&prefix); extended_addrs_main.copy_from_slice(&address); // extended address checksum - let checksum: [u8; 4] = { - let first_digest: String = sha256::digest_bytes(&extended_addrs); - let second_digest: &[u8] = &sha256::digest(first_digest).into_bytes(); - [second_digest[0], second_digest[1], second_digest[2], second_digest[3]] - }; + let checksum: [u8; 4] = double_sha256(&extended_addrs)[0..4].try_into().unwrap(); let mut full_address: [u8; 37] = [0; 37]; let (full_address_left, full_address_right) = full_address.split_at_mut(extended_addrs.len()); full_address_left.copy_from_slice(&extended_addrs); full_address_right.copy_from_slice(&checksum); - WIF(bs58::encode(full_address).into_string()) + Wif(bs58::encode(full_address).into_string()) } } /// convert wallet import format `WIF` to `SecretKey` -impl From for SecretKey { - fn from(wif: WIF) -> Self { +impl From for SecretKey { + fn from(wif: Wif) -> Self { let full_address: Vec = bs58::decode(wif.0).into_vec().unwrap(); // extract prefix // TODO set secret key type mainnet/testnet @@ -88,13 +95,9 @@ impl From for SecretKey { let wif_checksum: [u8; 4] = full_address[33..37].try_into().expect("slice with incorrect length"); // validate checksum - let checksum: [u8; 4] = { - let first_digest: String = sha256::digest_bytes(&extended_addrs); - let second_digest: &[u8] = &sha256::digest(first_digest).into_bytes(); - [second_digest[0], second_digest[1], second_digest[2], second_digest[3]] - }; + let checksum: [u8; 4] = double_sha256(&extended_addrs)[0..4].try_into().unwrap(); assert!(wif_checksum == checksum); - let sk: Result = SecretKey::from_bytes(addrs).into(); + let sk: Result = SecretKey::from_bytes(addrs); sk.unwrap() } } @@ -116,26 +119,23 @@ impl TryInto for String { let wif_checksum: [u8; 4] = full_address[33..37].try_into().expect("slice with incorrect length"); // validate checksum - let checksum: [u8; 4] = { - let first_digest: String = sha256::digest_bytes(&extended_addrs); - let second_digest: &[u8] = &sha256::digest(first_digest).into_bytes(); - [second_digest[0], second_digest[1], second_digest[2], second_digest[3]] - }; + let checksum: [u8; 4] = double_sha256(&extended_addrs)[0..4].try_into().unwrap(); assert!(wif_checksum == checksum); - let sk: Result = SecretKey::from_bytes(addrs).into(); + let sk: Result = SecretKey::from_bytes(addrs); Ok(sk.unwrap()) } } #[cfg(test)] mod tests { - use crate::crypto::{wif::WIF, SecretKey}; + use super::*; + #[test] fn test_sk_towif() { let sk_bytes: [u8; 32] = [0; 32]; - let sk_str = std::str::from_utf8(&sk_bytes).unwrap(); + let _sk_str = std::str::from_utf8(&sk_bytes).unwrap(); let sk = SecretKey::from_bytes(sk_bytes).unwrap(); - let wif = WIF::from(sk); + let wif = Wif::from(&sk); let sk_res = match wif.try_into() { Err(why) => panic!("{:?}", why),