Skip to content

Commit

Permalink
refactor: remove dependencies (#6)
Browse files Browse the repository at this point in the history
* refactor: remove bitcoin_hashes

* refactor: remove sha2

* chore: run rustfmt
  • Loading branch information
mikesposito authored Sep 22, 2023
1 parent d4c03c5 commit 5c98e6f
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 148 deletions.
24 changes: 0 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 8 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ keywords = [
]

[dependencies]
hex = "0.4.3"
bitcoin_hashes = { version = ">= 0.12, <= 0.13" }
sha3 = "0.10.8"
bip32 = { version = "0.5.1" }
secp256k1 = "0.27.0"
rand_core = { version = "0.6", features = ["std"] }
chacha20poly1305 = { version = "0.9.0", features = ["stream"] }
pbkdf2 = { version = "0.12.2" }
sha2 = { version = "0.10.7" }
hmac = { version = "0.12.1" }
bip32 = "~0.5.1"
chacha20poly1305 = "~0.9.0"
hex = "~0.4.3"
hmac = "~0.12.1"
pbkdf2 = "~0.12.2"
rand_core = { version = "~0.6.0", features = ["std"] }
secp256k1 = "~0.27.0"
sha3 = "~0.10.8"
114 changes: 9 additions & 105 deletions src/account/keychain/account.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use bip32::XPub;
use hex::decode;
use sha3::{Digest, Keccak256};

use crate::{
hex::{add0x, assert_is_valid_hex_address, encode},
utils::crypto::sha3::keccak256,
};

#[derive(Clone, Debug)]
pub struct Account {
Expand All @@ -11,113 +14,14 @@ pub struct Account {
impl Account {
/// Create a new `Account` from an extended public key
pub fn from_extended_public_key(extended_public_key: &XPub) -> Result<Self, String> {
let address = extended_public_key_to_address(extended_public_key)?;
let extended_address = encode(&keccak256(&extended_public_key.to_bytes()));
let address = extended_address[extended_address.len() - 40..].to_string();

assert_is_valid_hex_address(address.as_str())?;
assert_is_valid_hex_address(&address)?;

Ok(Account {
address: add0x(address),
address: add0x(&address).to_owned(),
public_key: extended_public_key.to_owned(),
})
}
}

/// Assert that a string is a valid hex address
///
/// # Example
///
/// ```
/// use walleth::account::assert_is_valid_hex_address;
///
/// println!("{}", assert_is_valid_hex_address("0x00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD").is_ok());
///
/// assert_eq!(assert_is_valid_hex_address("0x00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD").is_ok(), true);
/// ```
pub fn assert_is_valid_hex_address(value: &str) -> Result<(), String> {
let unprefixed = remove0x(value);

assert_is_hex(&unprefixed)?;

if unprefixed.len() != 40 {
return Err(format!(
"String passed into assert_is_valid_hex_address is {} hex chars long instead of 40.",
value.len()
));
}

Ok(())
}

/// Assert that a string is a valid hex
///
/// # Example
///
/// ```
/// use walleth::account::assert_is_hex;
///
/// let assertion = assert_is_hex("00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD");
///
/// assert!(assertion.is_ok());
/// ```
pub fn assert_is_hex(value: &str) -> Result<(), String> {
match decode(value) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
}

/// Remove the 0x prefix from a string
///
/// # Example
///
/// ```
/// use walleth::remove0x;
///
/// let unprefixed = remove0x("0x00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD");
/// assert_eq!(
/// unprefixed,
/// "00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD",
/// );
/// ```
pub fn remove0x(value: &str) -> &str {
match value.starts_with("0x") {
true => &value[2..],
_ => value,
}
}

/// Add the 0x prefix to a string
///
/// # Example
///
/// ```
/// use walleth::add0x;
///
/// assert_eq!(
/// add0x("00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD".to_string()),
/// "0x00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD".to_string(),
/// );
/// ```
pub fn add0x(value: String) -> String {
match value.starts_with("0x") {
true => value,
_ => format!("0x{}", value),
}
}

/// Convert an extended public key to an ethereum address
pub fn extended_public_key_to_address(extended_public_key: &XPub) -> Result<String, String> {
let address = keccak_hash(&extended_public_key.to_bytes());
Ok(address[(address.len() - 40)..].to_string())
}

/// Hash data using the keccak256 algorithm
fn keccak_hash<T>(data: &T) -> String
where
T: ?Sized + AsRef<[u8]>,
{
let mut hasher = Keccak256::new();
hasher.update(data);
let result = hasher.finalize();
hex::encode(result)
}
9 changes: 4 additions & 5 deletions src/account/signer/signable.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use bitcoin_hashes::{sha256, Hash};
use secp256k1::Message;

use crate::utils::crypto::sha3::keccak256;

#[derive(Debug, Clone)]
pub struct Signable {
message: Message,
Expand Down Expand Up @@ -37,13 +38,11 @@ impl Signable {

/// Digest a message string
pub fn digest_str(message: &str) -> Message {
let hash = sha256::Hash::hash(message.as_bytes());
Message::from_slice(hash.as_byte_array()).unwrap()
Message::from_slice(&keccak256(message.as_bytes())).unwrap()
}

/// Digest message bytes
pub fn digest_bytes(message: &[u8]) -> Message {
let hash = sha256::Hash::hash(message);
// Unwrap is safe because the hash is always 32 bytes
Message::from_slice(hash.as_byte_array()).unwrap()
Message::from_slice(&keccak256(message)).unwrap()
}
1 change: 1 addition & 0 deletions src/utils/crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod sha3;
30 changes: 30 additions & 0 deletions src/utils/crypto/sha3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use sha3::{Digest, Keccak256};

/// Computes the Keccak-256 hash of the input data.
///
/// # Example
///
/// ```
/// use walleth::utils::crypto::sha3::keccak256;
///
/// let hash = keccak256(&"Hello, world!".as_bytes());
///
/// assert_eq!(
/// hash,
/// [
/// 182, 225, 109, 39, 172,
/// 90, 180, 39, 167, 246,
/// 137, 0, 172, 85, 89,
/// 206, 39, 45, 198, 195,
/// 124, 130, 179, 224, 82,
/// 36, 108, 130, 36, 76,
/// 80, 228
/// ]
/// );
/// ```
///
pub fn keccak256(data: &[u8]) -> [u8; 32] {
let mut hasher = Keccak256::new();
hasher.update(data);
hasher.finalize().into()
}
95 changes: 95 additions & 0 deletions src/utils/hex/hex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use hex;

/// Encode a byte array into a hex string
pub fn encode(data: &[u8]) -> String {
hex::encode(data)
}

/// Decode a hex string into a byte array
pub fn decode(data: &str) -> Result<Vec<u8>, String> {
match hex::decode(data) {
Ok(bytes) => Ok(bytes),
Err(e) => Err(e.to_string()),
}
}

/// Assert that a string is a valid hex address
///
/// # Example
///
/// ```
/// use walleth::utils::hex::assert_is_valid_hex_address;
///
/// assert!(assert_is_valid_hex_address(&"0x00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD".to_string()).is_ok());
/// ```
pub fn assert_is_valid_hex_address(value: &String) -> Result<(), String> {
let unprefixed = remove0x(value);

assert_is_hex(&unprefixed)?;

if unprefixed.len() != 40 {
return Err(format!(
"String passed into assert_is_valid_hex_address is {} hex chars long instead of 40.",
value.len()
));
}

Ok(())
}

/// Assert that a string is a valid hex
///
/// # Example
///
/// ```
/// use walleth::utils::hex::assert_is_hex;
///
/// let assertion = assert_is_hex(&"00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD".to_string());
///
/// assert!(assertion.is_ok());
/// ```
pub fn assert_is_hex(value: &str) -> Result<(), String> {
match decode(value) {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
}

/// Remove the 0x prefix from a string
///
/// # Example
///
/// ```
/// use walleth::utils::hex::remove0x;
///
/// let unprefixed = remove0x(&"0x00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD".to_string());
/// assert_eq!(
/// unprefixed,
/// "00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD".to_string(),
/// );
/// ```
pub fn remove0x(value: &String) -> String {
match value.starts_with("0x") {
true => String::from(&value[2..]),
_ => value.to_string(),
}
}

/// Add the 0x prefix to a string
///
/// # Example
///
/// ```
/// use walleth::utils::hex::add0x;
///
/// assert_eq!(
/// add0x(&"00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD".to_string()),
/// "0x00C08c440DbDC3A2a9C9D99b30077a53Ba7eDEAD",
/// );
/// ```
pub fn add0x(value: &String) -> String {
match value.starts_with("0x") {
true => value.to_string(),
_ => format!("0x{}", value),
}
}
2 changes: 2 additions & 0 deletions src/utils/hex/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod hex;
pub use hex::*;
2 changes: 2 additions & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub mod controller;
pub mod crypto;
pub mod hdwallet;
pub mod hex;
pub mod observable;
pub mod safe;

Expand Down
6 changes: 3 additions & 3 deletions src/utils/safe/encryption_key.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use hmac::Hmac;
use pbkdf2::pbkdf2;
use rand_core::{OsRng, RngCore};
use sha2::Sha256;
use sha3::Keccak256;

/// A Public Key & Salt pair that can be used for simmetric encryption,
/// compatible with ChaCha20Poly1305
Expand All @@ -27,7 +27,7 @@ impl EncryptionKey {

// Key derivation
let mut pubk = [0; 32];
if let Err(_) = pbkdf2::<Hmac<Sha256>>(password, &salt, rounds, &mut pubk) {
if let Err(_) = pbkdf2::<Hmac<Keccak256>>(password, &salt, rounds, &mut pubk) {
panic!("Key derivation failed")
}

Expand All @@ -39,7 +39,7 @@ impl EncryptionKey {
pub fn with_salt(password: &[u8], salt: [u8; 16], rounds: u32) -> Self {
// Key derivation
let mut pubk = [0; 32];
if let Err(_) = pbkdf2::<Hmac<Sha256>>(password, &salt, rounds, &mut pubk) {
if let Err(_) = pbkdf2::<Hmac<Keccak256>>(password, &salt, rounds, &mut pubk) {
panic!("Key derivation failed")
}

Expand Down
Loading

0 comments on commit 5c98e6f

Please sign in to comment.