Project Path: pqbip39

Source Tree:

```txt
pqbip39
├── Cargo.toml
└── src
    ├── errors.rs
    ├── lib.rs
    ├── mnemonic.rs
    ├── pbkdf2.rs
    ├── rng.rs
    └── utils.rs

```

`pqbip39/Cargo.toml`:

```toml
[package]
name = "pqbip39"
version = "0.1.0"
edition = "2021"
authors = ["Rinat hicc0rus@gmail.com"]
description = "A no_std compatible implementation of the BIP39 mnemonic code standard."
license = "MIT"
repository = "https://github.com/openzebra/pq_bip39.rs"
readme = "README.md"
keywords = ["bip39", "mnemonic", "bitcoin", "crypto", "no-std"]
categories = ["cryptography", "no-std"]

[dependencies]
hmac = { version = "0.12.1", default-features = false }
sha2 = { version = "0.10.9", default-features = false }
thiserror = { version = "2.0.12", default-features = false }

unicode-normalization = { version = "0.1.24", default-features = false, optional = true }
zeroize = { version = "1.8.1", features = ["zeroize_derive"], default-features = false, optional = true }

[dev-dependencies]
hex = "0.4.3" 
rand = "0.9.1" 

[features]
default = ["std"]
std = ["unicode-normalization/std"]
zeroize = ["dep:zeroize"]

```

`pqbip39/src/errors.rs`:

```rs
use hmac::digest::InvalidLength;
use thiserror::Error;

#[derive(Debug, Error, PartialEq)]
pub enum Bip39Error {
    #[error("Invalid word count: {0}")]
    BadWordCount(usize),

    #[error("entropy was not between 128-256 bits or not a multiple of 32 bits: {0} bits")]
    BadEntropyBitCount(usize),

    #[error("mnemonic contains an unknown word (word {0})")]
    UnknownWord(usize),

    #[error("the mnemonic has an invalid checksum")]
    InvalidChecksum,

    #[error("HMAC key error: {0}")]
    HmacError(InvalidLength),
}

impl From<InvalidLength> for Bip39Error {
    fn from(error: InvalidLength) -> Self {
        Bip39Error::HmacError(error)
    }
}

```

`pqbip39/src/lib.rs`:

```rs
#![cfg_attr(not(feature = "std"), no_std)]

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

pub mod errors;
pub mod mnemonic;
pub mod pbkdf2;
pub mod rng;
pub mod utils;

```

`pqbip39/src/mnemonic.rs`:

