diceware

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: BSD-3-Clause Imports: 11 Imported by: 0

README

diceware

A small Go library for generating Diceware passphrases from a wordlist of your choice.

diceware only implements the generation logic — it does not ship with any embedded wordlist. This keeps the library free of third-party licensing concerns and lets you use any wordlist you trust, such as the EFF long wordlist or one in your own language.

Features

  • Configurable passphrase length (number of words)
  • Optional trailing digit group (word-word-word-482)
  • Optional scattered digits, inserted at random positions within the words (w4rd-wo9rd-word)
  • Optional capitalization
  • Estimated entropy (in bits) for every generated passphrase
  • No embedded dependencies, no network calls, cryptographically secure randomness (crypto/rand)

Install

go get codeberg.org/mrclippy/diceware

Usage

package main

import (
	"fmt"
	"log"

	"codeberg.org/mrclippy/diceware"
)

func main() {
	d := diceware.New()

	// download a wordlist you trust, e.g. the EFF long wordlist:
	// https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt
	if err := d.Load("eff_large_wordlist.txt"); err != nil {
		log.Fatal(err)
	}

	// 6 words, 3 trailing digits, capitalized, no scattering
	if err := d.Configure(6, 3, true, false); err != nil {
		log.Fatal(err)
	}

	p, err := d.Gen()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(p.Phrase())   // e.g. [Cactus River Ember Frost Willow Amber 482]
	fmt.Println(p.Entropy())  // estimated entropy in bits
}

Wordlist format

Load expects a plain text file with one entry per line, in the form:

<dice code> <word>
  • The dice code is a string of digits 16.
  • All dice codes in the file must have the same length, between 4 and 8 digits.
  • The number of valid entries must exactly match 6^len(code) (e.g. a 5-digit wordlist must contain exactly 7776 entries).
  • Lines that don't match this format — blank lines, comments, headers — are silently skipped, so wordlists with license headers or metadata at the top work fine.

Example (5-digit codes, as used by the EFF long wordlist):

11111 abacus
11112 abdomen
11113 abdominal
...

API

Function Description
New() *DiceWare Creates a generator with the default configuration (6 words, no digits, no caps).
(*DiceWare) Load(path string) error Loads a wordlist from disk.
(*DiceWare) LoadReader(r io.Reader) error Loads a wordlist from any io.Reader (a file, a string, an embedded asset, etc.).
(*DiceWare) Configure(words, digits uint, caps, scattered bool) error Updates the generator's configuration.
(*DiceWare) Gen() (*passphrase, error) Generates a new passphrase. Requires a wordlist to be loaded first.
(passphrase) Phrase() []string Returns the generated words.
(passphrase) Entropy() float64 Returns the estimated entropy, in bits.

Full documentation is available on pkg.go.dev once published.

Testing

go test ./...

License

BSD-3-Clause. See LICENSE.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DiceWare

type DiceWare struct {
	// contains filtered or unexported fields
}

DiceWare generates Diceware passphrases from a loaded wordlist. The zero value is not ready for use; create one with New.

func New

func New() *DiceWare

New creates a DiceWare generator with the default configuration: 6 words, no appended digits, no capitalization, no digit scattering. A wordlist must be loaded separately via Load before calling Gen.

func (*DiceWare) Configure

func (d *DiceWare) Configure(
	words uint,
	digits uint,
	caps bool,
	scattered bool,
) error

Configure updates the generator's configuration.

words is the number of words in the generated passphrase and must be greater than zero; Configure returns an error otherwise.

digits is the number of random digits to add to the passphrase. If scattered is false, the digits are appended as a single trailing group (e.g. "word-word-word-482"); if true, they are inserted one at a time at random positions within the words themselves.

caps capitalizes the first letter of each word and lowercases the rest.

func (*DiceWare) Gen

func (d *DiceWare) Gen() (*passphrase, error)

Gen generates a new passphrase using the current configuration and loaded wordlist.

A wordlist must have been loaded via Load beforehand; Gen returns an error otherwise. Gen also returns an error if the configured word count is zero or if the wordlist size is inconsistent with the configured dice code length.

func (*DiceWare) Load

func (d *DiceWare) Load(path string) error

Load reads a Diceware wordlist from path and prepares the generator to use it, replacing any previously loaded wordlist.

The file must contain one entry per line in the form "<dice code> <word>", where the dice code is a run of digits 1-6 with a consistent length (4 to 8) across the whole file, and the total number of valid entries must exactly match 6^len(code). Lines that don't match this format (blank lines, comments, headers) are skipped.

Load returns an error if path does not exist, is a directory, or the file contains a malformed or incomplete wordlist (including duplicate dice codes).

func (*DiceWare) LoadReader

func (d *DiceWare) LoadReader(r io.Reader) error

LoadReader loads a wordlist from r, replacing any previously loaded wordlist. See Load for the expected format.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL