How to generate a secure password?

There are no 100% secure passwords. Cracking any password is just a matter of time. But as programmers, we can make it harder.

Daily I use Ubuntu. The solutions provided will therefore apply to this environment. But these solutions are available on various Linux distributions.

Little improvisation

This way is to use Linux commands and a dictionary file. The shuf command will randomize a few words. And tr will remove the enters and this way we get a long password. Long doesnโ€™t mean safe.

$ shuf -n8 /usr/share/dict/words | tr -d '\n'
PentaxAlsopwigwamsunsureexplorationsupposedlyattiresignalling

This idea is taken from Stack Overflow. I strongly advise against generating a password in this way.

pwgen

Pwgen is a tool for automatic password generation. Pwgen generates random, meaningless but pronounceable passwords. The term pronounceable and a password of several dozen letters are in my opinion an oxymoron. The generated passwords include only lowercase letters, or upper and lower case mixed, or digits. For better memorization, capital letters and numbers are placed in the appropriate positions. It gives the impression of constructed words. The pwgen command with no parameters will generate 160 eight-characters passwords. Usually, one password is needed. Moreover, eight letters in a password are definitely not enough.

Click here to see how to install pwgen.

Installing pwgen:

$ sudo apt install pwgen
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  pwgen
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 17,4 kB of archives.
After this operation, 53,2 kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com/ubuntu lunar/universe amd64 pwgen amd64 2.08-2build1 [17,4 kB]
Fetched 17,4 kB in 0s (81,5 kB/s)
Selecting previously unselected package pwgen.
(Reading database ... 351738 files and directories currently installed.)
Preparing to unpack .../pwgen_2.08-2build1_amd64.deb ...
Unpacking pwgen (2.08-2build1) ...
Setting up pwgen (2.08-2build1) ...
Processing triggers for man-db (2.11.2-1) ...


To generate 1 password with 32 characters:

$ pwgen 32 1
gugoqu0Ziu4unguori7Ehooroo4eic1o

Need more characters in your password? No problem.

$ pwgen 48 1
ahr6ejei4uithohloh9aib8IeY4zu4KaecuGheijo0IngooV

Even more password characters? Your wish is my command.

$ pwgen 64 1
eem1Aighehupuaphie5eo5Apah3baataegahxiec3quenaeMieH6eiMaj9hai0Oh
Click here to see a pwgen parameter list.

$ pwgen -h
Usage: pwgen [ OPTIONS ] [ pw_length ] [ num_pw ]

