diff --git a/Cargo.toml b/Cargo.toml index 966a066..fdf4bb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,10 +19,15 @@ readme = "README.md" [dependencies] aes = "0.7.4" -bs58 = "0.4.0" -rand = "0.8.4" -ripemd160 = "0.9.1" +bs58 = { version = "0.4.0", default-features = false, features = ["alloc"] } +rand = { version = "0.8.4", default-features = false, features = ["alloc"] } +ripemd160 = { version = "0.9.0", default-features = false } scrypt = { version = "0.7.0", default-features = false } -secp256k1 = "0.20.3" -sha2 = "0.9.5" -unicode-normalization = "0.1.19" +secp256k1 = { version = "0.20.0", default-features = false, features = ["alloc"] } +digest = { version = "0.10.7", default-features = false } +sha2 = { version = "0.10.8", default-features = false } +unicode-normalization = { version = "0.1.19", default-features = false } + +[features] +default = ["std"] +std = ["rand/std", "rand/std_rng", "sha2/std", "unicode-normalization/std", "digest/std"] \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 0cd3ac5..ce499a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -169,6 +169,28 @@ //! }); //! ``` +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate alloc; + +#[cfg(not(feature = "std"))] +use alloc::{ + string::String, + vec::Vec, + vec +}; + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "std")] +use std::{ + string::String, + vec, + vec::Vec, +}; + use aes::Aes256; use aes::cipher::{ BlockDecrypt, @@ -176,11 +198,11 @@ use aes::cipher::{ generic_array::GenericArray, NewBlockCipher }; -use rand::RngCore; +use digest::Digest; +use rand::{RngCore}; use ripemd160::Ripemd160; use scrypt::Params; use secp256k1::{Secp256k1, SecretKey, PublicKey}; -use sha2::Digest; use unicode_normalization::UnicodeNormalization; /// Number of base58 characters on every encrypted private key. @@ -255,6 +277,9 @@ pub enum Error { WifKey, } +#[cfg(feature = "std")] +impl std::error::Error for Error {} + /// Internal Functions to manipulate an arbitrary number of bytes [u8]. trait BytesManipulation { /// Encode informed data in base 58 check. @@ -627,7 +652,10 @@ pub trait Generate { /// .decrypt("\u{03d2}\u{0301}\u{0000}\u{010400}\u{01f4a9}").is_ok() /// ); /// ``` - fn generate(&self, compress: bool) -> Result; + #[cfg(feature = "std")] + fn generate(&self, compress: bool) -> Result; + + fn generate_rng(&self, compress: bool, rng: &mut R) -> Result; } /// Internal trait to manipulate private keys (32 bytes). @@ -683,6 +711,7 @@ impl BytesManipulation for [u8] { #[inline] fn hash160(&self) -> [u8; 20] { let mut result = [0x00; 20]; + use ripemd160::Digest; result[..].copy_from_slice(&Ripemd160::digest(&sha2::Sha256::digest(self))); result } @@ -690,7 +719,7 @@ impl BytesManipulation for [u8] { #[inline] fn hash256(&self) -> [u8; 32] { let mut result = [0x00; 32]; - result[..].copy_from_slice(&sha2::Sha256::digest(&sha2::Sha256::digest(self))); + result[..].copy_from_slice(&sha2::Sha256::digest(sha2::Sha256::digest(self))); result } @@ -777,13 +806,17 @@ impl Encrypt for [u8; 32] { } impl Generate for str { - #[inline] - fn generate(&self, compress: bool) -> Result { + #[cfg(feature = "std")] + fn generate(&self, compress: bool) -> Result { + self.generate_rng(compress, &mut rand::thread_rng()) + } + + fn generate_rng(&self, compress: bool, rng: &mut R) -> Result { let mut owner_salt = [0x00; 8]; let mut pass_factor = [0x00; 32]; let mut seed_b = [0x00; 24]; - rand::thread_rng().fill_bytes(&mut owner_salt); + rng.fill_bytes(&mut owner_salt); scrypt::scrypt( self.nfc().collect::().as_bytes(), @@ -796,7 +829,7 @@ impl Generate for str { let mut pass_point_mul = PublicKey::from_slice(&pass_point).map_err(|_| Error::PubKey)?; - rand::thread_rng().fill_bytes(&mut seed_b); + rng.fill_bytes(&mut seed_b); let factor_b = seed_b.hash256(); @@ -1157,7 +1190,7 @@ mod tests { Err(Error::WifKey) ); assert_eq!( - "KzkcmnPaJd7mqT47Rnk9XMGRfW2wfo7ar2M2o6Yoe6Rdgbg2bHM9".replace("d", "b").decode_wif(), + "KzkcmnPaJd7mqT47Rnk9XMGRfW2wfo7ar2M2o6Yoe6Rdgbg2bHM9".replace('d', "b").decode_wif(), Err(Error::Checksum) ); assert_eq!(["a"; 51].concat().decode_wif(), Err(Error::WifKey)); @@ -1174,7 +1207,7 @@ mod tests { } assert!(TV_ENCRYPTED[1].decrypt("Satoshi").is_ok()); assert_eq!(TV_ENCRYPTED[1].decrypt("wrong"), Err(Error::Pass)); - assert_eq!(TV_ENCRYPTED[1].replace("X", "x").decrypt("Satoshi"), Err(Error::Checksum)); + assert_eq!(TV_ENCRYPTED[1].replace('X', "x").decrypt("Satoshi"), Err(Error::Checksum)); assert_eq!(TV_ENCRYPTED[1][1..].decrypt("Satoshi"), Err(Error::EncKey)); }