<?php

# DICEWARE PASSPHRASE GENERATOR SCRIPT - MAY 2013
#
# This version of the script will use random.org to generate the dice rolls if no parameter is passed to the script...
# If the script is run with '?local=1' appended to the script name, the dice rolls are generated using mt_rand().
#
# *** 12/2016 update:
# The 'local=1' parameter was added to the script when a script bug was uncovered in late 2016:
# If the random.org site is unable to generate dice rolls due to excessive server activity, it was returning
# an error text string to the script instead of the random numbers from 1 to 6...
# The script was modified to detect this when it happens, and it gives the user the option to
# run the script with 'local=1' as a parameter via a link in the page displayed.

print <<<_HTML_
<html>
<head>
<style>
body { font-family: Verdana, Tahoma, Arial, Helvetica, sans-serif; font-size: 12px; margin: 10px 10px 10px 10px;}
</style>
</head>
<body>
4/28/2015 (updated 5/4/2015, and again 12/3/2016):<br>
<br>
This PHP script generates a random seven-word passphrase.<br>
<br>
More info:<br>
* <a target="_blank" href="https://firstlook.org/theintercept/2015/03/26/passphrases-can-memorize-attackers-cant-guess/">Passphrases that you can memorize - but that even the NSA can't guess</a><br>
* <a target="_blank" href="http://world.std.com/~reinhold/diceware.html">The Diceware Passphrase Home Page</a><br>
<br>
We admit up front that since this is an internet-based browser implementation of a Diceware Passphrase generator, it is not really secure - especially if an entity is monitoring your internet activity at the time you use this page to generate passphrases.<br>
<br>
The safest and most secure way to generate a diceware passphrase is to print out the <a target="_blank" href="http://world.std.com/~reinhold/diceware.wordlist.asc">Diceware Word List</a>, get a six-sided die, and manually generate a passphrase in a secured location.<br>
<br>
Alternatively, you can:<br>
* Install a PHP interpreter on your computer (<a target="_blank" href="http://windows.php.net/download/">Windows</a> or <a target="_blank" href="http://php.net/manual/en/install.macosx.php">Mac OS</a>),<br>
* Disconnect the computer from the internet, and<br>
* Use <a target="_blank" href="http://doctechnical.com/diceware/diceware.php">this Diceware PHP script</a> with the URL parameter '?local=1' to generate Diceware passphrases locally.<br>
<br>
If you're not concerned about the security of using this script via the open internet, feel free to use it as is (no warranties are expressed or implied).<br>
<br>
For this internet-based implementation, the site <a target="_blank" href="http://random.org">random.org</a> is used for generating the random dice rolls.<br>
<br>
The local version of this script uses the PHP <a target="_blank" href="http://php.net/manual/en/function.mt-srand.php">mt_srand()</a> function for seeding the random number generator (based on the PHP <a target="_blank" href="http://php.net/manual/en/function.microtime.php">microtime()</a> function), and then rolls the die using <a target="_blank" href="http://php.net/manual/en/function.mt-rand.php">mt_rand()</a>.<br>
<br>
You can invoke the local version of this function via <a href="http://doctechnical.com/diceware/index.php?local=1">http://doctechnical.com/diceware/index.php?local=1</a>.<br>
<br>
To generate a new Diceware passphrase, reload the browser page.<br>
<br>
For a shorter passphrase, eliminate words at random from the Diceware passphrase.<br>
<br>
For longer passphrases or more variety, generate multiple passphrases with this script and select words at random from all of the passphrases.<br>
<br>
Some sites and accounts require a mix of upper/lower case letters, numbers and/or characters - just tweak a Diceware passphrase accordingly, to taste.<br>
<br>
_HTML_;


#########################

# declare an array

$pass = array();

# seed the random number generator ...
# this comes into play when 'local' is passed
# to the PHP script as a parameter

mt_srand(make_seed());

# get the Diceware password list file...

$fil = file('./diceware.wordlist.asc');

# create an key/value array of the Diceware password list...
# key: index value (five rolls of a six-sided die)
# value: single Diceware passphrase word

$words = array();

foreach($fil as $val)
{
$set = explode("\t",$val);
$words[$set[0]] = $set[1];
}

# initialize a counter

$cnt = 0;

# while loop:

if ( $_GET["local"] != 1 ) {
# get the dice rolls from random.org
print "<br><span style=\"color: #c00;\">Generating a new diceware passphrase (may take a couple of seconds)...<br>\n";
while ( $cnt < 7 )
{
# generate a random five-digit Diceware index lookup value (via random.org)
$dicerolls = get_dicerolls(5);
# remove the line breaks from the string - we only want the digits
$dice_idx = preg_replace('/\x0A/','',$dicerolls);
# capture the corresponding word in an array
$pass[] = $words[$dice_idx];
# increment the counter
$cnt++;
}

} else {
# get the dice rolls using php mt_rand
print "<br><span style=\"color: #c00;\">Generating a new diceware passphrase (using php \"mt_rand()\" function...)<br>\n";
while ( $cnt < 7 )
{
# generate a random five-digit Diceware index lookup value
$dice_idx = get_dice_idx();
# capture the corresponding word in an array
$pass[] = $words[$dice_idx];
# increment the counter
$cnt++;
}
}

# array $pass now contains seven random words from the Diceware password list...
# catenate them together in a single string, separated with single whitespace characters

$passphrase = implode(" ",$pass);

# display the random Diceware passphrase

print "<br>\nRandom Diceware passphrase: </span><span style=\"background-color: #e0e0e0; font-weight: bold;\">$passphrase</span><br>\n";

#print "(character length of passphrase: ";
#print strlen($passphrase);
#print ")<br>\n";

if ( $passphrase == ' ' ) {
print "<strong><em>The random.org site is busy right now, sorry about that ...<br>\n";
print "You can either reload the page to try again, or you can run the <a href=\"index.php?local=1\">local version</a> (uses \"mt_rand\") of the script if you like.</em></strong>\n";
}

print "<br>\n<br>\n<a target=\"_blank\" href=\"diceware.php\">Click here for the source code of this script</a><br>\n";

print "</body>\n</html>\n";

exit(0);

######################################

function get_dicerolls($numrolls)
{

# see http://random.org for details - info for this usage (integer generator): https://www.random.org/clients/http
$url = 'https://www.random.org/integers/?num=' . $numrolls . '&min=1&max=6&col=1&base=10&format=plain&rnd=new';
$crl = curl_init();
$timeout = 5;
curl_setopt ($crl, CURLOPT_URL,$url);
curl_setopt ($crl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($crl, CURLOPT_CONNECTTIMEOUT, $timeout);
$ret = curl_exec($crl);
curl_close($crl);
return $ret;

}

######################################

function make_seed()
{
# the number of seconds since the (Unix) epoch
# reference: http://en.wikipedia.org/wiki/Unix_time
list($usec, $sec) = explode(' ', microtime());
return (float) $sec + ((float) $usec * 100000);
}


function get_dice_idx()
{

$dice_idx = '';
for( $i=0; $i<5; $i++)
{
$dice_idx .= mt_rand(1,6);
}
return $dice_idx;

}

?>