Git Product home page Git Product logo

phraze's Introduction

Phraze

Crates.io Crates.io

Generate random passphrases.

$ phraze
curse-argues-valves-unfair-punk-ritual-inlet

Features

  • ๐ŸŽš๏ธ Allows user to set a minimum entropy, freeing them from having to figure how many words from a given list they need to create a strong passphrase
  • ๐ŸŽฏ All built-in word lists are uniquely decodable, ensuring that passphrase entropy estimates remain accurate when no separator is used
  • โšก Fast: Takes about 2 milliseconds to generate a passphrase
  • ๐Ÿ”ฃ Can insert numbers, symbols, and/or capital letters if necessary (e.g. phraze -s _b -t)
  • ๐Ÿ› Default word list is (hopefully) free of profane words
  • ๐Ÿงบ Choose from a number of included word lists or provide your own
  • ๐Ÿ› ๏ธ Written in Rust

Installing

Using Rust and Cargo

  1. Install Rust if you haven't already
  2. Run: cargo install phraze --locked (Run this same command to upgrade Phraze to latest available version.)

Uninstall Phraze by running cargo uninstall phraze.

Latest release

Alternatively, you can get binaries from the GitHub releases page.

How to use

Running phraze (without options) will generate a passphrase with at least 80 bits of entropy.

Entropy is an estimate of the "strength" of the passphrase. Higher entropy means a stronger passphrase.

Changing the strength of the passphrase

You can change the strength of the passphrase Phraze generates, making it either weaker or stronger, 3 different ways:

1. Enter a Strength Count. Use -S to increase minimum entropy from 80 bits to 100 bits. Each additional S adds another 20 bits of minimum entropy (e.g. -SS => 120 bit minimum; -SSS => 140 bit minimum, etc.).

$ phraze -SS
determined-pervasive-entirety-incumbent-trophy-emergence-spatial-wondering-destroyed-gamma

2. Set a specific minimum entropy. Use --minimum-entropy to specify your own minimum amount of entropy, in bits, that your passphrase must have.

$ phraze --minimum-entropy 100
toured-warrior-skeleton-shear-hosts-injuries-relied-sadness

3. Set number words. Use --words to specify the exact number of words for Phraze to use.

$ phraze ---words 5 # passphrase will have 5 words, overriding the default minimum entropy setting of 80 bits
determines-generated-frozen-excluded-sleeping

Note that you can only use one of these strength-changing methods at a time.

If you want to know how much entropy your generated passphrase has, add the -v/--verbose flag.

$ phraze -v -S
Passphrase has an estimated 104.00 bits of entropy (8 words from a list of 8192 words)
seventy-cost-freight-suspended-misery-objections-represents-buying

Changing the separator between words

By default, Phraze separates words with a hyphen ("-"). You can change that with the --sep (or -s) option.

--sep accept special inputs _n (random numbers), _s (random symbols), and _b (mix of both). Note that separator choice does not effect entropy calculations.

$ phraze --sep ' '
optimism daughters figures grim processors became decreasing
$ phrase --sep _s
fax/household>validation_replied-upgrade,remind?reasoning

If you don't want a separator at all, use -s '':

phraze -s ''
theftinversiondebtsquietlysuspensionannualchocolate

You can make all the word Title Case by using --title-case:

$ phraze --sep '' --title-case
GoverningDominateAnswersReceptorsAllocatedClientModify

If you need to have a symbol, a number and an uppercase character in your passphrase, you can try:

$ phraze -t -s _b
Welcome&Song}Barker)Concrete;Commune$Shouted2Ensuing

Changing the word list that Phraze uses

By default, Phraze uses a 8192-word list called the Orchard Street Medium List (which gives 13 bits of entropy per word).

You can specify a different list with --list/-l, with a choice of a handful of lists included with Phraze.

Each included list has a corresponding one-letter code (see below or run phrase --help for a full list). For example, --list s uses the EFF short list.

$ phraze --list s
duck-slip-swoop-stray-wink-stump-whiff-slot

(Note that we need 8 words from the EFF short list to meet the default minimum entropy of 80 bits.)

Using your own list

If you prefer, you can have Phraze generate a passphrase using your own word list. Use the --custom-list option.

$ phraze --custom-list path/to/word/list

Phraze will remove any and all trailing white space, duplicate words, and blank words in the inputted list. Phraze will also check for uniform Unicode normalization.

Copying passphrase to clipboard

You can pipe Phraze's outputted passphrase to other tools. For example, you can copy generated passphrase to xclip (a common Linux clipboard tool):

$ phraze | xclip -selection clipboard

Usage

Usage: phraze [OPTIONS]

Options:
  -S, --strength...
          Strengthen your passphrase the easy way: Each -S flag increases minimum 
          entropy by 20 bits (above the default of 80 bits)

  -e, --minimum-entropy <MINIMUM_ENTROPY>
          Set minimum amount of entropy in bits for generated passphrase. If 
          neither minimum_entropy or number_of_words is specified, Phraze will 
          default to an 80-bit minimum

  -w, --words <NUMBER_OF_WORDS>
          Set exactly how many words to use in generated passphrase. If neither 
          number_of_words or minimum_entropy is specified, Phraze will default to 
          an 80-bit minimum

  -n, --passphrases <N_PASSPHRASES>
          Number of passphrases to generate
          
          [default: 1]

  -s, --sep <SEPARATOR>
          Word separator. Can accept single quotes around the separator. For no 
          separator, use empty single quotes ''.
          
          There are special values that will trigger generated separators:
          
          _n: separators will be random numbers
          
          _s: separators will be random symbols
          
          _b: separators will be a mix of random numbers and symbols
          
          [default: -]

  -l, --list <LIST_CHOICE>
          Choose a word list to use.
          
          Options:
          
          m: Orchard Street Medium List (8,192 words) [DEFAULT]
          
          l: Orchard Street Long List (17,576 words)
          
          e: EFF long list (7,776 words)
          
          n: Mnemonicode list (1,633 words). Good if you know you're going to be 
          speaking passphrases out loud.
          
          s: EFF short list (1,296 words)
          
          q: Orchard Street QWERTY list (1,296 words). Optimized to minimize travel 
          distance on QWERTY keyboard layouts.
          
          a: Orchard Street Alpha list (1,296 words). Optimized to minimize travel 
          distance on an alphabetical keyboard layout
          
          [default: m]

  -c, --custom-list <CUSTOM_LIST_FILE_PATH>
          Provide a text file with a list of words to randomly generate passphrase 
          from.
          
          Should be a text file with one word per line.

  -t, --title-case
          Use Title Case for words in generated usernames

  -v, --verbose
          Print estimated entropy of generated passphrase, in bits, along with the 
          passphrase itself

  -h, --help
          Print help (see a summary with '-h')

  -V, --version
          Print version

Included word lists

By default, Phraze uses the Orchard Street Medium wordlist, which has 8,192 words. This means each word adds 13.0 bits of entropy to a passphrase.

However, Phraze comes with other word lists built-in. Run phraze --help to view word list options. You can choose a different word list by using the -l/--list option. All of the word lists included with Phraze are uniquely decodable, which means they're safe to use without a separator between words.

  • Orchard Street Medium list: 8,192 words; 13 bits of entropy per word. This is the DEFAULT list Phraze will use if no list is specified by the user.
  • Orchard Street Long list: 17,576 words; 14.1 bits of entropy per word. Use l.
  • EFF long list: 7,776 words; 12.93 bits of entropy per word. Use e.
  • Mnemonicode list: 1,633 words; 10.67 bits of entropy per word. Words are easy to pronounce out loud. Use n.
  • EFF short list 1: 1,296 words; 10.3 bits of entropy per word. Use s.
  • Orchard Street QWERTY list: 1,296 words; 10.3 bits of entropy per word. Use q.
  • Orchard Street Alpha list: 1,296 words; 10.3 bits of entropy per word. Use a.

