Merge pull request #57 from michalkucharczyk/mku-unicode-normalization-in-no-std
`alloc` feature added, to gate unicode normalization
This commit is contained in:
commit
6f6ec34f2d
|
@ -13,8 +13,9 @@ edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "std" ]
|
default = [ "std" ]
|
||||||
std = [ "unicode-normalization", "serde/std" ]
|
std = [ "alloc", "serde/std", "unicode-normalization/std" ]
|
||||||
rand = [ "crate_rand", "rand_core" ]
|
rand = [ "crate_rand", "rand_core" ]
|
||||||
|
alloc = [ "unicode-normalization" ]
|
||||||
|
|
||||||
# Note: English is the standard for bip39 so always included
|
# Note: English is the standard for bip39 so always included
|
||||||
chinese-simplified = []
|
chinese-simplified = []
|
||||||
|
@ -49,7 +50,7 @@ zeroize = { version = "1.5", features = ["zeroize_derive"], optional = true }
|
||||||
|
|
||||||
# Unexported dependnecies
|
# Unexported dependnecies
|
||||||
bitcoin_hashes = { version = ">=0.12, <=0.13", default-features = false }
|
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]
|
[dev-dependencies]
|
||||||
# Enabling the "rand" feature by default to run the benches
|
# Enabling the "rand" feature by default to run the benches
|
||||||
|
|
38
src/lib.rs
38
src/lib.rs
|
@ -29,30 +29,31 @@
|
||||||
#[cfg(any(test, feature = "std"))]
|
#[cfg(any(test, feature = "std"))]
|
||||||
pub extern crate core;
|
pub extern crate core;
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
extern crate bitcoin_hashes;
|
extern crate bitcoin_hashes;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "unicode-normalization")]
|
||||||
extern crate unicode_normalization;
|
extern crate unicode_normalization;
|
||||||
|
|
||||||
#[cfg(feature = "rand_core")]
|
|
||||||
pub extern crate rand_core;
|
|
||||||
#[cfg(feature = "rand")]
|
#[cfg(feature = "rand")]
|
||||||
pub extern crate crate_rand as rand;
|
pub extern crate crate_rand as rand;
|
||||||
|
#[cfg(feature = "rand_core")]
|
||||||
|
pub extern crate rand_core;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
pub extern crate serde;
|
pub extern crate serde;
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
use alloc::{borrow::Cow, string::ToString, vec::Vec};
|
||||||
use core::{fmt, str};
|
use core::{fmt, str};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use std::borrow::Cow;
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::error;
|
use std::error;
|
||||||
|
|
||||||
use bitcoin_hashes::{sha256, Hash};
|
use bitcoin_hashes::{sha256, Hash};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "unicode-normalization")]
|
||||||
use unicode_normalization::UnicodeNormalization;
|
use unicode_normalization::UnicodeNormalization;
|
||||||
|
|
||||||
#[cfg(feature = "zeroize")]
|
#[cfg(feature = "zeroize")]
|
||||||
|
@ -95,7 +96,7 @@ impl AmbiguousLanguages {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vector of the possible languages.
|
/// Returns a vector of the possible languages.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "alloc")]
|
||||||
pub fn to_vec(&self) -> Vec<Language> {
|
pub fn to_vec(&self) -> Vec<Language> {
|
||||||
self.iter().collect()
|
self.iter().collect()
|
||||||
}
|
}
|
||||||
|
@ -183,7 +184,7 @@ impl Mnemonic {
|
||||||
/// Performing this on a [Cow] means that all allocations for normalization
|
/// Performing this on a [Cow] means that all allocations for normalization
|
||||||
/// can be avoided for languages without special UTF8 characters.
|
/// can be avoided for languages without special UTF8 characters.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "unicode-normalization")]
|
||||||
pub fn normalize_utf8_cow<'a>(cow: &mut Cow<'a, str>) {
|
pub fn normalize_utf8_cow<'a>(cow: &mut Cow<'a, str>) {
|
||||||
let is_nfkd = unicode_normalization::is_nfkd_quick(cow.as_ref().chars());
|
let is_nfkd = unicode_normalization::is_nfkd_quick(cow.as_ref().chars());
|
||||||
if is_nfkd != unicode_normalization::IsNormalized::Yes {
|
if is_nfkd != unicode_normalization::IsNormalized::Yes {
|
||||||
|
@ -506,7 +507,7 @@ impl Mnemonic {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a mnemonic in the given language.
|
/// Parse a mnemonic in the given language.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "unicode-normalization")]
|
||||||
pub fn parse_in<'a, S: Into<Cow<'a, str>>>(
|
pub fn parse_in<'a, S: Into<Cow<'a, str>>>(
|
||||||
language: Language,
|
language: Language,
|
||||||
s: S,
|
s: S,
|
||||||
|
@ -517,7 +518,7 @@ impl Mnemonic {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a mnemonic and detect the language from the enabled languages.
|
/// 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> {
|
pub fn parse<'a, S: Into<Cow<'a, str>>>(s: S) -> Result<Mnemonic, Error> {
|
||||||
let mut cow = s.into();
|
let mut cow = s.into();
|
||||||
Mnemonic::normalize_utf8_cow(&mut cow);
|
Mnemonic::normalize_utf8_cow(&mut cow);
|
||||||
|
@ -542,17 +543,12 @@ impl Mnemonic {
|
||||||
const PBKDF2_BYTES: usize = 64;
|
const PBKDF2_BYTES: usize = 64;
|
||||||
|
|
||||||
let mut seed = [0u8; PBKDF2_BYTES];
|
let mut seed = [0u8; PBKDF2_BYTES];
|
||||||
pbkdf2::pbkdf2(
|
pbkdf2::pbkdf2(self.words(), normalized_passphrase.as_bytes(), PBKDF2_ROUNDS, &mut seed);
|
||||||
self.words(),
|
|
||||||
normalized_passphrase.as_bytes(),
|
|
||||||
PBKDF2_ROUNDS,
|
|
||||||
&mut seed,
|
|
||||||
);
|
|
||||||
seed
|
seed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to seed bytes.
|
/// 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] {
|
pub fn to_seed<'a, P: Into<Cow<'a, str>>>(&self, passphrase: P) -> [u8; 64] {
|
||||||
let normalized_passphrase = {
|
let normalized_passphrase = {
|
||||||
let mut cow = passphrase.into();
|
let mut cow = passphrase.into();
|
||||||
|
@ -601,7 +597,7 @@ impl Mnemonic {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the mnemonic back to the entropy used to generate it.
|
/// Convert the mnemonic back to the entropy used to generate it.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "alloc")]
|
||||||
pub fn to_entropy(&self) -> Vec<u8> {
|
pub fn to_entropy(&self) -> Vec<u8> {
|
||||||
let (arr, len) = self.to_entropy_array();
|
let (arr, len) = self.to_entropy_array();
|
||||||
arr[0..len].to_vec()
|
arr[0..len].to_vec()
|
||||||
|
@ -653,11 +649,11 @@ impl str::FromStr for Mnemonic {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Mnemonic, Error> {
|
fn from_str(s: &str) -> Result<Mnemonic, Error> {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "unicode-normalization")]
|
||||||
{
|
{
|
||||||
Mnemonic::parse(s)
|
Mnemonic::parse(s)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "unicode-normalization"))]
|
||||||
{
|
{
|
||||||
Mnemonic::parse_normalized(s)
|
Mnemonic::parse_normalized(s)
|
||||||
}
|
}
|
||||||
|
@ -876,7 +872,7 @@ mod tests {
|
||||||
mnemonic_str
|
mnemonic_str
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "unicode-normalization")]
|
||||||
{
|
{
|
||||||
assert_eq!(&mnemonic.to_string(), mnemonic_str, "failed vector: {}", mnemonic_str);
|
assert_eq!(&mnemonic.to_string(), mnemonic_str, "failed vector: {}", mnemonic_str);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in New Issue