Options supported by pwgen:
  -c or --capitalize
        Include at least one capital letter in the password
  -A or --no-capitalize
        Don't include capital letters in the password
  -n or --numerals
        Include at least one number in the password
  -0 or --no-numerals
        Don't include numbers in the password
  -y or --symbols
        Include at least one special symbol in the password
  -r <chars> or --remove-chars=<chars>
        Remove characters from the set of characters to generate passwords
  -s or --secure
        Generate completely random passwords
  -B or --ambiguous
        Don't include ambiguous characters in the password
  -h or --help
        Print a help message
  -H or --sha1=path/to/file[#seed]
        Use sha1 hash of given file as a (not so) random generator
  -C
        Print the generated passwords in columns
  -1
        Don't print the generated passwords in columns
  -v or --no-vowels
        Do not use any vowels so as to avoid accidental nasty words


Regarding security, I think itโ€™s worth reading the Anarcat post. The author strongly advises against using pwgen.

apg

APG means Automated Password Generator.

Click here to see how to install apg.

Installing apg:

$ sudo apt install apg
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  apg
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 41,3 kB of archives.
After this operation, 117 kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com/ubuntu jammy/main amd64 apg amd64 2.2.3.dfsg.1-5build2 [41,3 kB]
Fetched 41,3 kB in 0s (195 kB/s)
Selecting previously unselected package apg.
(Reading database ... 400219 files and directories currently installed.)
Preparing to unpack .../apg_2.2.3.dfsg.1-5build2_amd64.deb ...
Unpacking apg (2.2.3.dfsg.1-5build2) ...
Setting up apg (2.2.3.dfsg.1-5build2) ...
Processing triggers for man-db (2.10.2-1) ...


apg uses two algorithms to generate passwords. The first is based on an algorithm for generating pronounced passwords. The second is an algorithm for generating passwords with random characters. This first algorithm is outdated. His vulnerabilities were discussed at the National Computer Security Conference. This second algorithm has 35 configurable operating modes.

The apg command generates several passwords by default.

$ apg
^ovWiffAsdelv1 (CIRCUMFLEX-ov-Wiff-As-delv-ONE)
Opp\knis8 (Opp-BACKSLASH-knis-EIGHT)
tyob9Ok* (tyob-NINE-Ok-ASTERISK)
Igyat2orIct[ (Ig-yat-TWO-or-Ict-LEFT_BRACKET)
;ojWiuxCund4 (SEMICOLON-oj-Wi-ux-Cund-FOUR)
VuodecDis5op< (Vu-od-ec-Dis-FIVE-op-LESS_THAN)

To generate 1 password with 64 characters, type:

$ apg -m 64 -n 1
AtnokFuvWapIllAwkugheidijviFasOrIzyictUnveyzMobavArdOkWockyiesBu

By adding the parameter -a 0 you can use the first algorithm:

$ apg -a 0 -m 64 -n 1
riWrovDisickuAbpoovhyijyatyicdoupIalneDrojeuvwochanVafJeucgutoob

And the parameter -a 1 uses the second algorithm:

$ apg -a 1 -m 64 -n 1
zB;W&)dg(_1!{eZ@wBxkOO/x7<:DU5k]u3TW\aTgs.nK$rT\5"FKYBy(WKrpR-qA
Click here to see a apg parameter list.

$ apg -h

apg   Automated Password Generator
        Copyright (c) Adel I. Mirzazhanov

apg   [-a algorithm] [-r file]
      [-M mode] [-E char_string] [-n num_of_pass] [-m min_pass_len]
      [-x max_pass_len] [-c cl_seed] [-d] [-s] [-h] [-y] [-q]

-M mode         new style password modes
-E char_string  exclude characters from password generation process
-r file         apply dictionary check against file
-b filter_file  apply bloom filter check against filter_file
                (filter_file should be created with apgbfm(1) utility)
-p substr_len   paranoid modifier for bloom filter check
-a algorithm    choose algorithm
                 1 - random password generation according to
                     password modes
                 0 - pronounceable password generation
-n num_of_pass  generate num_of_pass passwords
-m min_pass_len minimum password length
-x max_pass_len maximum password length
-s              ask user for a random seed for password
                generation
-c cl_seed      use cl_seed as a random seed for password
-d              do NOT use any delimiters between generated passwords
-l              spell generated password
-t              print pronunciation for generated pronounceable password
-y              print crypted passwords
-q              quiet mode (do not print warnings)
-h              print this help screen
-v              print version information


This solution is a bit outdated but still available in packages.

diceware

Diceware creates memorizable passphrases from wordlists and various sources of randomness.

Click here to see how to install diceware.

Installing diceware:

$ sudo apt install diceware
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  diceware
0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded.
Need to get 98,7 kB of archives.
After this operation, 408 kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com/ubuntu jammy/universe amd64 diceware all 0.9.6-1 [98,7 kB]
Fetched 98,7 kB in 0s (458 kB/s)
Selecting previously unselected package diceware.
(Reading database ... 399541 files and directories currently installed.)
Preparing to unpack .../diceware_0.9.6-1_all.deb ...
Unpacking diceware (0.9.6-1) ...
Setting up diceware (0.9.6-1) ...
Processing triggers for man-db (2.10.2-1) ...


Running diceware generates a password that consists of 6 words (default).

$ diceware
SlipsTrumpetSariWaxIdeaDare

Of course, the number of words in the password can be changed.

$ diceware -n 10
SlamsZealWhoseTineLoomAnagramMossBrimBleatIsotope

An interesting option is the possibility of rolling real dice. I used this option once. As humans, I think weโ€™re too lazy.

$ diceware -r realdice
Please roll 5 dice (or a single dice 5 times).
What number shows dice number 1?
...
What number shows dice number 5?
SoundLimaQuakeCaptainPrudeFrost

Such passwords are probably easier to remember. Are these passwords more secure? This is a matter for discussion.

Click here to see a diceware parameter list.

The diceware parameter list is as follows:

$ diceware -h
usage: diceware [-h] [-n NUM] [-c | --no-caps] [-s NUM] [-d DELIMITER]
                [-r SOURCE] [-w NAME] [--dice-sides N] [-v] [--version]
                [INFILE]

Create a passphrase

positional arguments:
  INFILE                Input wordlist. `-' will read from stdin.

optional arguments:
  -h, --help            show this help message and exit
  -n NUM, --num NUM     number of words to concatenate. Default: 6
  -c, --caps            Capitalize words. This is the default.
  --no-caps             Turn off capitalization.
  -s NUM, --specials NUM
                        Insert NUM special chars into generated word.
  -d DELIMITER, --delimiter DELIMITER
                        Separate words by DELIMITER. Empty string by default.
  -r SOURCE, --randomsource SOURCE
                        Get randomness from this source. Possible values:
                        `realdice', `system'. Default: system
  -w NAME, --wordlist NAME
                        Use words from this wordlist. Possible values: `en',
                        `en_eff', `en_orig', `en_securedrop'. Wordlists are
                        stored in the folder displayed below. Default:
                        en_securedrop
  -v, --verbose         Be verbose. Use several times for increased verbosity.
  --version             output version information and exit.

Arguments related to `realdice' randomsource:
  --dice-sides N        Number of sides of dice. Default: 6

Wordlists are stored in /usr/lib/python2.7/dist-packages/diceware/wordlists


Password manager

Most password managers have a password generation feature. KeePassXC allows us to generate a password in the console.

Generate a password with 32 alphanumeric characters.

$ keepassxc-cli generate --lower --upper --numeric --length 32
oQJHaq7WeuTMJpSrKb2FKvJKFkujYRgc

We can also generate a passphrase with 8 words.

$ keepassxc-cli diceware --words 8
alphabet shape dictate blog faster comprised correct math

Generating passwords in Ruby

One way is to use the SecureRandom library.

require 'securerandom'
SecureRandom.alphanumeric(16)

The above Ruby code can be triggered from the command line.

Generating a 16-character password.

$ ruby -e "require 'securerandom'; puts SecureRandom.alphanumeric(16)"
khcGT6LbcCHdW1xs

Generating a 32-character password.

$ ruby -e "require 'securerandom'; puts SecureRandom.alphanumeric(32)"
XysKQb3CFaZxviWJUlPuEweLniIQt8J3

Is it worth using password generators?

Yes of course. Mainly because each of us has our own behavioral profile. Itโ€™s easier to crack a person than a strong password.