diceware-list
=============

|bdg-build| `sources <https://github.com/ulif/diceware-list>`_ | `issues <https://github.com/ulif/diceware-list/issues>`_

.. |bdg-build| image:: https://travis-ci.org/ulif/diceware-list.svg?branch=master
    :target: https://travis-ci.org/ulif/diceware-list
    :alt: Build Status

Create and check wordlists for use with `diceware`_.

This is not a `diceware`_ implementation, but a helper to create appropriate
wordlists.

Currently, we provide three scripts:

  - `diceware-list` create wordlists based on input lists
  - `wlflakes` checks existing wordlists for flaws
  - `wldownload` downloads Android wordlists


Install
--------

Install latest release from pypi_ ::

  (venv) $ pip install diceware-list

or clone repository from github::

  $ git clone https://github.com/ulif/diceware-list.git

Please consider using `virtualenv`_ for deployment.

In an active `virtualenv` you can install an executable script of
`diceware-list` running::

  (venv) $ python setup.py install
  (venv) $ diceware-list --help
  usage: diceware-list [-h] [-l LENGTH] [-n] [--ascii] [-d SIDES] [-k]
                       [--use-416] [-p {none,short,long}] [-v] [--version]
                       DICTFILE [DICTFILE ...]


Create Wordlists: `diceware-list`
---------------------------------

The `diceware-list` script creates new lists out of given ones::

  $ diceware-list -n -l 7776 /usr/share/dict/words
  11111 a
  11112 a's
  ...
  12353 capt
  12354 cara
  12355 carl
  ...
  66663 zoos
  66664 éclat
  66665 élan
  66666 épée

The main target of `diceware-list` is to provide "good"
wordlists. Wordlists are considered "good" if they

- contain enough terms for use with a certain diceware application
  (for instance 6^6 = 7776 terms if used with six six-sided dice)
- contain terms as short as possible (to reduce typing)
- (optionally) contain no words with non-ASCII chars (to enable use
  with non-localized keyboards)
- (optionally) are a `prefix code`_, i.e. no complete word in the list is
  prefix of another word in the list.
- contain no offending terms

The last topic is hard to solve technically (hints welcome!), but
`diceware-list` can help to follow the other design rules.

The wordlists generated by `diceware-list` are not meant to be kept
secret. You might put them on the internet, publish on facebook or
print them in the New York Times. Instead the security of the
`diceware`_ technique relies on the entropy or (in this case)
"randomness" of your dice, computer, etc.

In other words: Your passphrases will not be safe because of hiding
your wordlist. They will be safe because there are so many possible
combinations of words you can pick from your wordlist. That means:
longer lists are more secure than shorter ones (if really used to full
extent by your source of randomness with `diceware`_), but hidden
lists are *not* more secure than public ones.


Usage
-----

First, you need a file with words as "dictionary". On typical Debian
systems such files can be found in ``/usr/share/dicts/``.

This file can then be fed to `diceware-list` to create a wordlist
suitable for use with diceware.::

  $ diceware-list /usr/share/dict/words
  !
  !!
  !!!
  ...
  alan
  alana
  alar
  ...
  zzz
  zzzz

By default all input words are filtered and output. Using the `-l` option you
can request a certain length of the output wordlist. If an input list provides
more terms than needed, we will pick a subset. If there are not enough terms in
the input list, an error is raised.

With `-n` you can tell `diceware-list` to put numbers into each line,
representing dice throws [#]_ ::


  $ diceware_list -n -l 7776 /usr/share/dict/words
  11111 !
  11112 !!
  ...
  12353 alan
  12354 alana
  12355 alar
  ...
  66665 zzz
  66666 zzzz

If you create a wordlist for use with non-standard dice, for instance for
10-sided dice, then you can tell with `-d` like this::

  $ diceware_list -n -d 10 -l 10000 /usr/share/dict/words
  1-1-1-1 aol
  1-1-1-2 aachen
  1-1-1-3 aaron
  ...
  10-10-10-8 zoomed
  10-10-10-9 zooms
  10-10-10-10 zoos

The `--ascii` option filters terms out, that contain non-ASCII
characters. This can help in generating non-english word lists that
are usable with regular english keyboards.

The verbose option `--verbose` can be given multiple times to increase
verbosity.

See `--help` for other options.

`diceware-list` follows loosely the recommendations given on
http://diceware.com/ by Mr. Reinhold.


Check wordlists: wlflakes
-------------------------

Find flakes in wordlists.

::
  $ wlflakes mywordlist.txt

No output means: no problems detected.

Currently, only prefix flakes are checked. I.e., we check, whether any line in
the given file is the beginning of any other line.

::
  $ cat wordlist.txt
  air
  port
  airport

  $ wlflakes wordlist.txt
  wordlist.txt:3: E1 "air" from line 1 is a prefix of "airport"

Also `wlflakes` supports ``--help`` or ``-h`` to list all options supported.


Handle Android wordlists: wldownload
------------------------------------

Android wordlists are a nice source for wordlists. They can be downloaded from
public repositories::

  $ wldownload --raw -v
  Starting download of Android wordlist file.
  Fetching wordlist from https://android.googlesource.com/platform/pack...
  Done.

`wldownload` downloads these lists and helps to transform them into lists
usable for diceware. Be aware, that terms from lists are output on stdout by
default (and Android wordlists contain easily more than 100,000 terms)::

  $ wldownload > mylist
  $ cat mylist
  the
  to
  ...
  yt
  yuk

Terms are output on stdout by default (use shell redirects or ``--outfile`` to
change that behaviour).

You can request non-english wordlists using ``--lang`` or ``-l`` with a
language code like ``cs`` or ``de``. Use ``--lang-codes`` to list all supported
language codes.

The ``--no-offensive`` flag suppresses terms marked as possibly offensive.



Testing
-------

In a clone of the sources you can run tests like this::

  (venv) $ python setup.py test

This command will download all required packages, especially
`py.test`_.

You can also install `py.test`_ manually with `pip`_::

  (venv)$ pip install pytest
  (venv)$ pip install -e .

and afterwards run tests like so::

  (venv)$ py.test

If you also install `tox`::

  (venv)$ pip install tox

then you can run all tests for all supported platforms at once::

  (venv)$ tox


Coverage
--------

To get a coverage report, you can use the respective `tox` target::

  (venv)$ tox -e cov

Or you use the common `coverage` tool::

  (venv)$ pip install coverage
  (venv)$ coverage run setup.py test
  (venv)$ coverage report --include="diceware_list.py,libwordlist.py"


.. [#] The wordlist length in this case should be
       ``(number-of-sides-per-dice)`` powered to
       ``(number-of-dicethrows)``, for instance 6**5 = 7776 for five
       six-sided dice or a single six-sided dice thrown five times.

.. _diceware: http://diceware.com/
.. _pip: https://pip.pypa.io/en/latest/
.. _`prefix code`: https://en.wikipedia.org/wiki/Prefix_code
.. _py.test: https://pytest.org/
.. _pypi: https://pypi.python.org/
.. _virtualenv: https://virtualenv.pypa.io/