Notes on the Orchard Street QWERTY and Alpha lists

These two lists are optimized to minimize travel distance when inputting passphrases into TVs or video game consoles. They both have 1,296 words (10.3 bits per word).

The Orchard Street QWERTY list that is optimized for QWERTY keyboard layouts. Use this list if your keyboard layout looks like this:

qwertyuiop
asdfghjkl
zxcvbnm

The Orchard Street Alpha list that is optimized for alphabetical keyboard layouts. Use this list if your keyboard layout looks like this:

abcdef
ghijkl
mnopqr
stuvwx
yz

Technical details of all included word lists

This list information was generated using Word List Auditor.

Orchard Street Medium

Lines found               : 8192
Free of exact duplicates  : true
Free of fuzzy duplicates  : true
Free of blank lines       : true
Unique words found        : 8192
No start/end whitespace   : true
No non-ASCII characters   : true
Unicode normalized        : true
Free of prefix words      : false
Uniquely decodable        : true
Above brute force line    : true
Length of shortest word   : 3 characters (add)
Length of longest word    : 10 characters (worthwhile)
Mean word length          : 7.07 characters
Entropy per word          : 13.000 bits
Efficiency per character  : 1.839 bits
Assumed entropy per char  : 4.333 bits
Shortest edit distance    : 1
Mean edit distance        : 6.966
Longest shared prefix     : 9
Unique character prefix   : 10

Sample passphrases:
popular-claiming-sailing-spiritual-homeland-pay-keyboard
provided-plant-summarized-therapy-married-involves-rocks
worked-athlete-caucus-slight-discretion-tightly-occasional
medal-ranks-habit-labor-genre-saved-remainder
spectator-municipal-longest-colleagues-demolition-enzyme-widespread

Orchard Street Long list

Lines found               : 17576
Free of exact duplicates  : true
Free of fuzzy duplicates  : true
Free of blank lines       : true
Unique words found        : 17576
No start/end whitespace   : true
No non-ASCII characters   : true
Unicode normalized        : true
Free of prefix words      : false
Uniquely decodable        : true
Above brute force line    : true
Length of shortest word   : 3 characters (add)
Length of longest word    : 15 characters (troubleshooting)
Mean word length          : 7.98 characters
Entropy per word          : 14.101 bits
Efficiency per character  : 1.767 bits
Assumed entropy per char  : 4.700 bits
Shortest edit distance    : 1
Mean edit distance        : 7.915
Longest shared prefix     : 14
Unique character prefix   : 15

Sample passphrases:
exponent-sync-memorandum-vaulted-stiffened-reverted
camps-interdependence-worsening-choral-somebody-obey
immensely-casinos-plundered-warns-vinegar-event
bottled-charge-linkage-husbands-cuisine-weave
gospel-graders-relegated-exits-determine-ducked

EFF long list

Lines found               : 7776
Free of exact duplicates  : true
Free of fuzzy duplicates  : true
Free of blank lines       : true
Unique words found        : 7776
No start/end whitespace   : true
No non-ASCII characters   : true
Unicode normalized        : true
Free of prefix words      : true
Uniquely decodable        : true
Above brute force line    : true
Length of shortest word   : 3 characters (aim)
Length of longest word    : 9 characters (zoologist)
Mean word length          : 6.99 characters
Entropy per word          : 12.925 bits
Efficiency per character  : 1.849 bits
Assumed entropy per char  : 4.308 bits
Shortest edit distance    : 1
Mean edit distance        : 6.858
Longest shared prefix     : 8
Unique character prefix   : 9

