Last active
March 9, 2018 13:12
-
-
Save tjblackheart/d59d57c397295f81b7f15087836cc74d to your computer and use it in GitHub Desktop.
A Symfony form validator which validates against the https://haveibeenpwned.com/passwords Range API. You'll need https://github.com/php-http/HttplugBundle.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Utils; | |
use Http\Client\Common\HttpMethodsClient; | |
use Http\Client\Exception as HttpClientException; | |
use Http\Discovery\HttpClientDiscovery; | |
use Http\Discovery\MessageFactoryDiscovery; | |
class PwnedApi | |
{ | |
public const API = 'https://api.pwnedpasswords.com/range'; | |
public static function searchByRange(string $hash) : array | |
{ | |
$list = []; | |
$client = new HttpMethodsClient( | |
HttpClientDiscovery::find(), | |
MessageFactoryDiscovery::find() | |
); | |
try { | |
$response = $client->get(sprintf("%s/%s", self::API, $hash)); | |
foreach (preg_split("/((\r?\n)|(\r\n?))/", (string) $response->getBody()) as $line) { | |
$result = explode(':', $line); | |
$list[$result[0]] = $result[1]; | |
} | |
} catch (HttpClientException $ex) { | |
// fail silently ... or do whatever. | |
} | |
return $list; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Validator\Constraints; | |
use Symfony\Component\Validator\Constraint; | |
/** | |
* @Annotation | |
*/ | |
class PwnedPasswordConstraint extends Constraint | |
{ | |
public $message = "This password has previously appeared in a data breach | |
and was used {{ count }} times before. | |
If you've ever used it anywhere before, change it! | |
For more info visit: https://haveibeenpwned.com/passwords"; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Validator\Constraints; | |
use App\Utils\PwnedApi; | |
use Symfony\Component\Validator\Constraint; | |
use Symfony\Component\Validator\ConstraintValidator; | |
class PwnedPasswordConstraintValidator extends ConstraintValidator | |
{ | |
public function validate($value, Constraint $constraint) | |
{ | |
if (empty($value)) { | |
return; | |
} | |
$sha1 = strtoupper(hash('sha1', $value)); | |
$prefix = substr($sha1, 0, 5); | |
$suffix = substr($sha1, 5, strlen($sha1)); | |
$list = PwnedApi::searchByRange($prefix); | |
if (!empty($list[$suffix])) { | |
$this->context->buildViolation($constraint->message) | |
->setParameter('{{ count }}', $list[$suffix]) | |
->addViolation(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment