Skip to content

Commit

Permalink
Merge pull request #57 from michalkucharczyk/mku-unicode-normalizatio…
Browse files Browse the repository at this point in the history
…n-in-no-std

`alloc` feature added, to gate unicode normalization
  • Loading branch information
stevenroose authored Mar 28, 2024
2 parents a84eb00 + 86353a5 commit 6f6ec34
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 23 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ edition = "2018"

[features]
default = [ "std" ]
std = [ "unicode-normalization", "serde/std" ]
std = [ "alloc", "serde/std", "unicode-normalization/std" ]
rand = [ "crate_rand", "rand_core" ]
alloc = [ "unicode-normalization" ]

# Note: English is the standard for bip39 so always included
chinese-simplified = []
Expand Down Expand Up @@ -49,7 +50,7 @@ zeroize = { version = "1.5", features = ["zeroize_derive"], optional = true }

# Unexported dependnecies
bitcoin_hashes = { version = ">=0.12, <=0.13", default-features = false }
unicode-normalization = { version = "=0.1.22", optional = true }
unicode-normalization = { version = "=0.1.22", default-features = false, optional = true }

[dev-dependencies]
# Enabling the "rand" feature by default to run the benches
Expand Down
38 changes: 17 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,31 @@
#[cfg(any(test, feature = "std"))]
pub extern crate core;

#[cfg(feature = "alloc")]
extern crate alloc;

extern crate bitcoin_hashes;

#[cfg(feature = "std")]
#[cfg(feature = "unicode-normalization")]
extern crate unicode_normalization;

#[cfg(feature = "rand_core")]
pub extern crate rand_core;
#[cfg(feature = "rand")]
pub extern crate crate_rand as rand;
#[cfg(feature = "rand_core")]
pub extern crate rand_core;
#[cfg(feature = "serde")]
pub extern crate serde;

#[cfg(feature = "alloc")]
use alloc::{borrow::Cow, string::ToString, vec::Vec};
use core::{fmt, str};

#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use std::error;

use bitcoin_hashes::{sha256, Hash};

#[cfg(feature = "std")]
#[cfg(feature = "unicode-normalization")]
use unicode_normalization::UnicodeNormalization;

#[cfg(feature = "zeroize")]
Expand Down Expand Up @@ -95,7 +96,7 @@ impl AmbiguousLanguages {
}

/// Returns a vector of the possible languages.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub fn to_vec(&self) -> Vec<Language> {
self.iter().collect()
}
Expand Down Expand Up @@ -183,7 +184,7 @@ impl Mnemonic {
/// Performing this on a [Cow] means that all allocations for normalization
/// can be avoided for languages without special UTF8 characters.
#[inline]
#[cfg(feature = "std")]
#[cfg(feature = "unicode-normalization")]
pub fn normalize_utf8_cow<'a>(cow: &mut Cow<'a, str>) {
let is_nfkd = unicode_normalization::is_nfkd_quick(cow.as_ref().chars());
if is_nfkd != unicode_normalization::IsNormalized::Yes {
Expand Down Expand Up @@ -506,7 +507,7 @@ impl Mnemonic {
}

/// Parse a mnemonic in the given language.
#[cfg(feature = "std")]
#[cfg(feature = "unicode-normalization")]
pub fn parse_in<'a, S: Into<Cow<'a, str>>>(
language: Language,
s: S,
Expand All @@ -517,7 +518,7 @@ impl Mnemonic {
}

/// Parse a mnemonic and detect the language from the enabled languages.
#[cfg(feature = "std")]
#[cfg(feature = "unicode-normalization")]
pub fn parse<'a, S: Into<Cow<'a, str>>>(s: S) -> Result<Mnemonic, Error> {
let mut cow = s.into();
Mnemonic::normalize_utf8_cow(&mut cow);
Expand All @@ -542,17 +543,12 @@ impl Mnemonic {
const PBKDF2_BYTES: usize = 64;

let mut seed = [0u8; PBKDF2_BYTES];
pbkdf2::pbkdf2(
self.words(),
normalized_passphrase.as_bytes(),
PBKDF2_ROUNDS,
&mut seed,
);
pbkdf2::pbkdf2(self.words(), normalized_passphrase.as_bytes(), PBKDF2_ROUNDS, &mut seed);
seed
}

/// Convert to seed bytes.
#[cfg(feature = "std")]
#[cfg(feature = "unicode-normalization")]
pub fn to_seed<'a, P: Into<Cow<'a, str>>>(&self, passphrase: P) -> [u8; 64] {
let normalized_passphrase = {
let mut cow = passphrase.into();
Expand Down Expand Up @@ -601,7 +597,7 @@ impl Mnemonic {
}

/// Convert the mnemonic back to the entropy used to generate it.
#[cfg(feature = "std")]
#[cfg(feature = "alloc")]
pub fn to_entropy(&self) -> Vec<u8> {
let (arr, len) = self.to_entropy_array();
arr[0..len].to_vec()
Expand Down Expand Up @@ -653,11 +649,11 @@ impl str::FromStr for Mnemonic {
type Err = Error;

fn from_str(s: &str) -> Result<Mnemonic, Error> {
#[cfg(feature = "std")]
#[cfg(feature = "unicode-normalization")]
{
Mnemonic::parse(s)
}
#[cfg(not(feature = "std"))]
#[cfg(not(feature = "unicode-normalization"))]
{
Mnemonic::parse_normalized(s)
}
Expand Down Expand Up @@ -876,7 +872,7 @@ mod tests {
mnemonic_str
);

#[cfg(feature = "std")]
#[cfg(feature = "unicode-normalization")]
{
assert_eq!(&mnemonic.to_string(), mnemonic_str, "failed vector: {}", mnemonic_str);
assert_eq!(
Expand Down

0 comments on commit 6f6ec34

Please sign in to comment.