Random password generator

From Infogalactic: the planetary knowledge core
Jump to: navigation, search

Lua error in package.lua at line 80: module 'strict' not found. A random password generator is software program or hardware device that takes input from a random or pseudo-random number generator and automatically generates a password. Random passwords can be generated manually, using simple sources of randomness such as dice or coins, or they can be generated using a computer.

While there are many examples of "random" password generator programs available on the Internet, generating randomness can be tricky and many programs do not generate random characters in a way that ensures strong security. A common recommendation is to use open source security tools where possible, since they allow independent checks on the quality of the methods used. Note that simply generating a password at random does not ensure the password is a strong password, because it is possible, although highly unlikely, to generate an easily guessed or cracked password. In fact there is no need at all for a password to have been produced by a perfectly random process: it just needs to be sufficiently difficult to guess.

A password generator can be part of a password manager. When a password policy enforces complex rules, it can be easier to use a password generator based on that set of rules than to manually create passwords.

The naive approach

Lua error in package.lua at line 80: module 'strict' not found. Here are two code samples that a programmer who is not familiar with the limitations of the random number generators in standard programming libraries might implement:

C

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int
main(void)
{
    /* Length of the password */
    unsigned short int length = 8;

    /* Seed number for rand() */
    srand((unsigned int) time(0));

    /* ASCII characters 33 to 126 */
    while(length--) {
        putchar(rand() % 94 + 33);
    }

    printf("\n");

    return EXIT_SUCCESS;
}

In this case, the standard C function rand, which is a pseudo-random number generator, is initially seeded using the C functions time, but later iterations use rand instead. According to the ANSI C standard, time returns a value of type time_t, which is implementation defined, but most commonly a 32-bit integer containing the current number of seconds since January 1, 1970 (see: Unix time). There are about 31 million seconds in a year, so an attacker who knows the year (a simple matter in situations where frequent password changes are mandated by password policy) and the process ID that the password was generated with, faces a relatively small number, by cryptographic standards, of choices to test. If the attacker knows more accurately when the password was generated, he faces an even smaller number of candidates to test – a serious flaw in this implementation.

In situations where the attacker can obtain an encrypted version of the password, such testing can be performed rapidly enough so that a few million trial passwords can be checked in a matter of seconds. See: password cracking.

The function rand presents another problem. All pseudo-random number generators have an internal memory or state. The size of that state determines the maximum number of different values it can produce: an n-bit state can produce at most 2^n different values. On many systems rand has a 31 or 32 bit state, which is already a significant security limitation. Microsoft documentation does not describe the internal state of the Visual C++ implementation of the C standard library rand, but it has only 32767 possible outputs (15 bits) per call. [1] Microsoft recommends a different, more secure function, rand_s, be used instead. The output of rand_s is cryptographically secure, according to Microsoft, and it does not use the seed loaded by the srand function. However its programming interface differs from rand. [2]

PHP

function pass_gen($length = 8) {
    $pass = array();
    for ($i = 0; $i < $length; $i++) {
        $pass[] = chr(mt_rand(32, 126));
    }
    return implode($pass);
}

In the second case, the PHP function microtime is used, which returns the current Unix timestamp with microseconds. This increases the number of possibilities, but someone with a good guess of when the password was generated, for example the date an employee started work, still has a reasonably small search space. Also some operating systems do not provide time to microsecond resolution, sharply reducing the number of choices. Finally the rand function usually uses the underlying C rand function, and may have a small state space, depending on how it is implemented. An alternative random number generator, mt_rand, which is based on the Mersenne Twister pseudorandom number generator, is available in PHP, but it also has a 32-bit state. There are proposals for adding strong random number generation to PHP. [3]

Stronger methods

A variety of methods exist for generating strong, cryptographically secure random passwords. On Unix platforms /dev/random and /dev/urandom are commonly used, either programmatically or in conjunction with a program such as makepasswd.[1] Windows programmers can use the Cryptographic Application Programming Interface function CryptGenRandom. The Java programming language includes a class called SecureRandom. Another possibility is to derive randomness by measuring some external phenomenon, such as timing user keyboard input.

