Skip to content

Commit 5429d40

Browse files
authored
Support memorable passwords (#571)
* Improve password generator API. * Move ChangePassword to vault module. * feat: implement memorable password generator * feat: Add logging to memorable password generation test * feat: update `generate_memorable_password` to include uppercase and numeric characters * feat: update memorable password function to allow digit on either side of hyphen or as last character * feat: Implement memorable password generation * fix: Resolve moved compiler errors in memorable password test spec * feat: Add digit check to memorable password generation * feat: Update memorable password function * feat: create syllables by placing vowels between consonants * fix: Update memorable_password function and test case to ensure consonant at index 4 * Rewrite memorable password function manually. * Add memorable passwords to the builder. * Fix bug with hard-coded syllables length.
1 parent 060a92c commit 5429d40

File tree

8 files changed

+306
-89
lines changed

8 files changed

+306
-89
lines changed

crates/sdk/src/account/account.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ impl LocalAccount {
10321032
vault_id: &VaultId,
10331033
new_key: AccessKey,
10341034
) -> Result<Vec<u8>> {
1035-
use crate::passwd::ChangePassword;
1035+
use crate::vault::ChangePassword;
10361036
let paths = self.paths().clone();
10371037
// Get the current vault passphrase from the identity vault
10381038
let current_key = self

crates/sdk/src/passwd/diceware.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//! Helper functions for generating diceware passwords.
2+
use crate::{Error, Result};
3+
use chbs::{
4+
config::{BasicConfig, BasicConfigBuilder},
5+
prelude::*,
6+
probability::Probability,
7+
word::{WordList, WordSampler},
8+
};
9+
use secrecy::{Secret, SecretString};
10+
11+
use once_cell::sync::Lazy;
12+
13+
static WORD_LIST: Lazy<WordList> = Lazy::new(WordList::builtin_eff_large);
14+
15+
/// Generate a passphrase using the given config.
16+
pub fn generate_passphrase_config(
17+
config: &BasicConfig<WordSampler>,
18+
) -> Result<(SecretString, f64)> {
19+
if config.words < 6 {
20+
return Err(Error::DicewareWordsTooFew(config.words, 6));
21+
}
22+
23+
let scheme = config.to_scheme();
24+
Ok((Secret::new(scheme.generate()), scheme.entropy().bits()))
25+
}
26+
27+
/// Generate a diceware passphrase with the given number of words.
28+
///
29+
/// The number of words must be at least six.
30+
pub fn generate_passphrase_words(
31+
words: usize,
32+
) -> Result<(SecretString, f64)> {
33+
let config = default_config(words);
34+
generate_passphrase_config(&config)
35+
}
36+
37+
/// Generate a diceware passphrase with six words which is ~171 bits of entropy.
38+
pub fn generate_passphrase() -> Result<(SecretString, f64)> {
39+
generate_passphrase_words(6)
40+
}
41+
42+
/// Get the default config for diceware passphrase generation.
43+
pub fn default_config(words: usize) -> BasicConfig<WordSampler> {
44+
let config = BasicConfigBuilder::default()
45+
.word_provider(WORD_LIST.sampler())
46+
.words(words)
47+
.separator(' ')
48+
.capitalize_first(Probability::Never)
49+
.capitalize_words(Probability::Never)
50+
.build()
51+
.unwrap();
52+
config
53+
}

0 commit comments

Comments
 (0)