Generate or convert random bytes into passphrases. A Rust port of niceware.

Overview

niceware

Rust crates.io v0.6.0

My blog post: Porting Niceware to Rust


A Rust port of niceware. Sections of this README have been copied from the original project.

This library generates random-yet-memorable passwords. Each word provides 16 bits of entropy, so a useful password requires at least 3 words.

The transformation from bytes to passphrase is reversible.

Because the wordlist is of exactly size 2^16, niceware is also useful for convert cryptographic keys and other sequences of random bytes into human-readable phrases. With niceware, a 128-bit key is equivalent to an 8-word phrase.

Similar to the source, heed this warning:

WARNING: The wordlist has not been rigorously checked for offensive words. Use at your own risk.

Sample use cases

  • niceware can be used to generate secure, semi-memorable, easy-to-type passphrases. A random 3-5 word phrase in niceware is equivalent to a strong password for authentication to most online services. For instance, +8svofk0Y1o= and bacca cavort west volley are equally strong (64 bits of randomness).

  • niceware can be used to display cryptographic key material in a way that users can easily backup or copy between devices. For instance, the 128-bit random seed used to generate a 256-bit ECC key (~equivalent to a 3072-bit RSA key) is only 8 niceware words. With this 8-word phrase, you can reconstruct the entire public/private key pair.

Tests

cargo test

Credits

Rust port:

@Kixunil made some fantastic changes w/r/t idiomatic and performant Rust in #2.

Code, tests, and docs are either straight-up ported/copied from, or inspired by niceware.

Original:

Niceware was inspired by Diceware. Its wordlist is derived from the SIL English word list. This project is based on [diracdeltas] work on OpenPGP key backup for the Yahoo End-to-End project.

Comments
  • Consider renaming the crate to just `niceware` (without `rust-` prefix)

    Consider renaming the crate to just `niceware` (without `rust-` prefix)

    As per Rust API guidelines:

    Crate names should not use -rs or -rust as a suffix or prefix. Every crate is Rust! It serves no purpose to remind users of this constantly.

    niceware is not taken yet, so just renaming and re-publishing should be fine. Perhaps consider yanking the old crates (see cargo yank).

    opened by Kixunil 3
  • Design of `generate_passphrase`

    Design of `generate_passphrase`

    The function argument is now clearly named num_random_bytes but that didn't stop me from making a mistake in the example.

    Before I go ahead and fix it, I wonder if any of these approaches is better:

    • Changing it to number of words. If someone makes a mistake it at least leads to too good security instead of worse security. (Note that too many words is still bad. Also note it has nice property that it never panics due to odd count.)
    • have both fn generate_passphrase_with_entropy_bytes() and fn generate_passphrase_with_word_count() to disambiguate and perhaps make the code cleaner
    • enum Entropy { Words(u16), Bytes(u16), } and then take that enum instead.
    • struct WordCount(u16); and struct ByteCount(u16); with sealed trait Entropy. This is probably overengineered with the advantage that ByteCount could enforce even number in constructor.
    opened by Kixunil 2
  • Various changes to make the code more idiomatic and performant

    Various changes to make the code more idiomatic and performant

    Found your crate on reddit and thought that I could make a PR as the best kind of review. :)

    This makes various improvements to the code to make it more idiomatic and performant. I split them to somewhat smaller pieces that can be described more easily - see individual commit messages. One of them is quite big as it made significant changes, hope it's clear though. LMK if you don't understand something.

    opened by Kixunil 1
  • Wrap all possible errors in a new Error type instead of panicking

    Wrap all possible errors in a new Error type instead of panicking

    I've refactored both of the current error types into a new Error type and removed all sources of panics. This is to make the functions better match the constraints of the type system (e.g., bytes_to_pass_phrase can take any &[u8], but some of them are invalid). Also, I've changed num_words to be a usize; representing it as a u16 is mostly an implementation detail, since the real size check is done against MAX_PASSPHRASE_WORDS.

    opened by LegionMammal978 0
  • Make `generate_passphrase` take number of words

    Make `generate_passphrase` take number of words

    This changes generate_passphrase from taking number of bytes to taking number of words which is more natural and avoids panic. It also "fixes" documentation saying that calling the function with parameter 8 generates 128 bits of entropy. (That now becomes true statement.)

    Closes #5

    opened by Kixunil 0
  • v0.2.0

    v0.2.0

    We don't need ownership of Vec buffers in bytes_to_passphrase and passphrase_to_bytes.

    The arg to generate_passphrase can be named clearer to show it takes a random number of bytes.

    Don't expose ring's error type. Wrap it with the new RNGError to enable us to swap RNG crates in the future.

    opened by healeycodes 0
  • Implement conversion using an iterator

    Implement conversion using an iterator

    This adds BytesToPassPhraseIter which implements Iterator and related traits. This should make it possible to perform the conversion without allocations.

    Part of #6

    opened by Kixunil 0
  • Expose iterators in API

    Expose iterators in API

    Instead of taking/returning slice/Vec<...> the functions could take impl Iterator<Item=[u8; 2]>/return impl Iterator<Item=...> so that callers that don't need Vec do not need to allocate at all. (E.g. this is the case if the user wants to just write out the passphrase.) Requiring Item=[u8; 2] also side steps the evenness check completely.

    I think with these adjustments it should be possible to make whole crate allocation-free. The current methods can be kept for backwards compatibility or as helpers for people who don't want to mess with iterators

    opened by Kixunil 0
  • Consider exposing word from `UnknownWordError`

    Consider exposing word from `UnknownWordError`

    Inspecting specific word that is unknown may be useful to some callers but adding a method to retrieve it basically commits to always storing it within error type. I think it's very reasonable to expect that it will always be there but opened an issue just in case. The suggested method is:

    /// The word that is not known
    fn word(&self) -> &str {
        &self.word
    }
    

    An alternative would be to continue scanning the words even after error and return a slice of all unknown words.

    opened by Kixunil 0