Sample passphrases:
audible-encounter-defection-democracy-canister-pencil-comma
dwindling-gangway-driving-grumbly-stoke-scanning-stimulant
overpay-dial-manlike-purposely-demeanor-unified-likeness
edition-fernlike-synthetic-aloe-filing-wrangle-spiny
tattle-reapply-borough-stature-cuddle-crummiest-flatten

Mnemonicode list

Note: I swapped the word "beatles" for "beetle", so this isn't exactly the same as the canonical Mnemonicode word list.

Lines found               : 1633
Free of exact duplicates  : true
Free of fuzzy duplicates  : true
Free of blank lines       : true
Unique words found        : 1633
No start/end whitespace   : true
No non-ASCII characters   : true
Unicode normalized        : true
Free of prefix words      : true
Uniquely decodable        : true
Above brute force line    : true
Length of shortest word   : 3 characters (ego)
Length of longest word    : 7 characters (william)
Mean word length          : 5.75 characters
Entropy per word          : 10.673 bits
Efficiency per character  : 1.857 bits
Assumed entropy per char  : 3.558 bits
Shortest edit distance    : 1
Mean edit distance        : 5.552
Longest shared prefix     : 6
Unique character prefix   : 7

Sample passphrases:
bodies-novelist-poor-feminine-plates-ideology-emeritus
specific-lighting-orbit-math-weakness-embarked-rang
session-somebody-sector-keyboards-ambassador-circle-contrasts
strand-mankind-punished-woke-deities-keyboard-camping
glass-homeless-feature-fee-preparing-interfaces-nations

EFF short list

Note: I swapped out the word "yo-yo" for the word "zen".

Lines found               : 1296
Free of exact duplicates  : true
Free of fuzzy duplicates  : true
Free of blank lines       : true
Unique words found        : 1296
No start/end whitespace   : true
No non-ASCII characters   : true
Unicode normalized        : true
Free of prefix words      : true
Uniquely decodable        : true
Above brute force line    : true
Length of shortest word   : 3 characters (aim)
Length of longest word    : 5 characters (zippy)
Mean word length          : 4.54 characters
Entropy per word          : 10.340 bits
Efficiency per character  : 2.278 bits
Assumed entropy per char  : 3.447 bits
Shortest edit distance    : 1
Mean edit distance        : 4.366
Longest shared prefix     : 4
Unique character prefix   : 5

Sample passphrases:
flame-chump-stood-slurp-saint-spent-path-putt
sax-sweep-guide-snore-knee-pod-cadet-twist
reset-mouse-track-taco-movie-oak-recap-purse
hump-dug-wifi-skid-panty-rake-vocal-stoop
silo-utter-pest-snap-zoom-crate-suds-batch

Orchard Street QWERTY list

Lines found               : 1296
Free of exact duplicates  : true
Free of fuzzy duplicates  : true
Free of blank lines       : true
Unique words found        : 1296
No start/end whitespace   : true
No non-ASCII characters   : true
Unicode normalized        : true
Free of prefix words      : false
Uniquely decodable        : true
Above brute force line    : true
Length of shortest word   : 3 characters (add)
Length of longest word    : 8 characters (referred)
Mean word length          : 4.24 characters
Entropy per word          : 10.340 bits
Efficiency per character  : 2.441 bits
Assumed entropy per char  : 3.447 bits
Shortest edit distance    : 1
Mean edit distance        : 4.170
Longest shared prefix     : 6
Unique character prefix   : 7

Sample passphrases:
think-watt-bad-unity-strip-troop-three-crab
graded-mast-mom-semi-chop-dash-far-view
dam-fare-root-quite-pill-hitter-guide-muse
man-tomb-jar-trim-tip-bits-faded-dig
young-ten-threw-shy-zero-grew-ready-dead

Orchard Street Alpha list