```rs
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
use unicode_normalization::UnicodeNormalization;

use crate::{errors::Bip39Error, pbkdf2::pbkdf2, rng::Rng, utils::is_invalid_word_count};
use core::fmt;
use sha2::{Digest, Sha256};

pub const MIN_NB_WORDS: usize = 12;
pub const MAX_NB_WORDS: usize = 33;
pub const MAX_ENTROPY_BYTES: usize = 32;
pub const MAX_WORDS_DICT: usize = 2048;
pub const PBKDF2_ROUNDS: u32 = 2048;
pub const SEED_BYTE_LEN: usize = 64;

const EOF: u16 = u16::max_value();

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Mnemonic<'a> {
    lang_words: &'a [&'a str; MAX_WORDS_DICT],
    indicators: [u16; MAX_NB_WORDS],
    pub word_count: usize,
}

#[derive(Clone)]
pub struct MnemonicIter<'a, 'b> {
    mnemonic: &'b Mnemonic<'a>,
    position: usize,
}

#[derive(Clone)]
pub struct EntropyIter<'a> {
    mnemonic: &'a Mnemonic<'a>,
    word_idx: usize,
    bits: u32,
    bit_count: u32,
    bytes_produced: usize,
    bytes_to_produce: usize,
}

impl<'a> Iterator for EntropyIter<'a> {
    type Item = u8;

    fn next(&mut self) -> Option<Self::Item> {
        if self.bytes_produced >= self.bytes_to_produce {
            return None;
        }

        while self.bit_count < 8 {
            if self.word_idx >= self.mnemonic.word_count {
                return None;
            }

            let index = self.mnemonic.indicators[self.word_idx];

            self.bits = (self.bits << 11) | u32::from(index);
            self.bit_count += 11;
            self.word_idx += 1;
        }

        let shift = self.bit_count - 8;
        let byte = (self.bits >> shift) as u8;

        self.bit_count -= 8;
        self.bits &= (1 << self.bit_count) - 1;

        self.bytes_produced += 1;

        Some(byte)
    }
}

impl<'a, 'b> Iterator for MnemonicIter<'a, 'b> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        if self.position >= self.mnemonic.word_count {
            return None;
        }
        let word_index = self.mnemonic.indicators[self.position] as usize;
        self.position += 1;
        Some(self.mnemonic.lang_words[word_index])
    }
}

impl<'a> fmt::Display for Mnemonic<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for (i, word) in self.iter().enumerate() {
            if i > 0 {
                f.write_str(" ")?;
            }
            f.write_str(word)?;
        }
        Ok(())
    }
}

impl<'a> Mnemonic<'a> {
    pub fn from(dictionary: &'a [&'a str; MAX_WORDS_DICT]) -> Self {
        Self {
            lang_words: dictionary,
            indicators: [EOF; MAX_NB_WORDS],
            word_count: 0,
        }
    }

    pub fn iter<'b>(&'b self) -> MnemonicIter<'a, 'b> {
        MnemonicIter {
            mnemonic: self,
            position: 0,
        }
    }

    pub fn to_seed(&self, passphrase: &str) -> Result<[u8; SEED_BYTE_LEN], Bip39Error> {
        pbkdf2(self.iter(), passphrase.as_bytes(), PBKDF2_ROUNDS)
    }

    #[inline]
    #[cfg(feature = "unicode-normalization")]
    pub fn normalize_utf8_cow<'b>(cow: &mut Cow<'b, str>) {
        let is_nfkd = unicode_normalization::is_nfkd_quick(cow.as_ref().chars());
        if is_nfkd != unicode_normalization::IsNormalized::Yes {
            *cow = Cow::Owned(cow.as_ref().nfkd().to_string());
        }
    }

    pub fn parse_str(
        lang_words: &'a [&'a str; MAX_WORDS_DICT],
        s: &str,
    ) -> Result<Self, Bip39Error> {
        const MAX_TOTAL_BITS: usize = MAX_NB_WORDS * 11;
        const MAX_ENTROPY_BYTES_LOCAL: usize = 256 / 8;

        #[cfg(feature = "std")]
        let s_normalized = {
            let mut cow = s.into();
            Mnemonic::normalize_utf8_cow(&mut cow);
            cow
        };
        #[cfg(not(feature = "std"))]
        let s_normalized = s;

        let mut temp_words = [""; MAX_NB_WORDS + 1];
        let mut word_count = 0;
        for word in s_normalized.split_whitespace() {
            if word_count >= temp_words.len() {
                word_count += 1;
                break;
            }
            temp_words[word_count] = word;
            word_count += 1;
        }

        if is_invalid_word_count(word_count) {
            return Err(Bip39Error::BadWordCount(word_count));
        }

        let total_bits = word_count * 11;
        let checksum_len_bits = word_count / 3;
        let entropy_len_bits = total_bits - checksum_len_bits;
        let entropy_len_bytes = entropy_len_bits / 8;

        let mut indicators = [EOF; MAX_NB_WORDS];
        let mut bits = [false; MAX_TOTAL_BITS];

        for i in 0..word_count {
            let word_str = temp_words[i];
            match lang_words.iter().position(|&w| w == word_str) {
                Some(idx) => {
                    let idx_u16 = idx as u16;
                    indicators[i] = idx_u16;
                    for j in 0..11 {
                        bits[i * 11 + j] = (idx_u16 >> (10 - j)) & 1 == 1;
                    }
                }
                None => return Err(Bip39Error::UnknownWord(i)),
            }
        }

        let mut entropy = [0u8; MAX_ENTROPY_BYTES_LOCAL];
        for i in 0..entropy_len_bytes {
            for j in 0..8 {
                if bits[i * 8 + j] {
                    entropy[i] |= 1 << (7 - j);
                }
            }
        }

        let hash = Sha256::digest(&entropy[0..entropy_len_bytes]);
        let mnemonic_checksum_bits = &bits[entropy_len_bits..total_bits];

        for i in 0..checksum_len_bits {
            let expected_bit = (hash[i / 8] >> (7 - (i % 8))) & 1 == 1;
            if mnemonic_checksum_bits[i] != expected_bit {
                return Err(Bip39Error::InvalidChecksum);
            }
        }

        Ok(Mnemonic {
            lang_words,
            indicators,
            word_count,
        })
    }

    pub fn parse_str_without_checksum(
        lang_words: &'a [&'a str; MAX_WORDS_DICT],
        s: &str,
    ) -> Result<Self, Bip39Error> {
        #[cfg(feature = "std")]
        let s_normalized = {
            let mut cow = s.into();
            Mnemonic::normalize_utf8_cow(&mut cow);
            cow
        };
        #[cfg(not(feature = "std"))]
        let s_normalized = s;

        let mut temp_words = [""; MAX_NB_WORDS + 1];
        let mut word_count = 0;
        for word in s_normalized.split_whitespace() {
            if word_count >= temp_words.len() {
                word_count += 1;
                break;
            }
            temp_words[word_count] = word;
            word_count += 1;
        }

        if is_invalid_word_count(word_count) {
            return Err(Bip39Error::BadWordCount(word_count));
        }

        let mut indicators = [EOF; MAX_NB_WORDS];

        for i in 0..word_count {
            let word_str = temp_words[i];
            match lang_words.iter().position(|&w| w == word_str) {
                Some(idx) => {
                    indicators[i] = idx as u16;
                }
                None => return Err(Bip39Error::UnknownWord(i)),
            }
        }

        Ok(Mnemonic {
            lang_words,
            indicators,
            word_count,
        })
    }

    pub fn to_entropy(&'a self) -> EntropyIter<'a> {
        let entropy_bytes_len = (self.word_count / 3) * 4;
        EntropyIter {
            mnemonic: self,
            word_idx: 0,
            bits: 0,
            bit_count: 0,
            bytes_produced: 0,
            bytes_to_produce: entropy_bytes_len,
        }
    }

    pub fn from_entropy(
        lang_words: &'a [&'a str; MAX_WORDS_DICT],
        entropy: &[u8],
    ) -> Result<Self, Bip39Error> {
        const MAX_ENTROPY_BITS: usize = 256;
        const MIN_ENTROPY_BITS: usize = 128;
        const MAX_CHECKSUM_BITS: usize = 8;

        let nb_bytes = entropy.len();
        let nb_bits = nb_bytes * 8;

        if nb_bits % 32 != 0 {
            return Err(Bip39Error::BadEntropyBitCount(nb_bits));
        }
        if nb_bits < MIN_ENTROPY_BITS || nb_bits > MAX_ENTROPY_BITS {
            return Err(Bip39Error::BadEntropyBitCount(nb_bits));
        }

        let check = Sha256::digest(entropy);
        let cs_bits = nb_bits / 32;

        let mut bits = [false; MAX_ENTROPY_BITS + MAX_CHECKSUM_BITS];

        for i in 0..nb_bytes {
            for j in 0..8 {
                bits[i * 8 + j] = (entropy[i] & (1 << (7 - j))) != 0;
            }
        }

        for i in 0..cs_bits {
            bits[nb_bits + i] = (check[i / 8] & (1 << (7 - (i % 8)))) > 0;
        }

        let total_bits = nb_bits + cs_bits;
        let word_count = total_bits / 11;

        let mut indicators = [EOF; MAX_NB_WORDS];
        for i in 0..word_count {
            let mut idx = 0u16;
            for j in 0..11 {
                if bits[i * 11 + j] {
                    idx |= 1 << (10 - j);
                }
            }
            indicators[i] = idx;
        }

        Ok(Mnemonic {
            lang_words,
            indicators,
            word_count,
        })
    }

    pub fn generate<R: Rng>(
        rng: &mut R,
        lang_words: &'a [&'a str; MAX_WORDS_DICT],
        word_count: usize,
    ) -> Result<Self, Bip39Error> {
        if is_invalid_word_count(word_count) {
            return Err(Bip39Error::BadWordCount(word_count));
        }

        let entropy_bytes = (word_count / 3) * 4;
        let mut entropy = [0u8; (MAX_NB_WORDS / 3) * 4];

        Rng::fill_bytes(rng, &mut entropy[0..entropy_bytes]);

        Mnemonic::from_entropy(lang_words, &entropy[0..entropy_bytes])
    }

    pub fn checksum(&self) -> u8 {
        let last_word = self.indicators[self.word_count - 1];
        let mask = 0xFF >> (8 - self.word_count / 3);
        last_word as u8 & mask
    }
}

#[cfg(test)]
mod tests_mnemonic {
    use super::*;
    use hex;

    const JA_WORDS: [&str; 2048] = [
        "あいこくしん",
        "あいさつ",
        "あいだ",
        "あおぞら",
        "あかちゃん",
        "あきる",
        "あけがた",
        "あける",
        "あこがれる",
        "あさい",
        "あさひ",
        "あしあと",
        "あじわう",
        "あずかる",
        "あずき",
        "あそぶ",
        "あたえる",
        "あたためる",
        "あたりまえ",
        "あたる",
        "あつい",
        "あつかう",
        "あっしゅく",
        "あつまり",
        "あつめる",
        "あてな",
        "あてはまる",
        "あひる",
        "あぶら",
        "あぶる",
        "あふれる",
        "あまい",
        "あまど",
        "あまやかす",
        "あまり",
        "あみもの",
        "あめりか",
        "あやまる",
        "あゆむ",
        "あらいぐま",
        "あらし",
        "あらすじ",
        "あらためる",
        "あらゆる",
        "あらわす",
        "ありがとう",
        "あわせる",
        "あわてる",
        "あんい",
        "あんがい",
        "あんこ",
        "あんぜん",
        "あんてい",
        "あんない",
        "あんまり",
        "いいだす",
        "いおん",
        "いがい",
        "いがく",
        "いきおい",
        "いきなり",
        "いきもの",
        "いきる",
        "いくじ",
        "いくぶん",
        "いけばな",
        "いけん",
        "いこう",
        "いこく",
        "いこつ",
        "いさましい",
        "いさん",
        "いしき",
        "いじゅう",
        "いじょう",
        "いじわる",
        "いずみ",
        "いずれ",
        "いせい",
        "いせえび",
        "いせかい",
        "いせき",
        "いぜん",
        "いそうろう",
        "いそがしい",
        "いだい",
        "いだく",
        "いたずら",
        "いたみ",
        "いたりあ",
        "いちおう",
        "いちじ",
        "いちど",
        "いちば",
        "いちぶ",
        "いちりゅう",
        "いつか",
        "いっしゅん",
        "いっせい",
        "いっそう",
        "いったん",
        "いっち",
        "いってい",
        "いっぽう",
        "いてざ",
        "いてん",
        "いどう",
        "いとこ",
        "いない",
        "いなか",
        "いねむり",
        "いのち",
        "いのる",
        "いはつ",
        "いばる",
        "いはん",
        "いびき",
        "いひん",
        "いふく",
        "いへん",
        "いほう",
        "いみん",
        "いもうと",
        "いもたれ",
        "いもり",
        "いやがる",
        "いやす",
        "いよかん",
        "いよく",
        "いらい",
        "いらすと",
        "いりぐち",
        "いりょう",
        "いれい",
        "いれもの",
        "いれる",
        "いろえんぴつ",
        "いわい",
        "いわう",
        "いわかん",
        "いわば",
        "いわゆる",
        "いんげんまめ",
        "いんさつ",
        "いんしょう",
        "いんよう",
        "うえき",
        "うえる",
        "うおざ",
        "うがい",
        "うかぶ",
        "うかべる",
        "うきわ",
        "うくらいな",
        "うくれれ",
        "うけたまわる",
        "うけつけ",
        "うけとる",
        "うけもつ",
        "うける",
        "うごかす",
        "うごく",
        "うこん",
        "うさぎ",
        "うしなう",
        "うしろがみ",
        "うすい",
        "うすぎ",
        "うすぐらい",
        "うすめる",
        "うせつ",
        "うちあわせ",
        "うちがわ",
        "うちき",
        "うちゅう",
        "うっかり",
        "うつくしい",
        "うったえる",
        "うつる",
        "うどん",
        "うなぎ",
        "うなじ",
        "うなずく",
        "うなる",
        "うねる",
        "うのう",
        "うぶげ",
        "うぶごえ",
        "うまれる",
        "うめる",
        "うもう",
        "うやまう",
        "うよく",
        "うらがえす",
        "うらぐち",
        "うらない",
        "うりあげ",
        "うりきれ",
        "うるさい",
        "うれしい",
        "うれゆき",
        "うれる",
        "うろこ",
        "うわき",
        "うわさ",
        "うんこう",
        "うんちん",
        "うんてん",
        "うんどう",
        "えいえん",
        "えいが",
        "えいきょう",
        "えいご",
        "えいせい",
        "えいぶん",
        "えいよう",
        "えいわ",
        "えおり",
        "えがお",
        "えがく",
        "えきたい",
        "えくせる",
        "えしゃく",
        "えすて",
        "えつらん",
        "えのぐ",
        "えほうまき",
        "えほん",
        "えまき",
        "えもじ",
        "えもの",
        "えらい",
        "えらぶ",
        "えりあ",
        "えんえん",
        "えんかい",
        "えんぎ",
        "えんげき",
        "えんしゅう",
        "えんぜつ",
        "えんそく",
        "えんちょう",
        "えんとつ",
        "おいかける",
        "おいこす",
        "おいしい",
        "おいつく",
        "おうえん",
        "おうさま",
        "おうじ",
        "おうせつ",
        "おうたい",
        "おうふく",
        "おうべい",
        "おうよう",
        "おえる",
        "おおい",
        "おおう",
        "おおどおり",
        "おおや",
        "おおよそ",
        "おかえり",
        "おかず",
        "おがむ",
        "おかわり",
        "おぎなう",
        "おきる",
        "おくさま",
        "おくじょう",
        "おくりがな",
        "おくる",
        "おくれる",
        "おこす",
        "おこなう",
        "おこる",
        "おさえる",
        "おさない",
        "おさめる",
        "おしいれ",
        "おしえる",
        "おじぎ",
        "おじさん",
        "おしゃれ",
        "おそらく",
        "おそわる",
        "おたがい",
        "おたく",
        "おだやか",
        "おちつく",
        "おっと",
        "おつり",
        "おでかけ",
        "おとしもの",
        "おとなしい",
        "おどり",
        "おどろかす",
        "おばさん",
        "おまいり",
        "おめでとう",
        "おもいで",
        "おもう",
        "おもたい",
        "おもちゃ",
        "おやつ",
        "おやゆび",
        "およぼす",
        "おらんだ",
        "おろす",
        "おんがく",
        "おんけい",
        "おんしゃ",
        "おんせん",
        "おんだん",
        "おんちゅう",
        "おんどけい",
        "かあつ",
        "かいが",
        "がいき",
        "がいけん",
        "がいこう",
        "かいさつ",
        "かいしゃ",
        "かいすいよく",
        "かいぜん",
        "かいぞうど",
        "かいつう",
        "かいてん",
        "かいとう",
        "かいふく",
        "がいへき",
        "かいほう",
        "かいよう",
        "がいらい",
        "かいわ",
        "かえる",
        "かおり",
        "かかえる",
        "かがく",
        "かがし",
        "かがみ",
        "かくご",
        "かくとく",
        "かざる",
        "がぞう",
        "かたい",
        "かたち",
        "がちょう",
        "がっきゅう",
        "がっこう",
        "がっさん",
        "がっしょう",
        "かなざわし",
        "かのう",
        "がはく",
        "かぶか",
        "かほう",
        "かほご",
        "かまう",
        "かまぼこ",
        "かめれおん",
        "かゆい",
        "かようび",
        "からい",
        "かるい",
        "かろう",
        "かわく",
        "かわら",
        "がんか",
        "かんけい",
        "かんこう",
        "かんしゃ",
        "かんそう",
        "かんたん",
        "かんち",
        "がんばる",
        "きあい",
        "きあつ",
        "きいろ",
        "ぎいん",
        "きうい",
        "きうん",
        "きえる",
        "きおう",
        "きおく",
        "きおち",
        "きおん",
        "きかい",
        "きかく",
        "きかんしゃ",
        "ききて",
        "きくばり",
        "きくらげ",
        "きけんせい",
        "きこう",
        "きこえる",
        "きこく",
        "きさい",
        "きさく",
        "きさま",
        "きさらぎ",
        "ぎじかがく",
        "ぎしき",
        "ぎじたいけん",
        "ぎじにってい",
        "ぎじゅつしゃ",
        "きすう",
        "きせい",
        "きせき",
        "きせつ",
        "きそう",
        "きぞく",
        "きぞん",
        "きたえる",
        "きちょう",
        "きつえん",
        "ぎっちり",
        "きつつき",
        "きつね",
        "きてい",
        "きどう",
        "きどく",
        "きない",
        "きなが",
        "きなこ",
        "きぬごし",
        "きねん",
        "きのう",
        "きのした",
        "きはく",
        "きびしい",
        "きひん",
        "きふく",
        "きぶん",
        "きぼう",
        "きほん",
        "きまる",
        "きみつ",
        "きむずかしい",
        "きめる",
        "きもだめし",
        "きもち",
        "きもの",
        "きゃく",
        "きやく",
        "ぎゅうにく",
        "きよう",
        "きょうりゅう",
        "きらい",
        "きらく",
        "きりん",
        "きれい",
        "きれつ",
        "きろく",
        "ぎろん",
        "きわめる",
        "ぎんいろ",
        "きんかくじ",
        "きんじょ",
        "きんようび",
        "ぐあい",
        "くいず",
        "くうかん",
        "くうき",
        "くうぐん",
        "くうこう",
        "ぐうせい",
        "くうそう",
        "ぐうたら",
        "くうふく",
        "くうぼ",
        "くかん",
        "くきょう",
        "くげん",
        "ぐこう",
        "くさい",
        "くさき",
        "くさばな",
        "くさる",
        "くしゃみ",
        "くしょう",
        "くすのき",
        "くすりゆび",
        "くせげ",
        "くせん",
        "ぐたいてき",
        "くださる",
        "くたびれる",
        "くちこみ",
        "くちさき",
        "くつした",
        "ぐっすり",
        "くつろぐ",
        "くとうてん",
        "くどく",
        "くなん",
        "くねくね",
        "くのう",
        "くふう",
        "くみあわせ",
        "くみたてる",
        "くめる",
        "くやくしょ",
        "くらす",
        "くらべる",
        "くるま",
        "くれる",
        "くろう",
        "くわしい",
        "ぐんかん",
        "ぐんしょく",
        "ぐんたい",
        "ぐんて",
        "けあな",
        "けいかく",
        "けいけん",
        "けいこ",
        "けいさつ",
        "げいじゅつ",
        "けいたい",
        "げいのうじん",
        "けいれき",
        "けいろ",
        "けおとす",
        "けおりもの",
        "げきか",
        "げきげん",
        "げきだん",
        "げきちん",
        "げきとつ",
        "げきは",
        "げきやく",
        "げこう",
        "げこくじょう",
        "げざい",
        "けさき",
        "げざん",
        "けしき",
        "けしごむ",
        "けしょう",
        "げすと",
        "けたば",
        "けちゃっぷ",
        "けちらす",
        "けつあつ",
        "けつい",
        "けつえき",
        "けっこん",
        "けつじょ",
        "けっせき",
        "けってい",
        "けつまつ",
        "げつようび",
        "げつれい",
        "けつろん",
        "げどく",
        "けとばす",
        "けとる",
        "けなげ",
        "けなす",
        "けなみ",
        "けぬき",
        "げねつ",
        "けねん",
        "けはい",
        "げひん",
        "けぶかい",
        "げぼく",
        "けまり",
        "けみかる",
        "けむし",
        "けむり",
        "けもの",
        "けらい",
        "けろけろ",
        "けわしい",
        "けんい",
        "けんえつ",
        "けんお",
        "けんか",
        "げんき",
        "けんげん",
        "けんこう",
        "けんさく",
        "けんしゅう",
        "けんすう",
        "げんそう",
        "けんちく",
        "けんてい",
        "けんとう",
        "けんない",
        "けんにん",
        "げんぶつ",
        "けんま",
        "けんみん",
        "けんめい",
        "けんらん",
        "けんり",
        "こあくま",
        "こいぬ",
        "こいびと",
        "ごうい",
        "こうえん",
        "こうおん",
        "こうかん",
        "ごうきゅう",
        "ごうけい",
        "こうこう",
        "こうさい",
        "こうじ",
        "こうすい",
        "ごうせい",
        "こうそく",
        "こうたい",
        "こうちゃ",
        "こうつう",
        "こうてい",
        "こうどう",
        "こうない",
        "こうはい",
        "ごうほう",
        "ごうまん",
        "こうもく",
        "こうりつ",
        "こえる",
        "こおり",
        "ごかい",
        "ごがつ",
        "ごかん",
        "こくご",
        "こくさい",
        "こくとう",
        "こくない",
        "こくはく",
        "こぐま",
        "こけい",
        "こける",
        "ここのか",
        "こころ",
        "こさめ",
        "こしつ",
        "こすう",
        "こせい",
        "こせき",
        "こぜん",
        "こそだて",
        "こたい",
        "こたえる",
        "こたつ",
        "こちょう",
        "こっか",
        "こつこつ",
        "こつばん",
        "こつぶ",
        "こてい",
        "こてん",
        "ことがら",
        "ことし",
        "ことば",
        "ことり",
        "こなごな",
        "こねこね",
        "このまま",
        "このみ",
        "このよ",
        "ごはん",
        "こひつじ",
        "こふう",
        "こふん",
        "こぼれる",
        "ごまあぶら",
        "こまかい",
        "ごますり",
        "こまつな",
        "こまる",
        "こむぎこ",
        "こもじ",
        "こもち",
        "こもの",
        "こもん",
        "こやく",
        "こやま",
        "こゆう",
        "こゆび",
        "こよい",
        "こよう",
        "こりる",
        "これくしょん",
        "ころっけ",
        "こわもて",
        "こわれる",
        "こんいん",
        "こんかい",
        "こんき",
        "こんしゅう",
        "こんすい",
        "こんだて",
        "こんとん",
        "こんなん",
        "こんびに",
        "こんぽん",
        "こんまけ",
        "こんや",
        "こんれい",
        "こんわく",
        "ざいえき",
        "さいかい",
        "さいきん",
        "ざいげん",
        "ざいこ",
        "さいしょ",
        "さいせい",
        "ざいたく",
        "ざいちゅう",
        "さいてき",
        "ざいりょう",
        "さうな",
        "さかいし",
        "さがす",
        "さかな",
        "さかみち",
        "さがる",
        "さぎょう",
        "さくし",
        "さくひん",
        "さくら",
        "さこく",
        "さこつ",
        "さずかる",
        "ざせき",
        "さたん",
        "さつえい",
        "ざつおん",
        "ざっか",
        "ざつがく",
        "さっきょく",
        "ざっし",
        "さつじん",
        "ざっそう",
        "さつたば",
        "さつまいも",
        "さてい",
        "さといも",
        "さとう",
        "さとおや",
        "さとし",
        "さとる",
        "さのう",
        "さばく",
        "さびしい",
        "さべつ",
        "さほう",
        "さほど",
        "さます",
        "さみしい",
        "さみだれ",
        "さむけ",
        "さめる",
        "さやえんどう",
        "さゆう",
        "さよう",
        "さよく",
        "さらだ",
        "ざるそば",
        "さわやか",
        "さわる",
        "さんいん",
        "さんか",
        "さんきゃく",
        "さんこう",
        "さんさい",
        "ざんしょ",
        "さんすう",
        "さんせい",
        "さんそ",
        "さんち",
        "さんま",
        "さんみ",
        "さんらん",
        "しあい",
        "しあげ",
        "しあさって",
        "しあわせ",
        "しいく",
        "しいん",
        "しうち",
        "しえい",
        "しおけ",
        "しかい",
        "しかく",
        "じかん",
        "しごと",
        "しすう",
        "じだい",
        "したうけ",
        "したぎ",
        "したて",
        "したみ",
        "しちょう",
        "しちりん",
        "しっかり",
        "しつじ",
        "しつもん",
        "してい",
        "してき",
        "してつ",
        "じてん",
        "じどう",
        "しなぎれ",
        "しなもの",
        "しなん",
        "しねま",
        "しねん",
        "しのぐ",
        "しのぶ",
        "しはい",
        "しばかり",
        "しはつ",
        "しはらい",
        "しはん",
        "しひょう",
        "しふく",
        "じぶん",
        "しへい",
        "しほう",
        "しほん",
        "しまう",
        "しまる",
        "しみん",
        "しむける",
        "じむしょ",
        "しめい",
        "しめる",
        "しもん",
        "しゃいん",
        "しゃうん",
        "しゃおん",
        "じゃがいも",
        "しやくしょ",
        "しゃくほう",
        "しゃけん",
        "しゃこ",
        "しゃざい",
        "しゃしん",
        "しゃせん",
        "しゃそう",
        "しゃたい",
        "しゃちょう",
        "しゃっきん",
        "じゃま",
        "しゃりん",
        "しゃれい",
        "じゆう",
        "じゅうしょ",
        "しゅくはく",
        "じゅしん",
        "しゅっせき",
        "しゅみ",
        "しゅらば",
        "じゅんばん",
        "しょうかい",
        "しょくたく",
        "しょっけん",
        "しょどう",
        "しょもつ",
        "しらせる",
        "しらべる",
        "しんか",
        "しんこう",
        "じんじゃ",
        "しんせいじ",
        "しんちく",
        "しんりん",
        "すあげ",
        "すあし",
        "すあな",
        "ずあん",
        "すいえい",
        "すいか",
        "すいとう",
        "ずいぶん",
        "すいようび",
        "すうがく",
        "すうじつ",
        "すうせん",
        "すおどり",
        "すきま",
        "すくう",
        "すくない",
        "すける",
        "すごい",
        "すこし",
        "ずさん",
        "すずしい",
        "すすむ",
        "すすめる",
        "すっかり",
        "ずっしり",
        "ずっと",
        "すてき",
        "すてる",
        "すねる",
        "すのこ",
        "すはだ",
        "すばらしい",
        "ずひょう",
        "ずぶぬれ",
        "すぶり",
        "すふれ",
        "すべて",
        "すべる",
        "ずほう",
        "すぼん",
        "すまい",
        "すめし",
        "すもう",
        "すやき",
        "すらすら",
        "するめ",
        "すれちがう",
        "すろっと",
        "すわる",
        "すんぜん",
        "すんぽう",
        "せあぶら",
        "せいかつ",
        "せいげん",
        "せいじ",
        "せいよう",
        "せおう",
        "せかいかん",
        "せきにん",
        "せきむ",
        "せきゆ",
        "せきらんうん",
        "せけん",
        "せこう",
        "せすじ",
        "せたい",
        "せたけ",
        "せっかく",
        "せっきゃく",
        "ぜっく",
        "せっけん",
        "せっこつ",
        "せっさたくま",
        "せつぞく",
        "せつだん",
        "せつでん",
        "せっぱん",
        "せつび",
        "せつぶん",
        "せつめい",
        "せつりつ",
        "せなか",
        "せのび",
        "せはば",
        "せびろ",
        "せぼね",
        "せまい",
        "せまる",
        "せめる",
        "せもたれ",
        "せりふ",
        "ぜんあく",
        "せんい",
        "せんえい",
        "せんか",
        "せんきょ",
        "せんく",
        "せんげん",
        "ぜんご",
        "せんさい",
        "せんしゅ",
        "せんすい",
        "せんせい",
        "せんぞ",
        "せんたく",
        "せんちょう",
        "せんてい",
        "せんとう",
        "せんぬき",
        "せんねん",
        "せんぱい",
        "ぜんぶ",
        "ぜんぽう",
        "せんむ",
        "せんめんじょ",
        "せんもん",
        "せんやく",
        "せんゆう",
        "せんよう",
        "ぜんら",
        "ぜんりゃく",
        "せんれい",
        "せんろ",
        "そあく",
        "そいとげる",
        "そいね",
        "そうがんきょう",
        "そうき",
        "そうご",
        "そうしん",
        "そうだん",
        "そうなん",
        "そうび",
        "そうめん",
        "そうり",
        "そえもの",
        "そえん",
        "そがい",
        "そげき",
        "そこう",
        "そこそこ",
        "そざい",
        "そしな",
        "そせい",
        "そせん",
        "そそぐ",
        "そだてる",
        "そつう",
        "そつえん",
        "そっかん",
        "そつぎょう",
        "そっけつ",
        "そっこう",
        "そっせん",
        "そっと",
        "そとがわ",
        "そとづら",
        "そなえる",
        "そなた",
        "そふぼ",
        "そぼく",
        "そぼろ",
        "そまつ",
        "そまる",
        "そむく",
        "そむりえ",
        "そめる",
        "そもそも",
        "そよかぜ",
        "そらまめ",
        "そろう",
        "そんかい",
        "そんけい",
        "そんざい",
        "そんしつ",
        "そんぞく",
        "そんちょう",
        "ぞんび",
        "ぞんぶん",
        "そんみん",
        "たあい",
        "たいいん",
        "たいうん",
        "たいえき",
        "たいおう",
        "だいがく",
        "たいき",
        "たいぐう",
        "たいけん",
        "たいこ",
        "たいざい",
        "だいじょうぶ",
        "だいすき",
        "たいせつ",
        "たいそう",
        "だいたい",
        "たいちょう",
        "たいてい",
        "だいどころ",
        "たいない",
        "たいねつ",
        "たいのう",
        "たいはん",
        "だいひょう",
        "たいふう",
        "たいへん",
        "たいほ",
        "たいまつばな",
        "たいみんぐ",
        "たいむ",
        "たいめん",
        "たいやき",
        "たいよう",
        "たいら",
        "たいりょく",
        "たいる",
        "たいわん",
        "たうえ",
        "たえる",
        "たおす",
        "たおる",
        "たおれる",
        "たかい",
        "たかね",
        "たきび",
        "たくさん",
        "たこく",
        "たこやき",
        "たさい",
        "たしざん",
        "だじゃれ",
        "たすける",
        "たずさわる",
        "たそがれ",
        "たたかう",
        "たたく",
        "ただしい",
        "たたみ",
        "たちばな",
        "だっかい",
        "だっきゃく",
        "だっこ",
        "だっしゅつ",
        "だったい",
        "たてる",
        "たとえる",
        "たなばた",
        "たにん",
        "たぬき",
        "たのしみ",
        "たはつ",
        "たぶん",
        "たべる",
        "たぼう",
        "たまご",
        "たまる",
        "だむる",
        "ためいき",
        "ためす",
        "ためる",
        "たもつ",
        "たやすい",
        "たよる",
        "たらす",
        "たりきほんがん",
        "たりょう",
        "たりる",
        "たると",
        "たれる",
        "たれんと",
        "たろっと",
        "たわむれる",
        "だんあつ",
        "たんい",
        "たんおん",
        "たんか",
        "たんき",
        "たんけん",
        "たんご",
        "たんさん",
        "たんじょうび",
        "だんせい",
        "たんそく",
        "たんたい",
        "だんち",
        "たんてい",
        "たんとう",
        "だんな",
        "たんにん",
        "だんねつ",
        "たんのう",
        "たんぴん",
        "だんぼう",
        "たんまつ",
        "たんめい",
        "だんれつ",
        "だんろ",
        "だんわ",
        "ちあい",
        "ちあん",
        "ちいき",
        "ちいさい",
        "ちえん",
        "ちかい",
        "ちから",
        "ちきゅう",
        "ちきん",
        "ちけいず",
        "ちけん",
        "ちこく",
        "ちさい",
        "ちしき",
        "ちしりょう",
        "ちせい",
        "ちそう",
        "ちたい",
        "ちたん",
        "ちちおや",
        "ちつじょ",
        "ちてき",
        "ちてん",
        "ちぬき",
        "ちぬり",
        "ちのう",
        "ちひょう",
        "ちへいせん",
        "ちほう",
        "ちまた",
        "ちみつ",
        "ちみどろ",
        "ちめいど",
        "ちゃんこなべ",
        "ちゅうい",
        "ちゆりょく",
        "ちょうし",
        "ちょさくけん",
        "ちらし",
        "ちらみ",
        "ちりがみ",
        "ちりょう",
        "ちるど",
        "ちわわ",
        "ちんたい",
        "ちんもく",
        "ついか",
        "ついたち",
        "つうか",
        "つうじょう",
        "つうはん",
        "つうわ",
        "つかう",
        "つかれる",
        "つくね",
        "つくる",
        "つけね",
        "つける",
        "つごう",
        "つたえる",
        "つづく",
        "つつじ",
        "つつむ",
        "つとめる",
        "つながる",
        "つなみ",
        "つねづね",
        "つのる",
        "つぶす",
        "つまらない",
        "つまる",
        "つみき",
        "つめたい",
        "つもり",
        "つもる",
        "つよい",
        "つるぼ",
        "つるみく",
        "つわもの",
        "つわり",
        "てあし",
        "てあて",
        "てあみ",
        "ていおん",
        "ていか",
        "ていき",
        "ていけい",
        "ていこく",
        "ていさつ",
        "ていし",
        "ていせい",
        "ていたい",
        "ていど",
        "ていねい",
        "ていひょう",
        "ていへん",
        "ていぼう",
        "てうち",
        "ておくれ",
        "てきとう",
        "てくび",
        "でこぼこ",
        "てさぎょう",
        "てさげ",
        "てすり",
        "てそう",
        "てちがい",
        "てちょう",
        "てつがく",
        "てつづき",
        "でっぱ",
        "てつぼう",
        "てつや",
        "でぬかえ",
        "てぬき",
        "てぬぐい",
        "てのひら",
        "てはい",
        "てぶくろ",
        "てふだ",
        "てほどき",
        "てほん",
        "てまえ",
        "てまきずし",
        "てみじか",
        "てみやげ",
        "てらす",
        "てれび",
        "てわけ",
        "てわたし",
        "でんあつ",
        "てんいん",
        "てんかい",
        "てんき",
        "てんぐ",
        "てんけん",
        "てんごく",
        "てんさい",
        "てんし",
        "てんすう",
        "でんち",
        "てんてき",
        "てんとう",
        "てんない",
        "てんぷら",
        "てんぼうだい",
        "てんめつ",
        "てんらんかい",
        "でんりょく",
        "でんわ",
        "どあい",
        "といれ",
        "どうかん",
        "とうきゅう",
        "どうぐ",
        "とうし",
        "とうむぎ",
        "とおい",
        "とおか",
        "とおく",
        "とおす",
        "とおる",
        "とかい",
        "とかす",
        "ときおり",
        "ときどき",
        "とくい",
        "とくしゅう",
        "とくてん",
        "とくに",
        "とくべつ",
        "とけい",
        "とける",
        "とこや",
        "とさか",
        "としょかん",
        "とそう",
        "とたん",
        "とちゅう",
        "とっきゅう",
        "とっくん",
        "とつぜん",
        "とつにゅう",
        "とどける",
        "ととのえる",
        "とない",
        "となえる",
        "となり",
        "とのさま",
        "とばす",
        "どぶがわ",
        "とほう",
        "とまる",
        "とめる",
        "ともだち",
        "ともる",
        "どようび",
        "とらえる",
        "とんかつ",
        "どんぶり",
        "ないかく",
        "ないこう",
        "ないしょ",
        "ないす",
        "ないせん",
        "ないそう",
        "なおす",
        "ながい",
        "なくす",
        "なげる",
        "なこうど",
        "なさけ",
        "なたでここ",
        "なっとう",
        "なつやすみ",
        "ななおし",
        "なにごと",
        "なにもの",
        "なにわ",
        "なのか",
        "なふだ",
        "なまいき",
        "なまえ",
        "なまみ",
        "なみだ",
        "なめらか",
        "なめる",
        "なやむ",
        "ならう",
        "ならび",
        "ならぶ",
        "なれる",
        "なわとび",
        "なわばり",
        "にあう",
        "にいがた",
        "にうけ",
        "におい",
        "にかい",
        "にがて",
        "にきび",
        "にくしみ",
        "にくまん",
        "にげる",
        "にさんかたんそ",
        "にしき",
        "にせもの",
        "にちじょう",
        "にちようび",
        "にっか",
        "にっき",
        "にっけい",
        "にっこう",
        "にっさん",
        "にっしょく",
        "にっすう",
        "にっせき",
        "にってい",
        "になう",
        "にほん",
        "にまめ",
        "にもつ",
        "にやり",
        "にゅういん",
        "にりんしゃ",
        "にわとり",
        "にんい",
        "にんか",
        "にんき",
        "にんげん",
        "にんしき",
        "にんずう",
        "にんそう",
        "にんたい",
        "にんち",
        "にんてい",
        "にんにく",
        "にんぷ",
        "にんまり",
        "にんむ",
        "にんめい",
        "にんよう",
        "ぬいくぎ",
        "ぬかす",
        "ぬぐいとる",
        "ぬぐう",
        "ぬくもり",
        "ぬすむ",
        "ぬまえび",
        "ぬめり",
        "ぬらす",
        "ぬんちゃく",
        "ねあげ",
        "ねいき",
        "ねいる",
        "ねいろ",
        "ねぐせ",
        "ねくたい",
        "ねくら",
        "ねこぜ",
        "ねこむ",
        "ねさげ",
        "ねすごす",
        "ねそべる",
        "ねだん",
        "ねつい",
        "ねっしん",
        "ねつぞう",
        "ねったいぎょ",
        "ねぶそく",
        "ねふだ",
        "ねぼう",
        "ねほりはほり",
        "ねまき",
        "ねまわし",
        "ねみみ",
        "ねむい",
        "ねむたい",
        "ねもと",
        "ねらう",
        "ねわざ",
        "ねんいり",
        "ねんおし",
        "ねんかん",
        "ねんきん",
        "ねんぐ",
        "ねんざ",
        "ねんし",
        "ねんちゃく",
        "ねんど",
        "ねんぴ",
        "ねんぶつ",
        "ねんまつ",
        "ねんりょう",
        "ねんれい",
        "のいず",
        "のおづま",
        "のがす",
        "のきなみ",
        "のこぎり",
        "のこす",
        "のこる",
        "のせる",
        "のぞく",
        "のぞむ",
        "のたまう",
        "のちほど",
        "のっく",
        "のばす",
        "のはら",
        "のべる",
        "のぼる",
        "のみもの",
        "のやま",
        "のらいぬ",
        "のらねこ",
        "のりもの",
        "のりゆき",
        "のれん",
        "のんき",
        "ばあい",
        "はあく",
        "ばあさん",
        "ばいか",
        "ばいく",
        "はいけん",
        "はいご",
        "はいしん",
        "はいすい",
        "はいせん",
        "はいそう",
        "はいち",
        "ばいばい",
        "はいれつ",
        "はえる",
        "はおる",
        "はかい",
        "ばかり",
        "はかる",
        "はくしゅ",
        "はけん",
        "はこぶ",
        "はさみ",
        "はさん",
        "はしご",
        "ばしょ",
        "はしる",
        "はせる",
        "ぱそこん",
        "はそん",
        "はたん",
        "はちみつ",
        "はつおん",
        "はっかく",
        "はづき",
        "はっきり",
        "はっくつ",
        "はっけん",
        "はっこう",
        "はっさん",
        "はっしん",
        "はったつ",
        "はっちゅう",
        "はってん",
        "はっぴょう",
        "はっぽう",
        "はなす",
        "はなび",
        "はにかむ",
        "はぶらし",
        "はみがき",
        "はむかう",
        "はめつ",
        "はやい",
        "はやし",
        "はらう",
        "はろうぃん",
        "はわい",
        "はんい",
        "はんえい",
        "はんおん",
        "はんかく",
        "はんきょう",
        "ばんぐみ",
        "はんこ",
        "はんしゃ",
        "はんすう",
        "はんだん",
        "ぱんち",
        "ぱんつ",
        "はんてい",
        "はんとし",
        "はんのう",
        "はんぱ",
        "はんぶん",
        "はんぺん",
        "はんぼうき",
        "はんめい",
        "はんらん",
        "はんろん",
        "ひいき",
        "ひうん",
        "ひえる",
        "ひかく",
        "ひかり",
        "ひかる",
        "ひかん",
        "ひくい",
        "ひけつ",
        "ひこうき",
        "ひこく",
        "ひさい",
        "ひさしぶり",
        "ひさん",
        "びじゅつかん",
        "ひしょ",
        "ひそか",
        "ひそむ",
        "ひたむき",
        "ひだり",
        "ひたる",
        "ひつぎ",
        "ひっこし",
        "ひっし",
        "ひつじゅひん",
        "ひっす",
        "ひつぜん",
        "ぴったり",
        "ぴっちり",
        "ひつよう",
        "ひてい",
        "ひとごみ",
        "ひなまつり",
        "ひなん",
        "ひねる",
        "ひはん",
        "ひびく",
        "ひひょう",
        "ひほう",
        "ひまわり",
        "ひまん",
        "ひみつ",
        "ひめい",
        "ひめじし",
        "ひやけ",
        "ひやす",
        "ひよう",
        "びょうき",
        "ひらがな",
        "ひらく",
        "ひりつ",
        "ひりょう",
        "ひるま",
        "ひるやすみ",
        "ひれい",
        "ひろい",
        "ひろう",
        "ひろき",
        "ひろゆき",
        "ひんかく",
        "ひんけつ",
        "ひんこん",
        "ひんしゅ",
        "ひんそう",
        "ぴんち",
        "ひんぱん",
        "びんぼう",
        "ふあん",
        "ふいうち",
        "ふうけい",
        "ふうせん",
        "ぷうたろう",
        "ふうとう",
        "ふうふ",
        "ふえる",
        "ふおん",
        "ふかい",
        "ふきん",
        "ふくざつ",
        "ふくぶくろ",
        "ふこう",
        "ふさい",
        "ふしぎ",
        "ふじみ",
        "ふすま",
        "ふせい",
        "ふせぐ",
        "ふそく",
        "ぶたにく",
        "ふたん",
        "ふちょう",
        "ふつう",
        "ふつか",
        "ふっかつ",
        "ふっき",
        "ふっこく",
        "ぶどう",
        "ふとる",
        "ふとん",
        "ふのう",
        "ふはい",
        "ふひょう",
        "ふへん",
        "ふまん",
        "ふみん",
        "ふめつ",
        "ふめん",
        "ふよう",
        "ふりこ",
        "ふりる",
        "ふるい",
        "ふんいき",
        "ぶんがく",
        "ぶんぐ",
        "ふんしつ",
        "ぶんせき",
        "ふんそう",
        "ぶんぽう",
        "へいあん",
        "へいおん",
        "へいがい",
        "へいき",
        "へいげん",
        "へいこう",
        "へいさ",
        "へいしゃ",
        "へいせつ",
        "へいそ",
        "へいたく",
        "へいてん",
        "へいねつ",
        "へいわ",
        "へきが",
        "へこむ",
        "べにいろ",
        "べにしょうが",
        "へらす",
        "へんかん",
        "べんきょう",
        "べんごし",
        "へんさい",
        "へんたい",
        "べんり",
        "ほあん",
        "ほいく",
        "ぼうぎょ",
        "ほうこく",
        "ほうそう",
        "ほうほう",
        "ほうもん",
        "ほうりつ",
        "ほえる",
        "ほおん",
        "ほかん",
        "ほきょう",
        "ぼきん",
        "ほくろ",
        "ほけつ",
        "ほけん",
        "ほこう",
        "ほこる",
        "ほしい",
        "ほしつ",
        "ほしゅ",
        "ほしょう",
        "ほせい",
        "ほそい",
        "ほそく",
        "ほたて",
        "ほたる",
        "ぽちぶくろ",
        "ほっきょく",
        "ほっさ",
        "ほったん",
        "ほとんど",
        "ほめる",
        "ほんい",
        "ほんき",
        "ほんけ",
        "ほんしつ",
        "ほんやく",
        "まいにち",
        "まかい",
        "まかせる",
        "まがる",
        "まける",
        "まこと",
        "まさつ",
        "まじめ",
        "ますく",
        "まぜる",
        "まつり",
        "まとめ",
        "まなぶ",
        "まぬけ",
        "まねく",
        "まほう",
        "まもる",
        "まゆげ",
        "まよう",
        "まろやか",
        "まわす",
        "まわり",
        "まわる",
        "まんが",
        "まんきつ",
        "まんぞく",
        "まんなか",
        "みいら",
        "みうち",
        "みえる",
        "みがく",
        "みかた",
        "みかん",
        "みけん",
        "みこん",
        "みじかい",
        "みすい",
        "みすえる",
        "みせる",
        "みっか",
        "みつかる",
        "みつける",
        "みてい",
        "みとめる",
        "みなと",
        "みなみかさい",
        "みねらる",
        "みのう",
        "みのがす",
        "みほん",
        "みもと",
        "みやげ",
        "みらい",
        "みりょく",
        "みわく",
        "みんか",
        "みんぞく",
        "むいか",
        "むえき",
        "むえん",
        "むかい",
        "むかう",
        "むかえ",
        "むかし",
        "むぎちゃ",
        "むける",
        "むげん",
        "むさぼる",
        "むしあつい",
        "むしば",
        "むじゅん",
        "むしろ",
        "むすう",
        "むすこ",
        "むすぶ",
        "むすめ",
        "むせる",
        "むせん",
        "むちゅう",
        "むなしい",
        "むのう",
        "むやみ",
        "むよう",
        "むらさき",
        "むりょう",
        "むろん",
        "めいあん",
        "めいうん",
        "めいえん",
        "めいかく",
        "めいきょく",
        "めいさい",
        "めいし",
        "めいそう",
        "めいぶつ",
        "めいれい",
        "めいわく",
        "めぐまれる",
        "めざす",
        "めした",
        "めずらしい",
        "めだつ",
        "めまい",
        "めやす",
        "めんきょ",
        "めんせき",
        "めんどう",
        "もうしあげる",
        "もうどうけん",
        "もえる",
        "もくし",
        "もくてき",
        "もくようび",
        "もちろん",
        "もどる",
        "もらう",
        "もんく",
        "もんだい",
        "やおや",
        "やける",
        "やさい",
        "やさしい",
        "やすい",
        "やすたろう",
        "やすみ",
        "やせる",
        "やそう",
        "やたい",
        "やちん",
        "やっと",
        "やっぱり",
        "やぶる",
        "やめる",
        "ややこしい",
        "やよい",
        "やわらかい",
        "ゆうき",
        "ゆうびんきょく",
        "ゆうべ",
        "ゆうめい",
        "ゆけつ",
        "ゆしゅつ",
        "ゆせん",
        "ゆそう",
        "ゆたか",
        "ゆちゃく",
        "ゆでる",
        "ゆにゅう",
        "ゆびわ",
        "ゆらい",
        "ゆれる",
        "ようい",
        "ようか",
        "ようきゅう",
        "ようじ",
        "ようす",
        "ようちえん",
        "よかぜ",
        "よかん",
        "よきん",
        "よくせい",
        "よくぼう",
        "よけい",
        "よごれる",
        "よさん",
        "よしゅう",
        "よそう",
        "よそく",
        "よっか",
        "よてい",
        "よどがわく",
        "よねつ",
        "よやく",
        "よゆう",
        "よろこぶ",
        "よろしい",
        "らいう",
        "らくがき",
        "らくご",
        "らくさつ",
        "らくだ",
        "らしんばん",
        "らせん",
        "らぞく",
        "らたい",
        "らっか",
        "られつ",
        "りえき",
        "りかい",
        "りきさく",
        "りきせつ",
        "りくぐん",
        "りくつ",
        "りけん",
        "りこう",
        "りせい",
        "りそう",
        "りそく",
        "りてん",
        "りねん",
        "りゆう",
        "りゅうがく",
        "りよう",
        "りょうり",
        "りょかん",
        "りょくちゃ",
        "りょこう",
        "りりく",
        "りれき",
        "りろん",
        "りんご",
        "るいけい",
        "るいさい",
        "るいじ",
        "るいせき",
        "るすばん",
        "るりがわら",
        "れいかん",
        "れいぎ",
        "れいせい",
        "れいぞうこ",
        "れいとう",
        "れいぼう",
        "れきし",
        "れきだい",
        "れんあい",
        "れんけい",
        "れんこん",
        "れんさい",
        "れんしゅう",
        "れんぞく",
        "れんらく",
        "ろうか",
        "ろうご",
        "ろうじん",
        "ろうそく",
        "ろくが",
        "ろこつ",
        "ろじうら",
        "ろしゅつ",
        "ろせん",
        "ろてん",
        "ろめん",
        "ろれつ",
        "ろんぎ",
        "ろんぱ",
        "ろんぶん",
        "ろんり",
        "わかす",
        "わかめ",
        "わかやま",
        "わかれる",
        "わしつ",
        "わじまし",
        "わすれもの",
        "わらう",
        "われる",
    ];

    const EN_WORDS: [&str; 2048] = [
        "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract", "absurd",
        "abuse", "access", "accident", "account", "accuse", "achieve", "acid", "acoustic",
        "acquire", "across", "act", "action", "actor", "actress", "actual", "adapt", "add",
        "addict", "address", "adjust", "admit", "adult", "advance", "advice", "aerobic", "affair",
        "afford", "afraid", "again", "age", "agent", "agree", "ahead", "aim", "air", "airport",
        "aisle", "alarm", "album", "alcohol", "alert", "alien", "all", "alley", "allow", "almost",
        "alone", "alpha", "already", "also", "alter", "always", "amateur", "amazing", "among",
        "amount", "amused", "analyst", "anchor", "ancient", "anger", "angle", "angry", "animal",
        "ankle", "announce", "annual", "another", "answer", "antenna", "antique", "anxiety", "any",
        "apart", "apology", "appear", "apple", "approve", "april", "arch", "arctic", "area",
        "arena", "argue", "arm", "armed", "armor", "army", "around", "arrange", "arrest", "arrive",
        "arrow", "art", "artefact", "artist", "artwork", "ask", "aspect", "assault", "asset",
        "assist", "assume", "asthma", "athlete", "atom", "attack", "attend", "attitude", "attract",
        "auction", "audit", "august", "aunt", "author", "auto", "autumn", "average", "avocado",
        "avoid", "awake", "aware", "away", "awesome", "awful", "awkward", "axis", "baby",
        "bachelor", "bacon", "badge", "bag", "balance", "balcony", "ball", "bamboo", "banana",
        "banner", "bar", "barely", "bargain", "barrel", "base", "basic", "basket", "battle",
        "beach", "bean", "beauty", "because", "become", "beef", "before", "begin", "behave",
        "behind", "believe", "below", "belt", "bench", "benefit", "best", "betray", "better",
        "between", "beyond", "bicycle", "bid", "bike", "bind", "biology", "bird", "birth",
        "bitter", "black", "blade", "blame", "blanket", "blast", "bleak", "bless", "blind",
        "blood", "blossom", "blouse", "blue", "blur", "blush", "board", "boat", "body", "boil",
        "bomb", "bone", "bonus", "book", "boost", "border", "boring", "borrow", "boss", "bottom",
        "bounce", "box", "boy", "bracket", "brain", "brand", "brass", "brave", "bread", "breeze",
        "brick", "bridge", "brief", "bright", "bring", "brisk", "broccoli", "broken", "bronze",
        "broom", "brother", "brown", "brush", "bubble", "buddy", "budget", "buffalo", "build",
        "bulb", "bulk", "bullet", "bundle", "bunker", "burden", "burger", "burst", "bus",
        "business", "busy", "butter", "buyer", "buzz", "cabbage", "cabin", "cable", "cactus",
        "cage", "cake", "call", "calm", "camera", "camp", "can", "canal", "cancel", "candy",
        "cannon", "canoe", "canvas", "canyon", "capable", "capital", "captain", "car", "carbon",
        "card", "cargo", "carpet", "carry", "cart", "case", "cash", "casino", "castle", "casual",
        "cat", "catalog", "catch", "category", "cattle", "caught", "cause", "caution", "cave",
        "ceiling", "celery", "cement", "census", "century", "cereal", "certain", "chair", "chalk",
        "champion", "change", "chaos", "chapter", "charge", "chase", "chat", "cheap", "check",
        "cheese", "chef", "cherry", "chest", "chicken", "chief", "child", "chimney", "choice",
        "choose", "chronic", "chuckle", "chunk", "churn", "cigar", "cinnamon", "circle", "citizen",
        "city", "civil", "claim", "clap", "clarify", "claw", "clay", "clean", "clerk", "clever",
        "click", "client", "cliff", "climb", "clinic", "clip", "clock", "clog", "close", "cloth",
        "cloud", "clown", "club", "clump", "cluster", "clutch", "coach", "coast", "coconut",
        "code", "coffee", "coil", "coin", "collect", "color", "column", "combine", "come",
        "comfort", "comic", "common", "company", "concert", "conduct", "confirm", "congress",
        "connect", "consider", "control", "convince", "cook", "cool", "copper", "copy", "coral",
        "core", "corn", "correct", "cost", "cotton", "couch", "country", "couple", "course",
        "cousin", "cover", "coyote", "crack", "cradle", "craft", "cram", "crane", "crash",
        "crater", "crawl", "crazy", "cream", "credit", "creek", "crew", "cricket", "crime",
        "crisp", "critic", "crop", "cross", "crouch", "crowd", "crucial", "cruel", "cruise",
        "crumble", "crunch", "crush", "cry", "crystal", "cube", "culture", "cup", "cupboard",
        "curious", "current", "curtain", "curve", "cushion", "custom", "cute", "cycle", "dad",
        "damage", "damp", "dance", "danger", "daring", "dash", "daughter", "dawn", "day", "deal",
        "debate", "debris", "decade", "december", "decide", "decline", "decorate", "decrease",
        "deer", "defense", "define", "defy", "degree", "delay", "deliver", "demand", "demise",
        "denial", "dentist", "deny", "depart", "depend", "deposit", "depth", "deputy", "derive",
        "describe", "desert", "design", "desk", "despair", "destroy", "detail", "detect",
        "develop", "device", "devote", "diagram", "dial", "diamond", "diary", "dice", "diesel",
        "diet", "differ", "digital", "dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt",
        "disagree", "discover", "disease", "dish", "dismiss", "disorder", "display", "distance",
        "divert", "divide", "divorce", "dizzy", "doctor", "document", "dog", "doll", "dolphin",
        "domain", "donate", "donkey", "donor", "door", "dose", "double", "dove", "draft", "dragon",
        "drama", "drastic", "draw", "dream", "dress", "drift", "drill", "drink", "drip", "drive",
        "drop", "drum", "dry", "duck", "dumb", "dune", "during", "dust", "dutch", "duty", "dwarf",
        "dynamic", "eager", "eagle", "early", "earn", "earth", "easily", "east", "easy", "echo",
        "ecology", "economy", "edge", "edit", "educate", "effort", "egg", "eight", "either",
        "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator", "elite",
        "else", "embark", "embody", "embrace", "emerge", "emotion", "employ", "empower", "empty",
        "enable", "enact", "end", "endless", "endorse", "enemy", "energy", "enforce", "engage",
        "engine", "enhance", "enjoy", "enlist", "enough", "enrich", "enroll", "ensure", "enter",
        "entire", "entry", "envelope", "episode", "equal", "equip", "era", "erase", "erode",
        "erosion", "error", "erupt", "escape", "essay", "essence", "estate", "eternal", "ethics",
        "evidence", "evil", "evoke", "evolve", "exact", "example", "excess", "exchange", "excite",
        "exclude", "excuse", "execute", "exercise", "exhaust", "exhibit", "exile", "exist", "exit",
        "exotic", "expand", "expect", "expire", "explain", "expose", "express", "extend", "extra",
        "eye", "eyebrow", "fabric", "face", "faculty", "fade", "faint", "faith", "fall", "false",
        "fame", "family", "famous", "fan", "fancy", "fantasy", "farm", "fashion", "fat", "fatal",
        "father", "fatigue", "fault", "favorite", "feature", "february", "federal", "fee", "feed",
        "feel", "female", "fence", "festival", "fetch", "fever", "few", "fiber", "fiction",
        "field", "figure", "file", "film", "filter", "final", "find", "fine", "finger", "finish",
        "fire", "firm", "first", "fiscal", "fish", "fit", "fitness", "fix", "flag", "flame",
        "flash", "flat", "flavor", "flee", "flight", "flip", "float", "flock", "floor", "flower",
        "fluid", "flush", "fly", "foam", "focus", "fog", "foil", "fold", "follow", "food", "foot",
        "force", "forest", "forget", "fork", "fortune", "forum", "forward", "fossil", "foster",
        "found", "fox", "fragile", "frame", "frequent", "fresh", "friend", "fringe", "frog",
        "front", "frost", "frown", "frozen", "fruit", "fuel", "fun", "funny", "furnace", "fury",
        "future", "gadget", "gain", "galaxy", "gallery", "game", "gap", "garage", "garbage",
        "garden", "garlic", "garment", "gas", "gasp", "gate", "gather", "gauge", "gaze", "general",
        "genius", "genre", "gentle", "genuine", "gesture", "ghost", "giant", "gift", "giggle",
        "ginger", "giraffe", "girl", "give", "glad", "glance", "glare", "glass", "glide",
        "glimpse", "globe", "gloom", "glory", "glove", "glow", "glue", "goat", "goddess", "gold",
        "good", "goose", "gorilla", "gospel", "gossip", "govern", "gown", "grab", "grace", "grain",
        "grant", "grape", "grass", "gravity", "great", "green", "grid", "grief", "grit", "grocery",
        "group", "grow", "grunt", "guard", "guess", "guide", "guilt", "guitar", "gun", "gym",
        "habit", "hair", "half", "hammer", "hamster", "hand", "happy", "harbor", "hard", "harsh",
        "harvest", "hat", "have", "hawk", "hazard", "head", "health", "heart", "heavy", "hedgehog",
        "height", "hello", "helmet", "help", "hen", "hero", "hidden", "high", "hill", "hint",
        "hip", "hire", "history", "hobby", "hockey", "hold", "hole", "holiday", "hollow", "home",
        "honey", "hood", "hope", "horn", "horror", "horse", "hospital", "host", "hotel", "hour",
        "hover", "hub", "huge", "human", "humble", "humor", "hundred", "hungry", "hunt", "hurdle",
        "hurry", "hurt", "husband", "hybrid", "ice", "icon", "idea", "identify", "idle", "ignore",
        "ill", "illegal", "illness", "image", "imitate", "immense", "immune", "impact", "impose",
        "improve", "impulse", "inch", "include", "income", "increase", "index", "indicate",
        "indoor", "industry", "infant", "inflict", "inform", "inhale", "inherit", "initial",
        "inject", "injury", "inmate", "inner", "innocent", "input", "inquiry", "insane", "insect",
        "inside", "inspire", "install", "intact", "interest", "into", "invest", "invite",
        "involve", "iron", "island", "isolate", "issue", "item", "ivory", "jacket", "jaguar",
        "jar", "jazz", "jealous", "jeans", "jelly", "jewel", "job", "join", "joke", "journey",
        "joy", "judge", "juice", "jump", "jungle", "junior", "junk", "just", "kangaroo", "keen",
        "keep", "ketchup", "key", "kick", "kid", "kidney", "kind", "kingdom", "kiss", "kit",
        "kitchen", "kite", "kitten", "kiwi", "knee", "knife", "knock", "know", "lab", "label",
        "labor", "ladder", "lady", "lake", "lamp", "language", "laptop", "large", "later", "latin",
        "laugh", "laundry", "lava", "law", "lawn", "lawsuit", "layer", "lazy", "leader", "leaf",
        "learn", "leave", "lecture", "left", "leg", "legal", "legend", "leisure", "lemon", "lend",
        "length", "lens", "leopard", "lesson", "letter", "level", "liar", "liberty", "library",
        "license", "life", "lift", "light", "like", "limb", "limit", "link", "lion", "liquid",
        "list", "little", "live", "lizard", "load", "loan", "lobster", "local", "lock", "logic",
        "lonely", "long", "loop", "lottery", "loud", "lounge", "love", "loyal", "lucky", "luggage",
        "lumber", "lunar", "lunch", "luxury", "lyrics", "machine", "mad", "magic", "magnet",
        "maid", "mail", "main", "major", "make", "mammal", "man", "manage", "mandate", "mango",
        "mansion", "manual", "maple", "marble", "march", "margin", "marine", "market", "marriage",
        "mask", "mass", "master", "match", "material", "math", "matrix", "matter", "maximum",
        "maze", "meadow", "mean", "measure", "meat", "mechanic", "medal", "media", "melody",
        "melt", "member", "memory", "mention", "menu", "mercy", "merge", "merit", "merry", "mesh",
        "message", "metal", "method", "middle", "midnight", "milk", "million", "mimic", "mind",
        "minimum", "minor", "minute", "miracle", "mirror", "misery", "miss", "mistake", "mix",
        "mixed", "mixture", "mobile", "model", "modify", "mom", "moment", "monitor", "monkey",
        "monster", "month", "moon", "moral", "more", "morning", "mosquito", "mother", "motion",
        "motor", "mountain", "mouse", "move", "movie", "much", "muffin", "mule", "multiply",
        "muscle", "museum", "mushroom", "music", "must", "mutual", "myself", "mystery", "myth",
        "naive", "name", "napkin", "narrow", "nasty", "nation", "nature", "near", "neck", "need",
        "negative", "neglect", "neither", "nephew", "nerve", "nest", "net", "network", "neutral",
        "never", "news", "next", "nice", "night", "noble", "noise", "nominee", "noodle", "normal",
        "north", "nose", "notable", "note", "nothing", "notice", "novel", "now", "nuclear",
        "number", "nurse", "nut", "oak", "obey", "object", "oblige", "obscure", "observe",
        "obtain", "obvious", "occur", "ocean", "october", "odor", "off", "offer", "office",
        "often", "oil", "okay", "old", "olive", "olympic", "omit", "once", "one", "onion",
        "online", "only", "open", "opera", "opinion", "oppose", "option", "orange", "orbit",
        "orchard", "order", "ordinary", "organ", "orient", "original", "orphan", "ostrich",
        "other", "outdoor", "outer", "output", "outside", "oval", "oven", "over", "own", "owner",
        "oxygen", "oyster", "ozone", "pact", "paddle", "page", "pair", "palace", "palm", "panda",
        "panel", "panic", "panther", "paper", "parade", "parent", "park", "parrot", "party",
        "pass", "patch", "path", "patient", "patrol", "pattern", "pause", "pave", "payment",
        "peace", "peanut", "pear", "peasant", "pelican", "pen", "penalty", "pencil", "people",
        "pepper", "perfect", "permit", "person", "pet", "phone", "photo", "phrase", "physical",
        "piano", "picnic", "picture", "piece", "pig", "pigeon", "pill", "pilot", "pink", "pioneer",
        "pipe", "pistol", "pitch", "pizza", "place", "planet", "plastic", "plate", "play",
        "please", "pledge", "pluck", "plug", "plunge", "poem", "poet", "point", "polar", "pole",
        "police", "pond", "pony", "pool", "popular", "portion", "position", "possible", "post",
        "potato", "pottery", "poverty", "powder", "power", "practice", "praise", "predict",
        "prefer", "prepare", "present", "pretty", "prevent", "price", "pride", "primary", "print",
        "priority", "prison", "private", "prize", "problem", "process", "produce", "profit",
        "program", "project", "promote", "proof", "property", "prosper", "protect", "proud",
        "provide", "public", "pudding", "pull", "pulp", "pulse", "pumpkin", "punch", "pupil",
        "puppy", "purchase", "purity", "purpose", "purse", "push", "put", "puzzle", "pyramid",
        "quality", "quantum", "quarter", "question", "quick", "quit", "quiz", "quote", "rabbit",
        "raccoon", "race", "rack", "radar", "radio", "rail", "rain", "raise", "rally", "ramp",
        "ranch", "random", "range", "rapid", "rare", "rate", "rather", "raven", "raw", "razor",
        "ready", "real", "reason", "rebel", "rebuild", "recall", "receive", "recipe", "record",
        "recycle", "reduce", "reflect", "reform", "refuse", "region", "regret", "regular",
        "reject", "relax", "release", "relief", "rely", "remain", "remember", "remind", "remove",
        "render", "renew", "rent", "reopen", "repair", "repeat", "replace", "report", "require",
        "rescue", "resemble", "resist", "resource", "response", "result", "retire", "retreat",
        "return", "reunion", "reveal", "review", "reward", "rhythm", "rib", "ribbon", "rice",
        "rich", "ride", "ridge", "rifle", "right", "rigid", "ring", "riot", "ripple", "risk",
        "ritual", "rival", "river", "road", "roast", "robot", "robust", "rocket", "romance",
        "roof", "rookie", "room", "rose", "rotate", "rough", "round", "route", "royal", "rubber",
        "rude", "rug", "rule", "run", "runway", "rural", "sad", "saddle", "sadness", "safe",
        "sail", "salad", "salmon", "salon", "salt", "salute", "same", "sample", "sand", "satisfy",
        "satoshi", "sauce", "sausage", "save", "say", "scale", "scan", "scare", "scatter", "scene",
        "scheme", "school", "science", "scissors", "scorpion", "scout", "scrap", "screen",
        "script", "scrub", "sea", "search", "season", "seat", "second", "secret", "section",
        "security", "seed", "seek", "segment", "select", "sell", "seminar", "senior", "sense",
        "sentence", "series", "service", "session", "settle", "setup", "seven", "shadow", "shaft",
        "shallow", "share", "shed", "shell", "sheriff", "shield", "shift", "shine", "ship",
        "shiver", "shock", "shoe", "shoot", "shop", "short", "shoulder", "shove", "shrimp",
        "shrug", "shuffle", "shy", "sibling", "sick", "side", "siege", "sight", "sign", "silent",
        "silk", "silly", "silver", "similar", "simple", "since", "sing", "siren", "sister",
        "situate", "six", "size", "skate", "sketch", "ski", "skill", "skin", "skirt", "skull",
        "slab", "slam", "sleep", "slender", "slice", "slide", "slight", "slim", "slogan", "slot",
        "slow", "slush", "small", "smart", "smile", "smoke", "smooth", "snack", "snake", "snap",
        "sniff", "snow", "soap", "soccer", "social", "sock", "soda", "soft", "solar", "soldier",
        "solid", "solution", "solve", "someone", "song", "soon", "sorry", "sort", "soul", "sound",
        "soup", "source", "south", "space", "spare", "spatial", "spawn", "speak", "special",
        "speed", "spell", "spend", "sphere", "spice", "spider", "spike", "spin", "spirit", "split",
        "spoil", "sponsor", "spoon", "sport", "spot", "spray", "spread", "spring", "spy", "square",
        "squeeze", "squirrel", "stable", "stadium", "staff", "stage", "stairs", "stamp", "stand",
        "start", "state", "stay", "steak", "steel", "stem", "step", "stereo", "stick", "still",
        "sting", "stock", "stomach", "stone", "stool", "story", "stove", "strategy", "street",
        "strike", "strong", "struggle", "student", "stuff", "stumble", "style", "subject",
        "submit", "subway", "success", "such", "sudden", "suffer", "sugar", "suggest", "suit",
        "summer", "sun", "sunny", "sunset", "super", "supply", "supreme", "sure", "surface",
        "surge", "surprise", "surround", "survey", "suspect", "sustain", "swallow", "swamp",
        "swap", "swarm", "swear", "sweet", "swift", "swim", "swing", "switch", "sword", "symbol",
        "symptom", "syrup", "system", "table", "tackle", "tag", "tail", "talent", "talk", "tank",
        "tape", "target", "task", "taste", "tattoo", "taxi", "teach", "team", "tell", "ten",
        "tenant", "tennis", "tent", "term", "test", "text", "thank", "that", "theme", "then",
        "theory", "there", "they", "thing", "this", "thought", "three", "thrive", "throw", "thumb",
        "thunder", "ticket", "tide", "tiger", "tilt", "timber", "time", "tiny", "tip", "tired",
        "tissue", "title", "toast", "tobacco", "today", "toddler", "toe", "together", "toilet",
        "token", "tomato", "tomorrow", "tone", "tongue", "tonight", "tool", "tooth", "top",
        "topic", "topple", "torch", "tornado", "tortoise", "toss", "total", "tourist", "toward",
        "tower", "town", "toy", "track", "trade", "traffic", "tragic", "train", "transfer", "trap",
        "trash", "travel", "tray", "treat", "tree", "trend", "trial", "tribe", "trick", "trigger",
        "trim", "trip", "trophy", "trouble", "truck", "true", "truly", "trumpet", "trust", "truth",
        "try", "tube", "tuition", "tumble", "tuna", "tunnel", "turkey", "turn", "turtle", "twelve",
        "twenty", "twice", "twin", "twist", "two", "type", "typical", "ugly", "umbrella", "unable",
        "unaware", "uncle", "uncover", "under", "undo", "unfair", "unfold", "unhappy", "uniform",
        "unique", "unit", "universe", "unknown", "unlock", "until", "unusual", "unveil", "update",
        "upgrade", "uphold", "upon", "upper", "upset", "urban", "urge", "usage", "use", "used",
        "useful", "useless", "usual", "utility", "vacant", "vacuum", "vague", "valid", "valley",
        "valve", "van", "vanish", "vapor", "various", "vast", "vault", "vehicle", "velvet",
        "vendor", "venture", "venue", "verb", "verify", "version", "very", "vessel", "veteran",
        "viable", "vibrant", "vicious", "victory", "video", "view", "village", "vintage", "violin",
        "virtual", "virus", "visa", "visit", "visual", "vital", "vivid", "vocal", "voice", "void",
        "volcano", "volume", "vote", "voyage", "wage", "wagon", "wait", "walk", "wall", "walnut",
        "want", "warfare", "warm", "warrior", "wash", "wasp", "waste", "water", "wave", "way",
        "wealth", "weapon", "wear", "weasel", "weather", "web", "wedding", "weekend", "weird",
        "welcome", "west", "wet", "whale", "what", "wheat", "wheel", "when", "where", "whip",
        "whisper", "wide", "width", "wife", "wild", "will", "win", "window", "wine", "wing",
        "wink", "winner", "winter", "wire", "wisdom", "wise", "wish", "witness", "wolf", "woman",
        "wonder", "wood", "wool", "word", "work", "world", "worry", "worth", "wrap", "wreck",
        "wrestle", "wrist", "write", "wrong", "yard", "year", "yellow", "you", "young", "youth",
        "zebra", "zero", "zone", "zoo",
    ];

    #[test]
    fn test_from_entropy_valid_128_bits() {
        let entropy = [0u8; 16];
        let mnemonic = Mnemonic::from_entropy(&EN_WORDS, &entropy).unwrap();

        assert_eq!(mnemonic.word_count, 12);

        let expected_words = [
            "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon", "abandon",
            "abandon", "abandon", "abandon", "about",
        ];

        let mut mnemonic_iter = mnemonic.iter();
        let mut expected_iter = expected_words.iter();

        for _ in 0..expected_words.len() {
            assert_eq!(mnemonic_iter.next(), expected_iter.next().copied());
        }

        assert_eq!(mnemonic_iter.next(), None);
        assert_eq!(expected_iter.next(), None);
    }

    #[test]
    fn test_from_entropy_valid_256_bits() {
        let entropy = [0u8; 32];
        let mnemonic = Mnemonic::from_entropy(&EN_WORDS, &entropy).unwrap();
        assert_eq!(mnemonic.word_count, 24);
    }

    #[test]
    fn test_from_entropy_invalid_length() {
        let entropy = [0u8; 17];
        let result = Mnemonic::from_entropy(&EN_WORDS, &entropy);
        assert_eq!(result, Err(Bip39Error::BadEntropyBitCount(136)));
    }

    #[test]
    fn test_from_entropy_too_short() {
        let entropy = [0u8; 4];
        let result = Mnemonic::from_entropy(&EN_WORDS, &entropy);
        assert_eq!(result, Err(Bip39Error::BadEntropyBitCount(32)));
    }

    #[test]
    fn test_from_entropy_too_long() {
        let entropy = [0u8; 36];
        let result = Mnemonic::from_entropy(&EN_WORDS, &entropy);
        assert_eq!(result, Err(Bip39Error::BadEntropyBitCount(288)));
    }

    #[test]
    fn test_checksum() {
        let vectors = [
            "00000000000000000000000000000000",
            "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
            "80808080808080808080808080808080",
            "ffffffffffffffffffffffffffffffff",
            "000000000000000000000000000000000000000000000000",
            "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
            "808080808080808080808080808080808080808080808080",
            "ffffffffffffffffffffffffffffffffffffffffffffffff",
            "0000000000000000000000000000000000000000000000000000000000000000",
            "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
            "8080808080808080808080808080808080808080808080808080808080808080",
            "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
            "9e885d952ad362caeb4efe34a8e91bd2",
            "6610b25967cdcca9d59875f5cb50b0ea75433311869e930b",
            "68a79eaca2324873eacc50cb9c6eca8cc68ea5d936f98787c60c7ebc74e6ce7c",
            "c0ba5a8e914111210f2bd131f3d5e08d",
            "6d9be1ee6ebd27a258115aad99b7317b9c8d28b6d76431c3",
            "9f6a2878b2520799a44ef18bc7df394e7061a224d2c33cd015b157d746869863",
            "23db8160a31d3e0dca3688ed941adbf3",
            "8197a4a47f0425faeaa69deebc05ca29c0a5b5cc76ceacc0",
            "066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad",
            "f30f8c1da665478f49b001d94c5fc452",
            "c10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05",
            "f585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f",
            "ed3b83f0d7913a19667a1cfd7298cd57",
            "70639a4e81b151277b345476d169a3743ff3c141",
            "ba2520298b92063a7a0ee1d453ba92513af81d4f86e1d336",
            "9447d2cf44349cd88a58f5b4ff6f83b9a2d54c42f033e12b8e4d00cc",
            "38711e550dc6557df8082b2a87f7860ebbe47ea5867a7068f5f0f5b85db68be8",
        ];

        for entropy_hex in &vectors {
            let ent = hex::decode(entropy_hex).unwrap();
            let m = Mnemonic::from_entropy(&EN_WORDS, &ent).unwrap();
            let word_count = m.word_count;
            let cs = m.checksum();
            let digest = Sha256::digest(&ent);
            assert_eq!(digest[0] >> (8 - (word_count / 3)), cs);
        }
    }

    #[test]
    fn test_invalid_engish() {
        assert_eq!(
            Mnemonic::parse_str(
                &EN_WORDS,
                "getter advice cage absurd amount doctor acoustic avoid letter advice cage above",
            ),
            Err(Bip39Error::UnknownWord(0))
        );

        assert_eq!(
            Mnemonic::parse_str(
                &EN_WORDS,
                "letter advice cagex absurd amount doctor acoustic avoid letter advice cage above",
            ),
            Err(Bip39Error::UnknownWord(2))
        );

        assert_eq!(
            Mnemonic::parse_str(
                &EN_WORDS,
                "advice cage absurd amount doctor acoustic avoid letter advice cage above",
            ),
            Err(Bip39Error::BadWordCount(11))
        );

        assert_eq!(
            Mnemonic::parse_str(
                &EN_WORDS,
                "primary advice cage absurd amount doctor acoustic avoid letter advice cage above",
            ),
            Err(Bip39Error::InvalidChecksum)
        );
    }

    #[test]
    fn test_vectors_english() {
        let test_vectors = [
            (
                "00000000000000000000000000000000",
                "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
                "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04",
            ),
            (
                "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
                "legal winner thank year wave sausage worth useful legal winner thank yellow",
                "2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe1296106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607",
            ),
            (
                "80808080808080808080808080808080",
                "letter advice cage absurd amount doctor acoustic avoid letter advice cage above",
                "d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f12eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8",
            ),
            (
                "ffffffffffffffffffffffffffffffff",
                "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong",
                "ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a13332572917f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069",
            ),
            (
                "000000000000000000000000000000000000000000000000",
                "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent",
                "035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9a565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa",
            ),
            (
                "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
                "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will",
                "f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c392d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd",
            ),
            (
                "808080808080808080808080808080808080808080808080",
                "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always",
                "107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913ffb796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65",
            ),
            (
                "ffffffffffffffffffffffffffffffffffffffffffffffff",
                "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when",
                "0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b43348d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528",
            ),
            (
                "0000000000000000000000000000000000000000000000000000000000000000",
                "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art",
                "bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8",
            ),
            (
                "7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
                "legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title",
                "bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87",
            ),
            (
                "8080808080808080808080808080808080808080808080808080808080808080",
                "letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless",
                "c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f",
            ),
            (
                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
                "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote",
                "dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad",
            ),
            (
                "9e885d952ad362caeb4efe34a8e91bd2",
                "ozone drill grab fiber curtain grace pudding thank cruise elder eight picnic",
                "274ddc525802f7c828d8ef7ddbcdc5304e87ac3535913611fbbfa986d0c9e5476c91689f9c8a54fd55bd38606aa6a8595ad213d4c9c9f9aca3fb217069a41028",
            ),
            (
                "6610b25967cdcca9d59875f5cb50b0ea75433311869e930b",
                "gravity machine north sort system female filter attitude volume fold club stay feature office ecology stable narrow fog",
                "628c3827a8823298ee685db84f55caa34b5cc195a778e52d45f59bcf75aba68e4d7590e101dc414bc1bbd5737666fbbef35d1f1903953b66624f910feef245ac",
            ),
            (
                "68a79eaca2324873eacc50cb9c6eca8cc68ea5d936f98787c60c7ebc74e6ce7c",
                "hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay length",
                "64c87cde7e12ecf6704ab95bb1408bef047c22db4cc7491c4271d170a1b213d20b385bc1588d9c7b38f1b39d415665b8a9030c9ec653d75e65f847d8fc1fc440",
            ),
            (
                "c0ba5a8e914111210f2bd131f3d5e08d",
                "scheme spot photo card baby mountain device kick cradle pact join borrow",
                "ea725895aaae8d4c1cf682c1bfd2d358d52ed9f0f0591131b559e2724bb234fca05aa9c02c57407e04ee9dc3b454aa63fbff483a8b11de949624b9f1831a9612",
            ),
            (
                "6d9be1ee6ebd27a258115aad99b7317b9c8d28b6d76431c3",
                "horn tenant knee talent sponsor spell gate clip pulse soap slush warm silver nephew swap uncle crack brave",
                "fd579828af3da1d32544ce4db5c73d53fc8acc4ddb1e3b251a31179cdb71e853c56d2fcb11aed39898ce6c34b10b5382772db8796e52837b54468aeb312cfc3d",
            ),
            (
                "9f6a2878b2520799a44ef18bc7df394e7061a224d2c33cd015b157d746869863",
                "panda eyebrow bullet gorilla call smoke muffin taste mesh discover soft ostrich alcohol speed nation flash devote level hobby quick inner drive ghost inside",
                "72be8e052fc4919d2adf28d5306b5474b0069df35b02303de8c1729c9538dbb6fc2d731d5f832193cd9fb6aeecbc469594a70e3dd50811b5067f3b88b28c3e8d",
            ),
            (
                "23db8160a31d3e0dca3688ed941adbf3",
                "cat swing flag economy stadium alone churn speed unique patch report train",
                "deb5f45449e615feff5640f2e49f933ff51895de3b4381832b3139941c57b59205a42480c52175b6efcffaa58a2503887c1e8b363a707256bdd2b587b46541f5",
            ),
            (
                "8197a4a47f0425faeaa69deebc05ca29c0a5b5cc76ceacc0",
                "light rule cinnamon wrap drastic word pride squirrel upgrade then income fatal apart sustain crack supply proud access",
                "4cbdff1ca2db800fd61cae72a57475fdc6bab03e441fd63f96dabd1f183ef5b782925f00105f318309a7e9c3ea6967c7801e46c8a58082674c860a37b93eda02",
            ),
            (
                "066dca1a2bb7e8a1db2832148ce9933eea0f3ac9548d793112d9a95c9407efad",
                "all hour make first leader extend hole alien behind guard gospel lava path output census museum junior mass reopen famous sing advance salt reform",
                "26e975ec644423f4a4c4f4215ef09b4bd7ef924e85d1d17c4cf3f136c2863cf6df0a475045652c57eb5fb41513ca2a2d67722b77e954b4b3fc11f7590449191d",
            ),
            (
                "f30f8c1da665478f49b001d94c5fc452",
                "vessel ladder alter error federal sibling chat ability sun glass valve picture",
                "2aaa9242daafcee6aa9d7269f17d4efe271e1b9a529178d7dc139cd18747090bf9d60295d0ce74309a78852a9caadf0af48aae1c6253839624076224374bc63f",
            ),
            (
                "c10ec20dc3cd9f652c7fac2f1230f7a3c828389a14392f05",
                "scissors invite lock maple supreme raw rapid void congress muscle digital elegant little brisk hair mango congress clump",
                "7b4a10be9d98e6cba265566db7f136718e1398c71cb581e1b2f464cac1ceedf4f3e274dc270003c670ad8d02c4558b2f8e39edea2775c9e232c7cb798b069e88",
            ),
            (
                "f585c11aec520db57dd353c69554b21a89b20fb0650966fa0a9d6f74fd989d8f",
                "void come effort suffer camp survey warrior heavy shoot primary clutch crush open amazing screen patrol group space point ten exist slush involve unfold",
                "01f5bced59dec48e362f2c45b5de68b9fd6c92c6634f44d6d40aab69056506f0e35524a518034ddc1192e1dacd32c1ed3eaa3c3b131c88ed8e7e54c49a5d0998",
            )
        ];

        for vector in &test_vectors {
            let entropy = hex::decode(&vector.0).unwrap();
            let mnemonic_str = vector.1;
            let seed = hex::decode(&vector.2).unwrap();
            let mnemonic = Mnemonic::from_entropy(&EN_WORDS, &entropy).unwrap();

            assert_eq!(
                mnemonic,
                Mnemonic::parse_str(&EN_WORDS, mnemonic_str).unwrap(),
                "failed vector: {}",
                mnemonic_str
            );
            assert_eq!(
                &seed[..],
                &mnemonic.to_seed("TREZOR").unwrap()[..],
                "failed vector: {}",
                mnemonic_str
            );

            {
                assert_eq!(
                    &mnemonic.to_string(),
                    mnemonic_str,
                    "failed vector: {}",
                    mnemonic_str
                );
                assert_eq!(
                    mnemonic,
                    Mnemonic::parse_str(&EN_WORDS, mnemonic_str).unwrap(),
                    "failed vector: {}",
                    mnemonic_str
                );
                assert_eq!(
                    mnemonic,
                    Mnemonic::parse_str(&EN_WORDS, mnemonic_str).unwrap(),
                    "failed vector: {}",
                    mnemonic_str
                );
                assert_eq!(
                    &seed[..],
                    &mnemonic.to_seed("TREZOR").unwrap()[..],
                    "failed vector: {}",
                    mnemonic_str
                );
                assert_eq!(
                    &entropy,
                    &mnemonic.to_entropy().into_iter().collect::<Vec<u8>>(),
                    "failed vector: {}",
                    mnemonic_str
                );
            }
        }
    }

    #[test]
    fn test_invalid_mnemonic_restoration() {
        let mnemonic_str =
            "sword sure throw slide garden science six destroy canvas ceiling negative black";

        let mnemonic = Mnemonic::parse_str_without_checksum(&EN_WORDS, mnemonic_str).unwrap();
        let entropy = mnemonic.to_entropy().collect::<Vec<u8>>();
        let restored_mnemonic = Mnemonic::from_entropy(&EN_WORDS, &entropy).unwrap();

        assert_ne!(
            mnemonic.to_string(),
            restored_mnemonic.to_string(),
            "Restored mnemonic should match original"
        );
    }

    #[test]
    fn test_vectors_japanese() {
        // These vectors are tuples of
        // (entropy, mnemonic, passphrase, seed)
        let vectors = [
			(
				"00000000000000000000000000000000",
				"あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あおぞら",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"a262d6fb6122ecf45be09c50492b31f92e9beb7d9a845987a02cefda57a15f9c467a17872029a9e92299b5cbdf306e3a0ee620245cbd508959b6cb7ca637bd55",
			),
			(
				"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
				"そつう　れきだい　ほんやく　わかす　りくつ　ばいか　ろせん　やちん　そつう　れきだい　ほんやく　わかめ",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"aee025cbe6ca256862f889e48110a6a382365142f7d16f2b9545285b3af64e542143a577e9c144e101a6bdca18f8d97ec3366ebf5b088b1c1af9bc31346e60d9",
			),
			(
				"80808080808080808080808080808080",
				"そとづら　あまど　おおう　あこがれる　いくぶん　けいけん　あたえる　いよく　そとづら　あまど　おおう　あかちゃん",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"e51736736ebdf77eda23fa17e31475fa1d9509c78f1deb6b4aacfbd760a7e2ad769c714352c95143b5c1241985bcb407df36d64e75dd5a2b78ca5d2ba82a3544",
			),
			(
				"ffffffffffffffffffffffffffffffff",
				"われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　ろんぶん",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"4cd2ef49b479af5e1efbbd1e0bdc117f6a29b1010211df4f78e2ed40082865793e57949236c43b9fe591ec70e5bb4298b8b71dc4b267bb96ed4ed282c8f7761c",
			),
			(
				"000000000000000000000000000000000000000000000000",
				"あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あらいぐま",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"d99e8f1ce2d4288d30b9c815ae981edd923c01aa4ffdc5dee1ab5fe0d4a3e13966023324d119105aff266dac32e5cd11431eeca23bbd7202ff423f30d6776d69",
			),
			(
				"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
				"そつう　れきだい　ほんやく　わかす　りくつ　ばいか　ろせん　やちん　そつう　れきだい　ほんやく　わかす　りくつ　ばいか　ろせん　やちん　そつう　れいぎ",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"eaaf171efa5de4838c758a93d6c86d2677d4ccda4a064a7136344e975f91fe61340ec8a615464b461d67baaf12b62ab5e742f944c7bd4ab6c341fbafba435716",
			),
			(
				"808080808080808080808080808080808080808080808080",
				"そとづら　あまど　おおう　あこがれる　いくぶん　けいけん　あたえる　いよく　そとづら　あまど　おおう　あこがれる　いくぶん　けいけん　あたえる　いよく　そとづら　いきなり",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"aec0f8d3167a10683374c222e6e632f2940c0826587ea0a73ac5d0493b6a632590179a6538287641a9fc9df8e6f24e01bf1be548e1f74fd7407ccd72ecebe425",
			),
			(
				"ffffffffffffffffffffffffffffffffffffffffffffffff",
				"われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　りんご",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"f0f738128a65b8d1854d68de50ed97ac1831fc3a978c569e415bbcb431a6a671d4377e3b56abd518daa861676c4da75a19ccb41e00c37d086941e471a4374b95",
			),
			(
				"0000000000000000000000000000000000000000000000000000000000000000",
				"あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　あいこくしん　いってい",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"23f500eec4a563bf90cfda87b3e590b211b959985c555d17e88f46f7183590cd5793458b094a4dccc8f05807ec7bd2d19ce269e20568936a751f6f1ec7c14ddd",
			),
			(
				"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f",
				"そつう　れきだい　ほんやく　わかす　りくつ　ばいか　ろせん　やちん　そつう　れきだい　ほんやく　わかす　りくつ　ばいか　ろせん　やちん　そつう　れきだい　ほんやく　わかす　りくつ　ばいか　ろせん　まんきつ",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"cd354a40aa2e241e8f306b3b752781b70dfd1c69190e510bc1297a9c5738e833bcdc179e81707d57263fb7564466f73d30bf979725ff783fb3eb4baa86560b05",
			),
			(
				"8080808080808080808080808080808080808080808080808080808080808080",
				"そとづら　あまど　おおう　あこがれる　いくぶん　けいけん　あたえる　いよく　そとづら　あまど　おおう　あこがれる　いくぶん　けいけん　あたえる　いよく　そとづら　あまど　おおう　あこがれる　いくぶん　けいけん　あたえる　うめる",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"6b7cd1b2cdfeeef8615077cadd6a0625f417f287652991c80206dbd82db17bf317d5c50a80bd9edd836b39daa1b6973359944c46d3fcc0129198dc7dc5cd0e68",
			),
			(
				"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
				"われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　われる　らいう",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"a44ba7054ac2f9226929d56505a51e13acdaa8a9097923ca07ea465c4c7e294c038f3f4e7e4b373726ba0057191aced6e48ac8d183f3a11569c426f0de414623",
			),
			(
				"77c2b00716cec7213839159e404db50d",
				"せまい　うちがわ　あずき　かろう　めずらしい　だんち　ますく　おさめる　ていぼう　あたる　すあな　えしゃく",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"344cef9efc37d0cb36d89def03d09144dd51167923487eec42c487f7428908546fa31a3c26b7391a2b3afe7db81b9f8c5007336b58e269ea0bd10749a87e0193",
			),
			(
				"b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b",
				"ぬすむ　ふっかつ　うどん　こうりつ　しつじ　りょうり　おたがい　せもたれ　あつめる　いちりゅう　はんしゃ　ごますり　そんけい　たいちょう　らしんばん　ぶんせき　やすみ　ほいく",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"b14e7d35904cb8569af0d6a016cee7066335a21c1c67891b01b83033cadb3e8a034a726e3909139ecd8b2eb9e9b05245684558f329b38480e262c1d6bc20ecc4",
			),
			(
				"3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982",
				"くのう　てぬぐい　そんかい　すろっと　ちきゅう　ほあん　とさか　はくしゅ　ひびく　みえる　そざい　てんすう　たんぴん　くしょう　すいようび　みけん　きさらぎ　げざん　ふくざつ　あつかう　はやい　くろう　おやゆび　こすう",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"32e78dce2aff5db25aa7a4a32b493b5d10b4089923f3320c8b287a77e512455443298351beb3f7eb2390c4662a2e566eec5217e1a37467af43b46668d515e41b",
			),
			(
				"0460ef47585604c5660618db2e6a7e7f",
				"あみもの　いきおい　ふいうち　にげる　ざんしょ　じかん　ついか　はたん　ほあん　すんぽう　てちがい　わかめ",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"0acf902cd391e30f3f5cb0605d72a4c849342f62bd6a360298c7013d714d7e58ddf9c7fdf141d0949f17a2c9c37ced1d8cb2edabab97c4199b142c829850154b",
			),
			(
				"72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f",
				"すろっと　にくしみ　なやむ　たとえる　へいこう　すくう　きない　けってい　とくべつ　ねっしん　いたみ　せんせい　おくりがな　まかい　とくい　けあな　いきおい　そそぐ",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"9869e220bec09b6f0c0011f46e1f9032b269f096344028f5006a6e69ea5b0b8afabbb6944a23e11ebd021f182dd056d96e4e3657df241ca40babda532d364f73",
			),
			(
				"2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416",
				"かほご　きうい　ゆたか　みすえる　もらう　がっこう　よそう　ずっと　ときどき　したうけ　にんか　はっこう　つみき　すうじつ　よけい　くげん　もくてき　まわり　せめる　げざい　にげる　にんたい　たんそく　ほそく",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"713b7e70c9fbc18c831bfd1f03302422822c3727a93a5efb9659bec6ad8d6f2c1b5c8ed8b0b77775feaf606e9d1cc0a84ac416a85514ad59f5541ff5e0382481",
			),
			(
				"eaebabb2383351fd31d703840b32e9e2",
				"めいえん　さのう　めだつ　すてる　きぬごし　ろんぱ　はんこ　まける　たいおう　さかいし　ねんいり　はぶらし",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"06e1d5289a97bcc95cb4a6360719131a786aba057d8efd603a547bd254261c2a97fcd3e8a4e766d5416437e956b388336d36c7ad2dba4ee6796f0249b10ee961",
			),
			(
				"7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78",
				"せんぱい　おしえる　ぐんかん　もらう　きあい　きぼう　やおや　いせえび　のいず　じゅしん　よゆう　きみつ　さといも　ちんもく　ちわわ　しんせいじ　とめる　はちみつ",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"1fef28785d08cbf41d7a20a3a6891043395779ed74503a5652760ee8c24dfe60972105ee71d5168071a35ab7b5bd2f8831f75488078a90f0926c8e9171b2bc4a",
			),
			(
				"4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef",
				"こころ　いどう　きあつ　そうがんきょう　へいあん　せつりつ　ごうせい　はいち　いびき　きこく　あんい　おちつく　きこえる　けんとう　たいこ　すすめる　はっけん　ていど　はんおん　いんさつ　うなぎ　しねま　れいぼう　みつかる",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"43de99b502e152d4c198542624511db3007c8f8f126a30818e856b2d8a20400d29e7a7e3fdd21f909e23be5e3c8d9aee3a739b0b65041ff0b8637276703f65c2",
			),
			(
				"18ab19a9f54a9274f03e5209a2ac8a91",
				"うりきれ　さいせい　じゆう　むろん　とどける　ぐうたら　はいれつ　ひけつ　いずれ　うちあわせ　おさめる　おたく",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"3d711f075ee44d8b535bb4561ad76d7d5350ea0b1f5d2eac054e869ff7963cdce9581097a477d697a2a9433a0c6884bea10a2193647677977c9820dd0921cbde",
			),
			(
				"18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4",
				"うりきれ　うねる　せっさたくま　きもち　めんきょ　へいたく　たまご　ぜっく　びじゅつかん　さんそ　むせる　せいじ　ねくたい　しはらい　せおう　ねんど　たんまつ　がいけん",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"753ec9e333e616e9471482b4b70a18d413241f1e335c65cd7996f32b66cf95546612c51dcf12ead6f805f9ee3d965846b894ae99b24204954be80810d292fcdd",
			),
			(
				"15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419",
				"うちゅう　ふそく　ひしょ　がちょう　うけもつ　めいそう　みかん　そざい　いばる　うけとる　さんま　さこつ　おうさま　ぱんつ　しひょう　めした　たはつ　いちぶ　つうじょう　てさぎょう　きつね　みすえる　いりぐち　かめれおん",
				"㍍ガバヴァぱばぐゞちぢ十人十色",
				"346b7321d8c04f6f37b49fdf062a2fddc8e1bf8f1d33171b65074531ec546d1d3469974beccb1a09263440fc92e1042580a557fdce314e27ee4eabb25fa5e5fe",
			)
		];

        for vector in &vectors {
            let entropy = hex::decode(&vector.0).unwrap();
            let mnemonic_str = vector.1;
            let passphrase = vector.2;
            let seed = hex::decode(&vector.3).unwrap();

            let mnemonic = Mnemonic::from_entropy(&JA_WORDS, &entropy).unwrap();

            assert_eq!(
                seed,
                &mnemonic.to_seed(passphrase).unwrap()[..],
                "failed vector: {}",
                mnemonic_str
            );
            let rt = Mnemonic::parse_str(&JA_WORDS, &mnemonic.to_string()).unwrap();
            assert_eq!(seed, &rt.to_seed(passphrase).unwrap()[..]);

            let mnemonic = Mnemonic::parse_str(&JA_WORDS, mnemonic_str).unwrap();
            assert_eq!(
                seed,
                &mnemonic.to_seed(passphrase).unwrap()[..],
                "failed vector: {}",
                mnemonic_str
            );
        }
    }
}

```

