Security

Passphrases

Diceware passphrases from the EFF word lists, easy to type and remember and hard to guess, with their strength in bits.

Version 1.0.0 · 3 functions · 2 crates

#passwords#sign-up#random#wifi

Functions

What use passphrase.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use passphrase, passphrase_with from passphrase (Quillo 0.6).

passphrase(words: int, separator: str) → stror an error

A passphrase of words words (3 to 20) from the EFF long list, joined by separator ("-", " ", "." ...; up to 3 characters). Each word adds 12.9 bits: 5 words, 64.6 bits; 6 words, 77.5. Picked with the system's secure random numbers.

passphrase_with(words: int, separator: str, list_name: str, capitalize: bool, digit: bool) → anyor an error

A passphrase with choices: list "long", "short" or "memorable"; capitalize each word; digit adds one digit to one word, for sites that ask for one. Gives { passphrase, words, bits }, bits being its strength when the guesser knows the list and the rules.

passphrase_bits(words: int, list_name: str) → floator an error

The strength in bits of words words from list ("long", "short" or "memorable").

Get it

$ quillo install passphrase               # passphrase.qwer into this folder$ quillo install passphrase --example     # and its example, passphrase.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/passphrase.qwer$ curl -O https://quillolang.org/plugins/files/passphrase.qwe

Then, in your program, all of it or only what you call:

main.qwe
use passphrase.qweruse passphrase, passphrase_with from passphrase      // Quillo 0.6: only these

It uses these crates, which cargo fetches the first time the plugin is built:

[dependencies]
diceware_wordlists = "1.2"rand = "0.8"

Example

passphrase.qwe
// First passwords for new staff accounts, and a recovery phrase, as passphrases.////   quillo run passphrase.qwe      then open http://localhost:8080/newuse "passphrase.qwer"route GET /new ? { words: int = 5 } = { password: passphrase(words, "-")?, bits: passphrase_bits(words, "long")? }route GET /wifi = passphrase_with(4, " ", "memorable", true, true)?route GET /strength = { five_long: passphrase_bits(5, "long")?, six_long: passphrase_bits(6, "long")?, eight_short: passphrase_bits(8, "short")? }
$ quillo run passphrase.qwe$ curl 'localhost:8080/new'$ curl 'localhost:8080/strength'$ curl 'localhost:8080/wifi'

Source

passphrase.qwer
//! Diceware passphrases from the EFF word lists (`crane-shrunk-gristle-unwind-pacific`): easy to type and remember, hard to guess, for first passwords, Wi-Fi keys and recovery phrases.//! version: 1.0.0//!//! [dependencies]//! diceware_wordlists = "1.2"//! rand = "0.8"use diceware_wordlists::Wordlist;use rand::seq::SliceRandom;use rand::Rng;use serde_json::{json, Value};fn list(name: &str) -> Result<&'static [&'static str], String> {    match name {        "" | "long" => Ok(Wordlist::EffLong.get_list()),        "short" => Ok(Wordlist::EffShort1.get_list()),        "memorable" => Ok(Wordlist::EffShort2.get_list()),        other => Err(format!("unknown list `{}`: long (7,776 words), short (1,296 short words) or memorable (1,296 words with unique 3-letter starts)", other)),    }}fn make(words: i64, separator: &str, list_name: &str, capitalize: bool, digit: bool) -> Result<Value, String> {    let l = list(list_name)?;    let n = words.clamp(3, 20) as usize;    let mut rng = rand::rngs::OsRng;    let mut picked: Vec<String> = (0..n).map(|_| l.choose(&mut rng).copied().unwrap_or("word").to_string()).collect();    if capitalize {        for w in picked.iter_mut() {            let mut c = w.chars();            *w = c.next().map(|f| f.to_uppercase().collect::<String>() + c.as_str()).unwrap_or_default();        }    }    let mut bits = n as f64 * (l.len() as f64).log2();    if digit {        let at = rng.gen_range(0..n);        picked[at].push_str(&rng.gen_range(0..10).to_string());        bits += 10f64.log2() + (n as f64).log2();    }    let sep: String = separator.chars().take(3).collect();    Ok(json!({ "passphrase": picked.join(&sep), "words": n, "bits": (bits * 10.0).round() / 10.0 }))}/// A passphrase of `words` words (3 to 20) from the EFF long list, joined by `separator` ("-", " ", "." ...; up to 3/// characters). Each word adds 12.9 bits: 5 words, 64.6 bits; 6 words, 77.5. Picked with the system's secure random numbers.pub fn passphrase(words: i64, separator: &str) -> Result<String, String> {    Ok(make(words, separator, "long", false, false)?["passphrase"].as_str().unwrap_or_default().to_string())}/// A passphrase with choices: `list` "long", "short" or "memorable"; `capitalize` each word; `digit` adds one digit to one/// word, for sites that ask for one. Gives `{ passphrase, words, bits }`, `bits` being its strength when the guesser knows/// the list and the rules.pub fn passphrase_with(words: i64, separator: &str, list_name: &str, capitalize: bool, digit: bool) -> Result<Value, String> {    make(words, separator, list_name, capitalize, digit)}/// The strength in bits of `words` words from `list` ("long", "short" or "memorable").pub fn passphrase_bits(words: i64, list_name: &str) -> Result<f64, String> {    Ok(((words.max(0) as f64 * (list(list_name)?.len() as f64).log2()) * 10.0).round() / 10.0)}
Thread
77Useful? Like it, or add to its thread below.

Thread 0 posts

On Passphrases: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.