Skip to content

Instantly share code, notes, and snippets.

@ssigwart
Created August 4, 2017 03:36
Show Gist options
  • Save ssigwart/cf5bdd1028c96d021ad06b7768075f38 to your computer and use it in GitHub Desktop.
Save ssigwart/cf5bdd1028c96d021ad06b7768075f38 to your computer and use it in GitHub Desktop.
Lookup a password to see if it's been cracked in a breach.
<?php
# Download text file from https://haveibeenpwned.com/Passwords
/** Password SHA1 searches */
class PasswordSha1Search
{
/** Line Size (sha1 + \r\n) */
const RECORD_SIZE = 42;
/** File */
private $file = null;
/** Number of lines */
private $numLines = 0;
/** Constructor */
public function __construct()
{
$this->file = fopen('pwned-passwords-1.0.txt', 'r');
if ($this->file === false)
{
print "Failed to open file.\n";
exit(1);
}
// Compute number of lines
fseek($this->file, 0, SEEK_END);
$this->numLines = ftell($this->file)/self::RECORD_SIZE;
}
/**
* Look up a SHA1
*
* @param string $sha1 SHA1 of password
*
* @return bool True if found
*/
public function lookupSha1($sha1)
{
return $this->_lookupSha1(strtoupper($sha1), 0, $this->numLines);
}
/**
* Look up a SHA1 and output whether it's found or not
*
* @param string $sha1 SHA1 of password
*/
public function lookupSha1Output($sha1)
{
if ($this->lookupSha1($sha1))
print "Password found!\n";
else
print "Password NOT found!\n";
}
/**
* Binary search for a SHA1
*
* @param string $sha1 SHA1 of password (uppercase)
*
* @return bool True if found
*/
private function _lookupSha1($sha1, $min, $max)
{
// Done?
if ($min > $max)
return false;
// Check midpoint
$mid = $min+(int)(($max-$min)/2);
fseek($this->file, self::RECORD_SIZE*$mid, SEEK_SET);
$recordSha1 = fread($this->file, 40);
// Match
$cmp = strcmp($sha1, $recordSha1);
if ($cmp === 0)
return true;
else if ($cmp < 0)
return $this->_lookupSha1($sha1, $min, $mid-1);
else
return $this->_lookupSha1($sha1, $mid+1, $max);
}
}
// Load class
$search = new PasswordSha1Search();
// SHA1 on command line
$sha1 = isset($argv[1]) ? $argv[1] : null;
if ($sha1 !== null && strlen($sha1) === 40)
$search->lookupSha1Output($sha1);
else
{
// Allow user to type passwords
print "Enter passwords to look up. When you are done, enter a blank link.\n";
$continue = true;
do
{
// Get password
echo 'Password: ';
system('stty -echo');
$password = trim(fgets(STDIN));
system('stty echo');
print PHP_EOL;
// Is there a password?
$continue = ($password !== '');
if ($continue)
{
// Construct and print SHA1
$sha1 = sha1($password);
print $sha1 . PHP_EOL;
// Check if it's found
$search->lookupSha1Output($sha1);
// Separator
print PHP_EOL . '--------------------------------------------------------------------------------' . PHP_EOL . PHP_EOL;
}
} while ($continue);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment