mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-11 21:49:26 +00:00
Smash out seed
This commit is contained in:
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -4862,6 +4862,17 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "monero-seed"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"curve25519-dalek",
|
||||||
|
"rand_core",
|
||||||
|
"std-shims",
|
||||||
|
"thiserror",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "monero-serai"
|
name = "monero-serai"
|
||||||
version = "0.1.4-alpha"
|
version = "0.1.4-alpha"
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ members = [
|
|||||||
"coins/monero/rpc",
|
"coins/monero/rpc",
|
||||||
"coins/monero/rpc/simple-request",
|
"coins/monero/rpc/simple-request",
|
||||||
"coins/monero/wallet",
|
"coins/monero/wallet",
|
||||||
|
"coins/monero/wallet/seed",
|
||||||
"coins/monero/wallet/polyseed",
|
"coins/monero/wallet/polyseed",
|
||||||
|
|
||||||
"message-queue",
|
"message-queue",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ name = "polyseed"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Rust implementation of Polyseed"
|
description = "Rust implementation of Polyseed"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/serai-dex/serai/tree/develop/coins/monero/wallet.polyseed"
|
repository = "https://github.com/serai-dex/serai/tree/develop/coins/monero/wallet/polyseed"
|
||||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.79"
|
rust-version = "1.79"
|
||||||
@@ -40,5 +40,4 @@ std = [
|
|||||||
"sha3/std",
|
"sha3/std",
|
||||||
"pbkdf2/std",
|
"pbkdf2/std",
|
||||||
]
|
]
|
||||||
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
|||||||
37
coins/monero/wallet/seed/Cargo.toml
Normal file
37
coins/monero/wallet/seed/Cargo.toml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[package]
|
||||||
|
name = "monero-seed"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Rust implementation of Monero's seed algorithm"
|
||||||
|
license = "MIT"
|
||||||
|
repository = "https://github.com/serai-dex/serai/tree/develop/coins/monero/wallet/seed"
|
||||||
|
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.79"
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
all-features = true
|
||||||
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
std-shims = { path = "../../../../common/std-shims", version = "^0.1.1", default-features = false }
|
||||||
|
|
||||||
|
thiserror = { version = "1", default-features = false, optional = true }
|
||||||
|
|
||||||
|
zeroize = { version = "^1.5", default-features = false, features = ["zeroize_derive"] }
|
||||||
|
rand_core = { version = "0.6", default-features = false }
|
||||||
|
|
||||||
|
curve25519-dalek = { version = "4", default-features = false, features = ["alloc", "zeroize"] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
std = [
|
||||||
|
"std-shims/std",
|
||||||
|
|
||||||
|
"thiserror",
|
||||||
|
|
||||||
|
"zeroize/std",
|
||||||
|
"rand_core/std",
|
||||||
|
]
|
||||||
|
default = ["std"]
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Monero Seeds
|
# Monero Seeds
|
||||||
|
|
||||||
A Rust implementation of Monero's seed algorithm.
|
Rust implementation of Monero's seed algorithm.
|
||||||
|
|
||||||
This library is usable under no-std when the `std` feature (on by default) is
|
This library is usable under no-std when the `std` feature (on by default) is
|
||||||
disabled.
|
disabled.
|
||||||
|
|||||||
@@ -11,26 +11,55 @@ use rand_core::{RngCore, CryptoRng};
|
|||||||
|
|
||||||
use curve25519_dalek::scalar::Scalar;
|
use curve25519_dalek::scalar::Scalar;
|
||||||
|
|
||||||
use crate::seed::SeedError;
|
const CLASSIC_SEED_LENGTH: usize = 24;
|
||||||
|
const CLASSIC_SEED_LENGTH_WITH_CHECKSUM: usize = 25;
|
||||||
|
|
||||||
pub(crate) const CLASSIC_SEED_LENGTH: usize = 24;
|
/// An error when working with a seed.
|
||||||
pub(crate) const CLASSIC_SEED_LENGTH_WITH_CHECKSUM: usize = 25;
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||||
|
pub enum SeedError {
|
||||||
|
/// The deprecated English language option was used with a checksum.
|
||||||
|
///
|
||||||
|
/// The deprecated English language option did not include a checksum.
|
||||||
|
#[cfg_attr(feature = "std", error("deprecated English language option included a checksum"))]
|
||||||
|
DeprecatedEnglishWithChecksum,
|
||||||
|
#[cfg_attr(feature = "std", error("invalid seed"))]
|
||||||
|
/// The seed was invalid.
|
||||||
|
InvalidSeed,
|
||||||
|
/// The checksum did not match the data.
|
||||||
|
#[cfg_attr(feature = "std", error("invalid checksum"))]
|
||||||
|
InvalidChecksum,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Language options.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Zeroize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Zeroize)]
|
||||||
pub enum Language {
|
pub enum Language {
|
||||||
|
/// Chinese language option.
|
||||||
Chinese,
|
Chinese,
|
||||||
|
/// English language option.
|
||||||
English,
|
English,
|
||||||
|
/// Dutch language option.
|
||||||
Dutch,
|
Dutch,
|
||||||
|
/// French language option.
|
||||||
French,
|
French,
|
||||||
|
/// Spanish language option.
|
||||||
Spanish,
|
Spanish,
|
||||||
|
/// German language option.
|
||||||
German,
|
German,
|
||||||
|
/// Italian language option.
|
||||||
Italian,
|
Italian,
|
||||||
|
/// Portuguese language option.
|
||||||
Portuguese,
|
Portuguese,
|
||||||
|
/// Japanese language option.
|
||||||
Japanese,
|
Japanese,
|
||||||
|
/// Russian language option.
|
||||||
Russian,
|
Russian,
|
||||||
|
/// Esperanto language option.
|
||||||
Esperanto,
|
Esperanto,
|
||||||
|
/// Lojban language option.
|
||||||
Lojban,
|
Lojban,
|
||||||
EnglishOld,
|
/// The original, and deprecated, English language.
|
||||||
|
DeprecatedEnglish,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trim(word: &str, len: usize) -> Zeroizing<String> {
|
fn trim(word: &str, len: usize) -> Zeroizing<String> {
|
||||||
@@ -38,14 +67,14 @@ fn trim(word: &str, len: usize) -> Zeroizing<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct WordList {
|
struct WordList {
|
||||||
word_list: Vec<&'static str>,
|
word_list: &'static [&'static str],
|
||||||
word_map: HashMap<&'static str, usize>,
|
word_map: HashMap<&'static str, usize>,
|
||||||
trimmed_word_map: HashMap<String, usize>,
|
trimmed_word_map: HashMap<String, usize>,
|
||||||
unique_prefix_length: usize,
|
unique_prefix_length: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WordList {
|
impl WordList {
|
||||||
fn new(word_list: Vec<&'static str>, prefix_length: usize) -> WordList {
|
fn new(word_list: &'static [&'static str], prefix_length: usize) -> WordList {
|
||||||
let mut lang = WordList {
|
let mut lang = WordList {
|
||||||
word_list,
|
word_list,
|
||||||
word_map: HashMap::new(),
|
word_map: HashMap::new(),
|
||||||
@@ -67,32 +96,23 @@ static LANGUAGES_CELL: OnceLock<HashMap<Language, WordList>> = OnceLock::new();
|
|||||||
fn LANGUAGES() -> &'static HashMap<Language, WordList> {
|
fn LANGUAGES() -> &'static HashMap<Language, WordList> {
|
||||||
LANGUAGES_CELL.get_or_init(|| {
|
LANGUAGES_CELL.get_or_init(|| {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(Language::Chinese, WordList::new(include!("./classic/zh.rs"), 1)),
|
(Language::Chinese, WordList::new(include!("./words/zh.rs"), 1)),
|
||||||
(Language::English, WordList::new(include!("./classic/en.rs"), 3)),
|
(Language::English, WordList::new(include!("./words/en.rs"), 3)),
|
||||||
(Language::Dutch, WordList::new(include!("./classic/nl.rs"), 4)),
|
(Language::Dutch, WordList::new(include!("./words/nl.rs"), 4)),
|
||||||
(Language::French, WordList::new(include!("./classic/fr.rs"), 4)),
|
(Language::French, WordList::new(include!("./words/fr.rs"), 4)),
|
||||||
(Language::Spanish, WordList::new(include!("./classic/es.rs"), 4)),
|
(Language::Spanish, WordList::new(include!("./words/es.rs"), 4)),
|
||||||
(Language::German, WordList::new(include!("./classic/de.rs"), 4)),
|
(Language::German, WordList::new(include!("./words/de.rs"), 4)),
|
||||||
(Language::Italian, WordList::new(include!("./classic/it.rs"), 4)),
|
(Language::Italian, WordList::new(include!("./words/it.rs"), 4)),
|
||||||
(Language::Portuguese, WordList::new(include!("./classic/pt.rs"), 4)),
|
(Language::Portuguese, WordList::new(include!("./words/pt.rs"), 4)),
|
||||||
(Language::Japanese, WordList::new(include!("./classic/ja.rs"), 3)),
|
(Language::Japanese, WordList::new(include!("./words/ja.rs"), 3)),
|
||||||
(Language::Russian, WordList::new(include!("./classic/ru.rs"), 4)),
|
(Language::Russian, WordList::new(include!("./words/ru.rs"), 4)),
|
||||||
(Language::Esperanto, WordList::new(include!("./classic/eo.rs"), 4)),
|
(Language::Esperanto, WordList::new(include!("./words/eo.rs"), 4)),
|
||||||
(Language::Lojban, WordList::new(include!("./classic/jbo.rs"), 4)),
|
(Language::Lojban, WordList::new(include!("./words/jbo.rs"), 4)),
|
||||||
(Language::EnglishOld, WordList::new(include!("./classic/ang.rs"), 4)),
|
(Language::DeprecatedEnglish, WordList::new(include!("./words/ang.rs"), 4)),
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
pub(crate) fn trim_by_lang(word: &str, lang: Language) -> String {
|
|
||||||
if lang != Language::EnglishOld {
|
|
||||||
word.chars().take(LANGUAGES()[&lang].unique_prefix_length).collect()
|
|
||||||
} else {
|
|
||||||
word.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn checksum_index(words: &[Zeroizing<String>], lang: &WordList) -> usize {
|
fn checksum_index(words: &[Zeroizing<String>], lang: &WordList) -> usize {
|
||||||
let mut trimmed_words = Zeroizing::new(String::new());
|
let mut trimmed_words = Zeroizing::new(String::new());
|
||||||
for w in words {
|
for w in words {
|
||||||
@@ -135,7 +155,7 @@ fn checksum_index(words: &[Zeroizing<String>], lang: &WordList) -> usize {
|
|||||||
|
|
||||||
// Convert a private key to a seed
|
// Convert a private key to a seed
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
fn key_to_seed(lang: Language, key: Zeroizing<Scalar>) -> ClassicSeed {
|
fn key_to_seed(lang: Language, key: Zeroizing<Scalar>) -> Seed {
|
||||||
let bytes = Zeroizing::new(key.to_bytes());
|
let bytes = Zeroizing::new(key.to_bytes());
|
||||||
|
|
||||||
// get the language words
|
// get the language words
|
||||||
@@ -172,7 +192,7 @@ fn key_to_seed(lang: Language, key: Zeroizing<Scalar>) -> ClassicSeed {
|
|||||||
indices.zeroize();
|
indices.zeroize();
|
||||||
|
|
||||||
// create a checksum word for all languages except old english
|
// create a checksum word for all languages except old english
|
||||||
if lang != Language::EnglishOld {
|
if lang != Language::DeprecatedEnglish {
|
||||||
let checksum = seed[checksum_index(&seed, &LANGUAGES()[&lang])].clone();
|
let checksum = seed[checksum_index(&seed, &LANGUAGES()[&lang])].clone();
|
||||||
seed.push(checksum);
|
seed.push(checksum);
|
||||||
}
|
}
|
||||||
@@ -184,11 +204,11 @@ fn key_to_seed(lang: Language, key: Zeroizing<Scalar>) -> ClassicSeed {
|
|||||||
}
|
}
|
||||||
*res += word;
|
*res += word;
|
||||||
}
|
}
|
||||||
ClassicSeed(lang, res)
|
Seed(lang, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a seed to bytes
|
// Convert a seed to bytes
|
||||||
pub(crate) fn seed_to_bytes(lang: Language, words: &str) -> Result<Zeroizing<[u8; 32]>, SeedError> {
|
fn seed_to_bytes(lang: Language, words: &str) -> Result<Zeroizing<[u8; 32]>, SeedError> {
|
||||||
// get seed words
|
// get seed words
|
||||||
let words = words.split_whitespace().map(|w| Zeroizing::new(w.to_string())).collect::<Vec<_>>();
|
let words = words.split_whitespace().map(|w| Zeroizing::new(w.to_string())).collect::<Vec<_>>();
|
||||||
if (words.len() != CLASSIC_SEED_LENGTH) && (words.len() != CLASSIC_SEED_LENGTH_WITH_CHECKSUM) {
|
if (words.len() != CLASSIC_SEED_LENGTH) && (words.len() != CLASSIC_SEED_LENGTH_WITH_CHECKSUM) {
|
||||||
@@ -196,8 +216,8 @@ pub(crate) fn seed_to_bytes(lang: Language, words: &str) -> Result<Zeroizing<[u8
|
|||||||
}
|
}
|
||||||
|
|
||||||
let has_checksum = words.len() == CLASSIC_SEED_LENGTH_WITH_CHECKSUM;
|
let has_checksum = words.len() == CLASSIC_SEED_LENGTH_WITH_CHECKSUM;
|
||||||
if has_checksum && lang == Language::EnglishOld {
|
if has_checksum && lang == Language::DeprecatedEnglish {
|
||||||
Err(SeedError::EnglishOldWithChecksum)?;
|
Err(SeedError::DeprecatedEnglishWithChecksum)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate words are in the language word list
|
// Validate words are in the language word list
|
||||||
@@ -272,15 +292,20 @@ pub(crate) fn seed_to_bytes(lang: Language, words: &str) -> Result<Zeroizing<[u8
|
|||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A Monero seed.
|
||||||
#[derive(Clone, PartialEq, Eq, Zeroize)]
|
#[derive(Clone, PartialEq, Eq, Zeroize)]
|
||||||
pub struct ClassicSeed(Language, Zeroizing<String>);
|
pub struct Seed(Language, Zeroizing<String>);
|
||||||
impl ClassicSeed {
|
impl Seed {
|
||||||
pub(crate) fn new<R: RngCore + CryptoRng>(rng: &mut R, lang: Language) -> ClassicSeed {
|
/// Create a new seed.
|
||||||
key_to_seed(lang, Zeroizing::new(Scalar::random(rng)))
|
pub fn new<R: RngCore + CryptoRng>(rng: &mut R, lang: Language) -> Seed {
|
||||||
|
let mut scalar_bytes = Zeroizing::new([0; 64]);
|
||||||
|
rng.fill_bytes(scalar_bytes.as_mut());
|
||||||
|
key_to_seed(lang, Zeroizing::new(Scalar::from_bytes_mod_order_wide(scalar_bytes.deref())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a seed from a string.
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn from_string(lang: Language, words: Zeroizing<String>) -> Result<ClassicSeed, SeedError> {
|
pub fn from_string(lang: Language, words: Zeroizing<String>) -> Result<Seed, SeedError> {
|
||||||
let entropy = seed_to_bytes(lang, &words)?;
|
let entropy = seed_to_bytes(lang, &words)?;
|
||||||
|
|
||||||
// Make sure this is a valid scalar
|
// Make sure this is a valid scalar
|
||||||
@@ -295,17 +320,20 @@ impl ClassicSeed {
|
|||||||
Ok(Self::from_entropy(lang, entropy).unwrap())
|
Ok(Self::from_entropy(lang, entropy).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a seed from entropy.
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn from_entropy(lang: Language, entropy: Zeroizing<[u8; 32]>) -> Option<ClassicSeed> {
|
pub fn from_entropy(lang: Language, entropy: Zeroizing<[u8; 32]>) -> Option<Seed> {
|
||||||
Option::from(Scalar::from_canonical_bytes(*entropy))
|
Option::from(Scalar::from_canonical_bytes(*entropy))
|
||||||
.map(|scalar| key_to_seed(lang, Zeroizing::new(scalar)))
|
.map(|scalar| key_to_seed(lang, Zeroizing::new(scalar)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_string(&self) -> Zeroizing<String> {
|
/// Convert a seed to a string.
|
||||||
|
pub fn to_string(&self) -> Zeroizing<String> {
|
||||||
self.1.clone()
|
self.1.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn entropy(&self) -> Zeroizing<[u8; 32]> {
|
/// Return the entropy underlying this seed.
|
||||||
|
pub fn entropy(&self) -> Zeroizing<[u8; 32]> {
|
||||||
seed_to_bytes(self.0, &self.1).unwrap()
|
seed_to_bytes(self.0, &self.1).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"like",
|
"like",
|
||||||
"just",
|
"just",
|
||||||
"love",
|
"love",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"Abakus",
|
"Abakus",
|
||||||
"Abart",
|
"Abart",
|
||||||
"abbilden",
|
"abbilden",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"abbey",
|
"abbey",
|
||||||
"abducts",
|
"abducts",
|
||||||
"ability",
|
"ability",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"abako",
|
"abako",
|
||||||
"abdiki",
|
"abdiki",
|
||||||
"abelo",
|
"abelo",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"ábaco",
|
"ábaco",
|
||||||
"abdomen",
|
"abdomen",
|
||||||
"abeja",
|
"abeja",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"abandon",
|
"abandon",
|
||||||
"abattre",
|
"abattre",
|
||||||
"aboi",
|
"aboi",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"abbinare",
|
"abbinare",
|
||||||
"abbonato",
|
"abbonato",
|
||||||
"abisso",
|
"abisso",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"あいこくしん",
|
"あいこくしん",
|
||||||
"あいさつ",
|
"あいさつ",
|
||||||
"あいだ",
|
"あいだ",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"backi",
|
"backi",
|
||||||
"bacru",
|
"bacru",
|
||||||
"badna",
|
"badna",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"aalglad",
|
"aalglad",
|
||||||
"aalscholver",
|
"aalscholver",
|
||||||
"aambeeld",
|
"aambeeld",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"abaular",
|
"abaular",
|
||||||
"abdominal",
|
"abdominal",
|
||||||
"abeto",
|
"abeto",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"абажур",
|
"абажур",
|
||||||
"абзац",
|
"абзац",
|
||||||
"абонент",
|
"абонент",
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
vec![
|
&[
|
||||||
"的",
|
"的",
|
||||||
"一",
|
"一",
|
||||||
"是",
|
"是",
|
||||||
@@ -4,7 +4,7 @@ use std_shims::string::String;
|
|||||||
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||||
use rand_core::{RngCore, CryptoRng};
|
use rand_core::{RngCore, CryptoRng};
|
||||||
|
|
||||||
pub(crate) mod classic;
|
pub(crate) use monero_seed as classic;
|
||||||
pub(crate) use polyseed;
|
pub(crate) use polyseed;
|
||||||
use classic::{CLASSIC_SEED_LENGTH, CLASSIC_SEED_LENGTH_WITH_CHECKSUM, ClassicSeed};
|
use classic::{CLASSIC_SEED_LENGTH, CLASSIC_SEED_LENGTH_WITH_CHECKSUM, ClassicSeed};
|
||||||
use polyseed::{POLYSEED_LENGTH, Polyseed};
|
use polyseed::{POLYSEED_LENGTH, Polyseed};
|
||||||
|
|||||||
@@ -6,11 +6,7 @@ use curve25519_dalek::scalar::Scalar;
|
|||||||
|
|
||||||
use monero_serai::primitives::keccak256;
|
use monero_serai::primitives::keccak256;
|
||||||
|
|
||||||
use crate::seed::{
|
use crate::seed::{Seed, SeedType, SeedError, classic, polyseed};
|
||||||
Seed, SeedType, SeedError,
|
|
||||||
classic::{self, trim_by_lang},
|
|
||||||
polyseed,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_classic_seed() {
|
fn test_classic_seed() {
|
||||||
@@ -186,6 +182,14 @@ fn test_classic_seed() {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for vector in vectors {
|
for vector in vectors {
|
||||||
|
fn trim_by_lang(word: &str, lang: Language) -> String {
|
||||||
|
if lang != Language::DeprecatedEnglish {
|
||||||
|
word.chars().take(LANGUAGES()[&lang].unique_prefix_length).collect()
|
||||||
|
} else {
|
||||||
|
word.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let trim_seed = |seed: &str| {
|
let trim_seed = |seed: &str| {
|
||||||
seed
|
seed
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
|
|||||||
@@ -43,4 +43,6 @@ monero-clsag = { path = "../../coins/monero/ringct/clsag", default-features = fa
|
|||||||
monero-bulletproofs = { path = "../../coins/monero/ringct/bulletproofs", default-features = false }
|
monero-bulletproofs = { path = "../../coins/monero/ringct/bulletproofs", default-features = false }
|
||||||
monero-serai = { path = "../../coins/monero", default-features = false }
|
monero-serai = { path = "../../coins/monero", default-features = false }
|
||||||
monero-rpc = { path = "../../coins/monero/rpc", default-features = false }
|
monero-rpc = { path = "../../coins/monero/rpc", default-features = false }
|
||||||
|
monero-seed = { path = "../../coins/monero/wallet/seed", default-features = false }
|
||||||
|
monero-polyseed = { path = "../../coins/monero/wallet/polyseed", default-features = false }
|
||||||
monero-wallet = { path = "../../coins/monero/wallet", default-features = false }
|
monero-wallet = { path = "../../coins/monero/wallet", default-features = false }
|
||||||
|
|||||||
Reference in New Issue
Block a user