Lines found               : 1296
Free of exact duplicates  : true
Free of fuzzy duplicates  : true
Free of blank lines       : true
Unique words found        : 1296
No start/end whitespace   : true
No non-ASCII characters   : true
Unicode normalized        : true
Free of prefix words      : false
Uniquely decodable        : true
Above brute force line    : true
Length of shortest word   : 3 characters (add)
Length of longest word    : 7 characters (stopped)
Mean word length          : 4.12 characters
Entropy per word          : 10.340 bits
Efficiency per character  : 2.509 bits
Assumed entropy per char  : 3.447 bits
Shortest edit distance    : 1
Mean edit distance        : 4.043
Longest shared prefix     : 6
Unique character prefix   : 7

Sample passphrases:
pigs-sue-stay-week-woke-sued-pass-mayo
month-guns-half-lists-seek-pony-pine-foe
jet-troop-hung-fond-wind-lit-long-dams
loops-peer-quit-push-hank-over-doing-pain
gave-model-coil-lent-deep-lam-chin-tall

Source of randomness

Phraze uses the rand crate's ThreadRng as its cryptographically secure pseudo-random number generator (CSPRNG) for generating passphrases.

According to the rand crate documentation at the time of this writing, "ThreadRng uses the same CSPRNG as StdRng, ChaCha12.", meaning it uses 12 rounds of the ChaCha stream cipher. That StdRng uses ChaCha12 is relatively clear in the source code. (See this issue for arguments in favor of using 12 rounds rather than 20.)

Why another random passphrase generator?

There are already a few good passphrase generators, including passphraseme and Pgen.

Admittedly, part of my motivation to create Phraze was to highlight my Orchard Street Wordlists, which I think are pretty good!

For developers

I welcome both pull requests and issues.

Testing and benchmarking Phraze

Run cargo test to run Phraze's tests.

Phraze uses Criterion for benchmarking. You can run the benchmarks for yourself with cargo bench.

How to create a release

This project uses cargo-dist to create releases.

You're welcome to consult my personal notes on using cargo-dist; but basically: First, install cargo-dist withcargo install cargo-dist.

When you're ready to cut a new release, test the current state of the project with cargo dist build and cargo dist plan. If that went well, create a new git tag that matches the current project version in Cargo.toml with git tag vX.X.X. Finally, run git push --tags to kick off the release process. GitHub will handle it from here -- check your project's GitHub Releases page in about 5 to 10 minutes.

Licensing

Phraze's code is licensed under the Mozilla Public License v2.0. See included LICENSE.txt file or this online version of the license.

Word list licensing

phraze's People

Contributors

jc00ke avatar sts10 avatar westonal avatar wezm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

jc00ke westonal

phraze's Issues

Option to generate more than one passphrase at a time?

I've noticed that other similar command-line passphrase generators usually include an option for specifying how many passphrases the user wants the tool to generate.

E.g. phrazer -n 5 could generate and print 5 passphrases.

Is this a common enough use-case to build in to Phrazer? Do sys admins sometimes need to generate multiple passphrases in one go?

Add option for user to use any file as the word list

I assume this would be good for users who want a passphrase of non-English words.

It is unlikely that the user's list will be uniquely decodable (something I'm a bit of stickler about...), so I'd likely add a check like:

if custom_list.is_some() && separator=="" && !title_case {
   eprintln!("Whether inputted word list is uniquely decodable is unknown. With no separator between words or Title Case, risk of a word overlap too high to proceed.");
}

I think I'd also have Phraze check the inputted list for blank lines and duplicate words.

Mac and Windows release testers wanted

I've recently created binaries of Phraze for Mac and Windows (using cargo-dist). Unfortunately, I don't have access to a Mac or windows machine currently.

If folks could test these binaries and report back with any issues, that'd be great!

Steps to test

  1. Visit the Phraze releases page on Github
  2. Locate latest release (the top one)
  3. Download the relevant binary file for your system, e.g. phraze-aarch64-apple-darwin.tar.xz or phraze-x86_64-pc-windows-msvc.zip
  4. Run it locally and see what happens. Leave a comment on this issue, either success or failure!

"beatles" is in Mnemonicode list

groooaaaan... You'd have to be like "Beatles, as in the band" every time, lest the listener write down "beetles".

I'm tempted to replace "beatles" with "beetle". My only hesitation is deviating from the list, which seems rather canonical at this point (23 years old).

Publish `phraze` on crates.io

Publishing phraze on crates.io would be nice for folks like me who install some of the smaller helper tools they use with cargo install --locked. The name is still available too!

Licensing question: Can we use KeePassXC's word list?

I'd love to include the word list the KeePassXC password manager uses by default, which is basically the EFF long list with some nice word substitutions.

My hesitation is purely due to licensing compatibility questions. I think the KeePassXC is available under either GPL-2 or GPL-3. I deliberately chose the Mozilla Public License v2.0 for this project, as I believe it strikes a nice balance between copyleft licenses and permissive licenses.

The questions is whether I can take material from a GPL'd project and use it in an MPL2'd project. I probably knew the answer at one point but have forgotten.

Clean up main function

As noted in #14, I don't like how the main function looks right now. Specifically, how I need to have one variable for the built-in list and another for the user-submitted "custom" list.

phraze/src/main.rs

Lines 104 to 161 in d530eba

// We need two different variables here, one for a user-inputted list and another for
// the built-in list (whether chosen or the default). This is because we use different
// variable types for each case.
let (custom_list, built_in_list) = match opt.custom_list_file_path {
Some(custom_list_file_path) => (Some(read_in_custom_list(&custom_list_file_path)?), None),
None => (None, Some(fetch_list(opt.list_choice))),
};
// If a "custom_list" was given by the user, we're going to use that list.
// Otherwise we use the built-in list (a default list if the user didn't choose one).
// To get the length of the list we're going to use, we need to check if a
// custom_list was given.
let list_length = match custom_list {
Some(ref custom_list) => custom_list.len(),
None => built_in_list.unwrap().len(), // pretty sure we're safe to unwrap here...
};
// Since user can define a minimum entropy, we might have to do a little math to
// figure out how many words we need to include in this passphrase.
let number_of_words_to_put_in_passphrase = calculate_number_words_needed(
opt.number_of_words,
opt.minimum_entropy,
opt.strength_count,
list_length,
);
// If user enabled verbose option
if opt.verbose {
// print entropy information, but use eprint to only print it
// to the terminal
print_entropy(
number_of_words_to_put_in_passphrase,
list_length,
opt.n_passphrases,
);
}
// Now we can (finally) generate and print some number of passphrases
for _ in 0..opt.n_passphrases {
// Again, we have more code than we should because of this pesky list type situation...
let passphrase = match (&custom_list, built_in_list) {
(Some(ref custom_list), _) => generate_passphrase(
number_of_words_to_put_in_passphrase,
&opt.separator,
opt.title_case,
custom_list,
),
(None, Some(built_in_list)) => generate_passphrase(
number_of_words_to_put_in_passphrase,
&opt.separator,
opt.title_case,
built_in_list,
),
(None, None) => return Err("List selection error!".to_string()),
};
println!("{}", passphrase);
}

Any ideas on how to refactor this would be appreciated!

For example, is there a way to make a single Type or Struct that can take both a &' static[& 'static str] and a Vec<String>?

Implement an easy-to-use "Secure" mode

While I'm happy with the new default of 80 bits of entropy, I was thinking I could add a -S/--secure flag that guarantees that the outputted passphrase has 105 bits of entropy or more.

  • If -e minimum entropy is set to lower than 105, Phraze would ignore the flag and output a passphrase with at least 105 bits of entropy. If set to greater than 105 bits, Phraze would respect that setting.
  • If -w is set such that the resulting passphrase would have less than 105 bits, Phraze would ignore the flag.

Basically, make phraze -S an alias for phraze -e 105.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.