Many computer systems already have an application (typically named "apg") to implement FIPS 181.[2] FIPS 181—Automated Password Generator—describes a standard process for converting random bits (from a hardware random number generator) into somewhat pronounceable "words" suitable for a passphrase.[3] However, in 1994 an attack on the FIPS 181 algorithm was discovered, such that an attacker can expect, on average, to break into 1% of accounts that have passwords based on the algorithm, after searching just 1.6 million passwords. This is due to the non-uniformity in the distribution of passwords generated, which can be addressed by using longer passwords or by modifying the algorithm.[4][5]

Bash

Here is a code sample that uses /dev/urandom to generate a password with a simple Bash function.This function takes password length as a parameter, or uses 16 by default:

function mkpw() { tr -dc '[:graph:]' < /dev/urandom | head -c ${1:-16}; echo; }

C

// For Microsoft Windows
#include "windows.h"
#include "stdio.h"

int main() {
  int seed;
  DWORD[2] sysinfo;
  seed = *((int*)0x7FFE0014);
  seed ^= *((int*)0x7FFE0018);
  seed ^= GetCurrentProcessId() ^ GetCurrentThreadId();
  QueryPerformanceCounter((LARGE_INTEGER*)(sysinfo));
  seed ^= sysinfo[0];
  seed ^= sysinfo[1];
  srand(seed);
  for (int i = 0; i < 20; i++) {
    putchar(rand() % 94 + 33);
  }
  putchar(10);
  getchar(); // Allow user to see password
}

Java

Here is a code sample (adapted from the class PasswordGenerator[6]) that uses SecureRandom to generate a 10 hexadecimal character password:

String[] symbols = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
int length = 10;
Random random = SecureRandom.getInstanceStrong();    // as of JDK 8, this should return the strongest algorithm available to the JVM
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
    int indexRandom = random.nextInt( symbols.length );
    sb.append( symbols[indexRandom] );
}
String password = sb.toString();

Perl

This example uses the Crypt::Random::Source module to find a source of strong random numbers (which is platform dependent).

use Crypt::Random::Source qw(get_strong);

while(length($out) < 15) {
   my $a = get_strong(1);
   $a =~ s/[^[:graph:]]//g;
   $out .= $a;
}
print $out;

Python

The language Python includes a SystemRandom class that obtains cryptographic grade random bits from /dev/urandom on a Unix-like system, including Linux and Mac OS X, while on Windows it uses CryptGenRandom.[7][8] Here is a simple Python 2 script that demonstrates the use of this class:

#!/usr/bin/python
import random, string
myrg = random.SystemRandom()
length = 10
# If you want non-English characters, remove the [0:52]
alphabet = string.letters[0:52] + string.digits
pw = str().join(myrg.choice(alphabet) for _ in xrange(length))
print pw

PHP

A PHP program can open and read from /dev/urandom, if available, or invoke the Microsoft utilities.[9] A third option, if OpenSSL is available is to employ the function openssl_random_pseudo_bytes'.'[10]

Mechanical methods

Yet another method is to use physical devices such as dice to generate the randomness. One simple way to do this uses a 6 by 6 table of characters. The first die roll selects a row in the table and the second a column. So, for example, a roll of 2 followed by a roll of 4 would select the letter "j" from the fractionation table below.[11] To generate upper/lower case characters or some symbols a coin flip can be used, heads capital, tails lower case. If a digit was selected in the dice rolls, a heads coin flip might select the symbol above it on a standard keyboard, such as the '$' above the '4' instead of '4'.

1 2 3 4 5 6
1 a b c d e f
2 g h i j k l
3 m n o p q r
4 s t u v w x
5 y z 0 1 2 3
6 4 5 6 7 8 9

Type and strength of password generated

Lua error in package.lua at line 80: module 'strict' not found.

Random password generators normally output a string of symbols of specified length. These can be individual characters from some character set, syllables designed to form pronounceable passwords, or words from some word list to form a passphrase. The program can be customized to ensure the resulting password complies with the local password policy, say by always producing a mix of letters, numbers and special characters.