Owner
Andrew Healey
Software engineer / writer
Andrew Healey
A port of TinySMPC into Rust.

smol-mpc Smol-mpc is a tiny library to learn Secure Multiparty Computation (MPC) basics using the Rust programming language. Smol-mpc allows to the us

HashCloak 13 Sep 22, 2023
A Bitcoin wallet collider that brute forces random wallet addresses written in Rust.

Plutus-Rustus Bitcoin Brute Forcer A Bitcoin wallet collider that brute forces random wallet addresses written in Rust. This is a straight port of Plu

null 46 Dec 23, 2022
CypherSmith is a random cypher generator for OpenCypher.

CypherSmith is a random cypher generator for OpenCypher. Its paragon is SQLsmith, a random SQL query generator.

Haizhi Technologies 15 Dec 1, 2022
A fast, simple and powerful open-source cross platform utility tool for generating strong, unique and random passwords

password-generator-pro A fast, simple and powerful open-source cross platform utility tool for generating strong, unique and random passwords. Feature

Sebastien Rousseau 3 Dec 16, 2022
Convert private keys to PKCS#8 format in pure Rust

topk8 Convert private keys to PKCS#8 format in pure Rust. The following formats are supported at the moment: PKCS#1 PEM (RSA PRIVATE KEY) SEC1 PEM (EC

kazk 1 Dec 10, 2021
Convert rust coverage data to HTML reports, LCOV files or terminal tables

Coverage Prepare Convert coverage data to HTML reports, LCOV files or terminal tables. coverage-prepare --help: Convert "profraw" coverage data to: *

Samuel Colvin 3 Aug 23, 2022
convert CHAIN format to PAF format

convert CHAIN format to PAF format

Andrea Guarracino 9 May 24, 2022
A Rust port of the password primitives used in Django Project.

Rust DjangoHashers A Rust port of the password primitives used in Django Project. Django's django.contrib.auth.models.User class has a few methods to

Ronaldo Ferreira 52 Nov 17, 2022
Port path module (and tests) of nodejs to rust using the same algorithms.

rusty_nodejs_path Port path module (and tests) of nodejs to rust using the same algorithms. crates.io Documents Progress posix path.basename(path[, ex

Yunfei He 10 Sep 25, 2022
A Rust port of the password primitives used in Django Project.

Rust DjangoHashers A Rust port of the password primitives used in Django Project. Django's django.contrib.auth.models.User class has a few methods to

Ronaldo Ferreira 52 Nov 17, 2022
This is a port in the arkwork framework of the original implementation in bellperson of Snarkpack.

Snarpack on arkwork This is a port in the arkwork framework of the original implementation in bellperson of Snarkpack. Note both works are derived fro

Nicolas Gailly 13 Aug 5, 2022
A rust binding for nodejs to generate md5 hash value

Hasher A rust binding for creating node module to generate md5 hash value This project was bootstrapped by create-neon. Installing hasher Installing h

Md. Al-Amin 0 Nov 7, 2021
CLI tool written in Rust which can be used to generate hashes

rustgenhash rustgenhash is a tool to generate hashes on the commandline from stdio. It can be used to generate single or multiple hashes for usage in

Volker Schwaberow 11 Dec 29, 2022
Generate Nice Solana Address By Template

Yes, I know about GPU generators. https://smith-mcf.medium.com/solana-vanity-address-using-gpus-5a68ad94d1d4 ./solana-nice-address --help solana-nice-

Kirill Fomichev 18 Jun 18, 2022
Vanitygen-bip39 - Generate vanity / gas efficient Ethereum addresses for your hdwallet (bip39 12 or 24 words)

vanitygen-bip39 Generate Ethereum gas efficient addresses with leading zeros https://medium.com/coinmonks/on-efficient-ethereum-addresses-3fef0596e263

iam4x 9 Jul 2, 2022
A minimal esp-hal application template for use with cargo-generate

{{ project-name }} A minimalist template for use with cargo-generate to create no_std applications targeting Espressif's line of SoCs and modules. At

esp-rs 35 Dec 29, 2022
Generate IPv4 12th order Hilbert heatmaps from a file of IPv4 addresses.

Rustified IPv4 Heatmap This is a pure Rust version of the C ipv4-heatmap utility originally published by The Measurement Factory and updated forever-a

boB Rudis 8 Sep 28, 2022
Generate Nix fetcher calls from repository URLs [maintainer=@figsoda]

nurl Generate Nix fetcher calls from repository URLs $ nurl https://github.com/nix-community/patsh v0.2.0 2>/dev/null fetchFromGitHub { owner = "nix

Nix community projects 103 Jan 29, 2023
cargo-generate template for Criterion benchmarks

Criterion Benchmark Template This is a cargo-generate template for quickly creating benchmarks using the Criterion benchmarking framework. Usage $ car

Lily Mara 4 Jan 19, 2023