# NAME

CtrlO::Crypt::XkcdPassword - Yet another xkcd style password generator

# VERSION

version 1.010

# SYNOPSIS

    use CtrlO::Crypt::XkcdPassword;
    my $password_generator = CtrlO::Crypt::XkcdPassword->new;

    say $password_generator->xkcd;
    # LimousineAllegeClergymanEconomic

    say $password_generator->xkcd( words => 3 );
    # ObservantFiresideMacho

    say $password_generator->xkcd( words => 3, digits => 3 );
    # PowerfulSpreadScarf645

    # Use custom word list
    CtrlO::Crypt::XkcdPassword->new(
      wordlist => '/path/to/wordlist'
    );
    CtrlO::Crypt::XkcdPassword->new(
      wordlist => 'Some::Wordlist::From::CPAN'
    );

    # Use another source of randomness (aka entropy)
    CtrlO::Crypt::XkcdPassword->new(
      entropy => Data::Entropy::Source->new( ... );
    );

# DESCRIPTION

`CtrlO::Crypt::XkcdPassword` generates a random password using the
algorithm suggested in [https://xkcd.com/936/](https://xkcd.com/936/): It selects 4 words
from a curated list of words and combines them into a hopefully easy
to remember password (actually a passphrase, but we're all trying to
get things done, so who cares..).

See [this
explaination](https://www.explainxkcd.com/wiki/index.php/936:_Password_Strength)
for detailed information on the security of passwords generated from a
known word list.

But [https://xkcd.com/927/](https://xkcd.com/927/) also applies to this module, as there are
already a lot of modules on CPAN implementing
[https://xkcd.com/936/](https://xkcd.com/936/). We still wrote a new one, mainly because we
wanted to use a strong source of entropy and a fine-tuned word list.

# METHODS

## new

    my $pw_generator = CtrlO::Crypt::XkcdPassword->new;

Initialize a new object. Uses `CtrlO::Crypt::XkcdPassword::Wordlist::en_gb`
as a word list per default. The default entropy is based on
`Crypt::URandom`, i.e. `/dev/urandom` and should be random enough (at
least more random than plain old `rand()`).

If you want / need to supply another source of entropy, you can do so
by setting up an instance of `Data::Entropy::Source` and passing it
to `new` as `entropy`.

    my $pw_generator = CtrlO::Crypt::XkcdPassword->new(
        entropy => Data::Entropy::Source->new( ... )
    );

To use one of the included language-specific word lists, do:

    my $pw_generator = CtrlO::Crypt::XkcdPassword->new(
        language => 'en-GB',
    );

Available languages are:

- en-GB

You can also provide your own custom word list, either in a file:

    my $pw_generator = CtrlO::Crypt::XkcdPassword->new(
        wordlist => '/path/to/file'
    );

Or in a module:

    my $pw_generator = CtrlO::Crypt::XkcdPassword->new(
        wordlist => 'My::Wordlist'
    );

See ["DEFINING CUSTOM WORD LISTS"](#defining-custom-word-lists) for more info.

## xkcd

    my $pw = $pw_generator->xkcd;
    my $pw = $pw_generator->xkcd( words  => 3 );
    my $pw = $pw_generator->xkcd( digits => 2 );

Generate a random, xkcd-style password.

Per default will return 4 randomly chosen words from the word list,
each word's first letter turned to upper case, and concatenated
together into one string:

    $pw_generator->xkcd;
    # CorrectHorseBatteryStaple

You can get a different number of words by passing in `words`. But
remember that anything smaller than 3 will probably make for rather
poor passwords, and anything bigger than 7 will be hard to remember.

You can also pass in `digits` to append a random number consisting of
`digits` digits to the password:

    $pw_generator->xkcd( words => 3, digits => 2 );
    # StapleBatteryCorrect75

# DEFINING CUSTOM WORD LISTS

Please note that `language` is only supported for the word lists
included in this distribution.

## in a plain file

Put your word list into a plain file, one line per word. Install this
file somewhere on your system. You can now use your word list like
this:

    CtrlO::Crypt::XkcdPassword->new(
      wordlist => '/path/to/wordlist'
    );

## in a Perl module using the Wordlist API

[Perlancar](https://metacpan.org/author/PERLANCAR) came up with a unified API for various word list modules,
implemented in [Wordlist](https://metacpan.org/pod/WordList). Pack
your list into a module adhering to this API, install the module, and
load your word list:

    CtrlO::Crypt::XkcdPassword->new(
      wordlist => 'Your::Cool::Wordlist'
    );

You can check out [CtrlO::Crypt::XkcdPassword::Wordlist::en\_gb](https://metacpan.org/pod/CtrlO%3A%3ACrypt%3A%3AXkcdPassword%3A%3AWordlist%3A%3Aen_gb) (included in
this distribution) for an example. But it's really quite simple: Just
subclass `Wordlist` and put your list of words into the `__DATA__`
section of the module, one line per word.

## in a Perl module using the Crypt::Diceware API

David Golden uses a different API in his [Crypt::Diceware](https://metacpan.org/pod/Crypt%3A%3ADiceware) module,
which inspired the design of [CtrlO::Crypt::XkcdPassword](https://metacpan.org/pod/CtrlO%3A%3ACrypt%3A%3AXkcdPassword). To use one
of those word lists, use:

    CtrlO::Crypt::XkcdPassword->new(
      wordlist => 'Crypt::Diceware::Wordlist::Common'
    );

(yes, this looks just like when using `Wordlist`. We inspect the
wordlist module and try to figure out what kind of API you're using)

To create a module using the [Crypt::Diceware](https://metacpan.org/pod/Crypt%3A%3ADiceware) wordlist API, just
create a package containing a public array `@Words` containing your
word list.

# WRAPPER SCRIPT

This distributions includes a simple wrapper script, [pwgen-xkcd.pl](https://metacpan.org/pod/pwgen-xkcd.pl).

# RUNNING FROM GIT

This is **not** the recommended way to install / use this module. But
it's handy if you want to submit a patch or play around with the code
prior to a proper installation.

## Carton

    git clone git@github.com:domm/CtrlO-Crypt-XkcdPassword.git
    carton install
    carton exec perl -Ilib -MCtrlO::Crypt::XkcdPassword -E 'say CtrlO::Crypt::XkcdPassword->new->xkcd'

## cpanm & local::lib

    git clone git@github.com:domm/CtrlO-Crypt-XkcdPassword.git
    cpanm -L local --installdeps .
    perl -Mlocal::lib=local -Ilib -MCtrlO::Crypt::XkcdPassword -E 'say CtrlO::Crypt::XkcdPassword->new->xkcd'

# SEE ALSO

Inspired by [https://xkcd.com/936/](https://xkcd.com/936/) and [https://xkcd.com/927/](https://xkcd.com/927/).

There are a lot of similar modules on CPAN, so we just point you to
[Neil Bower's comparison of CPAN modules for generating passwords](http://neilb.org/reviews/passwords.html).

## But why did we write yet another module?

- Good entropy

    Most of the password generating modules just use `rand()`, which "is
    not cryptographically secure" (according to perldoc).
    `CtrlO::Crypt::XkcdPassword` uses [Crypt::URandom](https://metacpan.org/pod/Crypt%3A%3AURandom) via
    [Data::Entropy](https://metacpan.org/pod/Data%3A%3AEntropy), which provides good entropy while still being portable.

- Good word list

    While [Crypt::Diceware](https://metacpan.org/pod/Crypt%3A%3ADiceware) has good entropy, we did not like its word
    lists. Of course we could have just provided a word list better suited
    to our needs, but we wanted it to be very easy to generate xkcd-style
    passwords.

- Easy API

    `my $pwd = CtrlO::Crypt::XkcdPassword->new->xkcd` returns 4 words
    starting with an uppercase letter as a string, which is our main use
    case. Nevertheless, the API also allows for more or fewer words, or
    even some digits.

- Fork save
- [https://xkcd.com/927/](https://xkcd.com/927/)

# THANKS

- Thanks to [Ctrl O](http://www.ctrlo.com/) for funding the development of this module.
- We learned the usage of `Data::Entropy` from
[https://metacpan.org/pod/Crypt::Diceware](https://metacpan.org/pod/Crypt::Diceware), which also implements an
algorithm to generate a random passphrase.
- [m\_ueberall](https://twitter.com/m_ueberall/status/965263922310909952)
for pointing out
[https://www.explainxkcd.com/wiki/index.php/936:\_Password\_Strength](https://www.explainxkcd.com/wiki/index.php/936:_Password_Strength)

# AUTHOR

Thomas Klausner <domm@plix.at>

# COPYRIGHT AND LICENSE

This software is copyright (c) 2018 - 2021 by Thomas Klausner.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