`pqbip39/src/pbkdf2.rs`:

```rs
use hmac::{Hmac, Mac};
use sha2::{Digest, Sha512};

use crate::{errors::Bip39Error, mnemonic::SEED_BYTE_LEN};

const SALT_PREFIX: &str = "mnemonic";

fn mnemonic_byte_len<'a, I>(iter: I) -> usize
where
    I: Iterator<Item = &'a str>,
{
    let mut len = 0;
    let mut count: usize = 0;
    for word in iter {
        len += word.len();
        count += 1;
    }

    len + count.saturating_sub(1)
}

#[inline]
fn xor(a: &mut [u8], b: &[u8]) {
    for (a_byte, b_byte) in a.iter_mut().zip(b.iter()) {
        *a_byte ^= *b_byte;
    }
}

pub fn pbkdf2<'a, I>(
    mnemonic: I,
    passphrase: &[u8],
    c: u32,
) -> Result<[u8; SEED_BYTE_LEN], Bip39Error>
where
    I: Iterator<Item = &'a str> + Clone,
{
    const BLOCK_SIZE: usize = 128;
    let mut key_buffer = [0u8; BLOCK_SIZE];

    let mnemonic_len = mnemonic_byte_len(mnemonic.clone());

    let key = if mnemonic_len > BLOCK_SIZE {
        let mut hasher = Sha512::new();
        for (i, word) in mnemonic.clone().enumerate() {
            if i > 0 {
                hasher.update(b" ");
            }
            hasher.update(word.as_bytes());
        }
        let hashed_key = hasher.finalize();
        let len = hashed_key.len();
        key_buffer[..len].copy_from_slice(&hashed_key);
        &key_buffer[..len]
    } else {
        let mut cursor = 0;
        for (i, word) in mnemonic.enumerate() {
            if i > 0 {
                key_buffer[cursor] = b' ';
                cursor += 1;
            }
            let word_bytes = word.as_bytes();
            let word_len = word_bytes.len();
            key_buffer[cursor..cursor + word_len].copy_from_slice(word_bytes);
            cursor += word_len;
        }
        &key_buffer[..cursor]
    };

    let prf = Hmac::<Sha512>::new_from_slice(key)?;
    let h_len = <Sha512 as Digest>::output_size();
    let mut result = [0u8; SEED_BYTE_LEN];

    for (i, chunk) in result.chunks_mut(h_len).enumerate() {
        let i_be = ((i + 1) as u32).to_be_bytes();

        let mut mac = prf.clone();
        mac.update(SALT_PREFIX.as_bytes());
        mac.update(passphrase);
        mac.update(&i_be);
        let mut u = mac.finalize().into_bytes();

        chunk.copy_from_slice(&u);

        for _ in 1..c {
            let mut mac = prf.clone();
            mac.update(&u);
            u = mac.finalize().into_bytes();
            xor(chunk, &u);
        }
    }
    Ok(result)
}

#[cfg(test)]
mod tests_pbkdf2 {
    use super::*;

    #[test]
    fn test_mnemonic_byte_len() {
        let words: [&str; 0] = [];
        assert_eq!(mnemonic_byte_len(words.iter().cloned()), 0);

        let words = ["hello"];
        assert_eq!(mnemonic_byte_len(words.iter().cloned()), 5);

        let words = ["abandon", "ability", "able"];
        assert_eq!(mnemonic_byte_len(words.iter().cloned()), 20);

        let words = ["a", "b", "c", "d"];
        assert_eq!(mnemonic_byte_len(words.iter().cloned()), 7);
    }

    #[test]
    fn test_xor() {
        let mut a1 = [0b10101010, 0b11001100];
        let b1 = [0b11110000, 0b00110011];
        let expected1 = [0b01011010, 0b11111111];
        xor(&mut a1, &b1);
        assert_eq!(a1, expected1);

        let mut a2 = [1, 2, 3, 4];
        let b2 = [0, 0, 0, 0];
        let expected2 = [1, 2, 3, 4];
        xor(&mut a2, &b2);
        assert_eq!(a2, expected2);

        let mut a3 = [0xDE, 0xAD, 0xBE, 0xEF];
        let b3 = a3.clone();
        let expected3 = [0, 0, 0, 0];
        xor(&mut a3, &b3);
        assert_eq!(a3, expected3);
    }

    #[test]
    fn test_pbkdf2() {
        let mnemonic = ["word1", "word2", "word3"].iter().map(|&s| s);
        let salt = b"salt";
        let iterations = 1;
        let result = pbkdf2(mnemonic, salt, iterations).unwrap();

        assert_eq!(result.len(), 64);
        assert_ne!(result, [0u8; 64]);
        assert_eq!(
            [
                86, 130, 218, 167, 48, 166, 30, 74, 25, 139, 29, 236, 12, 8, 147, 130, 209, 25, 57,
                217, 46, 208, 137, 18, 0, 235, 182, 2, 198, 34, 120, 193, 235, 137, 250, 64, 84,
                77, 82, 46, 152, 18, 125, 151, 204, 241, 21, 57, 250, 206, 116, 67, 96, 238, 8, 18,
                117, 245, 196, 125, 250, 145, 49, 19,
            ],
            result
        );
    }
}

```

`pqbip39/src/rng.rs`:

```rs
pub trait Rng {
    fn fill_bytes(&mut self, dest: &mut [u8]);
}

```

`pqbip39/src/utils.rs`:

```rs
use crate::mnemonic::{MAX_NB_WORDS, MIN_NB_WORDS};

#[inline]
pub fn is_invalid_word_count(word_count: usize) -> bool {
    word_count < MIN_NB_WORDS || word_count % 3 != 0 || word_count > MAX_NB_WORDS
}

```