The Password strength of a random password against a particular attack (brute-force search), can be calculated by computing the information entropy of the random process that produced it. If each symbol in the password is produced independently and with uniform probability, the entropy in bits is given by the formula

H = L\,\log_2 N = L {\log N \over \log 2}

where N is the number of possible symbols and L is the number of symbols in the password. The function log2 is the base-2 logarithm. H is typically measured in bits.[12][13]

Entropy per symbol for different symbol sets
Symbol set Symbol count N Entropy per symbol H
Arabic numerals (0–9) (e.g. PIN) 10 3.32 bits
Hexadecimal numerals (0–9, A–F) (e.g. WEP key) 16 4.00 bits
Case insensitive Latin alphabet (a–z or A–Z) 26 4.70 bits
Case insensitive alphanumeric (a–z or A–Z, 0–9) 36 5.17 bits
Case sensitive Latin alphabet (a–z, A–Z) 52 5.70 bits
Case sensitive alphanumeric (a–z, A–Z, 0–9) 62 5.95 bits
All ASCII printable characters 94 6.55 bits
Diceware word list 7776 12.9 bits
Lengths L of truly randomly generated passwords required to achieve desired a password entropy H for symbol sets containing N symbols.
Desired password entropy H Arabic numerals Hexadecimal Case insensitive Latin alphabet Case insensitive alphanumeric Case sensitive Latin alphabet Case sensitive alphanumeric All ASCII printable characters All extended ASCII printable characters Diceware word list
32 bits 10 8 7 7 6 6 5 5 3
40 bits 13 10 9 8 8 7 7 6 4
64 bits 20 16 14 13 12 11 10 9 5
80 bits 25 20 18 16 15 14 13 11 7
96 bits 29 24 21 19 17 17 15 13 8
128 bits 39 32 28 25 23 22 20 17 10
160 bits 49 40 35 31 29 27 25 21 13
192 bits 58 48 41 38 34 33 30 25 15
224 bits 68 56 48 44 40 38 35 29 18
256 bits 78 64 55 50 45 43 39 33 20
384 bits 116 96 82 75 68 65 59 50 30
512 bits 155 128 109 100 90 86 78 66 40
1024 bits 309 256 218 199 180 172 156 132 80

Any password generator is limited by the state space of the pseudo-random number generator used, if it is based on one. Thus a password generated using a 32-bit generator is limited to 32 bits entropy, regardless of the number of characters the password contains.

Note, however, that a different type of attack might succeed against a password evaluated as 'very strong' by the above calculation.

Password generator programs and websites

A large number of password generator programs and websites are available on the Internet. Their quality varies and can be hard to assess if there is no clear description of the source of randomness that is used, and if source code is not provided to allow claims to be checked. Furthermore, and probably most importantly, transmitting candidate passwords over the Internet raises obvious security concerns, particularly if the connection to the password generation site's program is not properly secured or if the site is compromised in some way. Without a secure channel, it is not possible to prevent eavesdropping, especially over public networks such as the Internet. A possible solution to this issue is to generate the password using a client-side programming language such as JavaScript. The advantage of this approach is that the generated password stays in the client computer and is not transmitted to or from an external server.

See also

References

  1. http://www.cyberciti.biz/faq/generating-random-password/
  2. Ubuntu Strong Passwords
  3. NIST. Automated Password Generator standard FIPS 181
  4. Lua error in package.lua at line 80: module 'strict' not found.
  5. Lua error in package.lua at line 80: module 'strict' not found.
  6. http://s13.zetaboards.com/Crypto/topic/7111906/1/?x=90
  7. https://docs.python.org/py3k/library/random.html
  8. https://docs.python.org/py3k/library/os.html#os.urandom
  9. a sample PHP secure random program
  10. http://php.net/manual/en/function.openssl-random-pseudo-bytes.php
  11. Levine, John R., Ed.: Internet Secrets, Second edition, page 831 ff. John Wiley and Sons.
  12. Schneier, B: Applied Cryptography, Second edition, page 233 ff. John Wiley and Sons.
  13. Lua error in package.lua at line 80: module 'strict' not found.

External links