Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 9th, 2012  |  syntax: None  |  size: 3.38 KB  |  hits: 15  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <?php
  2. /*
  3.   By Marco Arment <me@marco.org>.
  4.   This code is released in the public domain.
  5.  
  6.   THERE IS ABSOLUTELY NO WARRANTY.
  7.  
  8.   Usage example:
  9.  
  10.   // In a registration or password-change form:
  11.   $hash_for_user = Bcrypt::hash($_POST['password']);
  12.  
  13.   // In a login form:
  14.   $is_correct = Bcrypt::check($_POST['password'], $stored_hash_for_user);
  15.  
  16.   // In a login form when migrating entries gradually from a legacy SHA-1 hash:
  17.   $is_correct = Bcrypt::check(
  18.       $_POST['password'],
  19.       $stored_hash_for_user,
  20.       function($password, $hash) { return $hash == sha1($password); }
  21.   );
  22.  
  23.   if ($is_correct && Bcrypt::is_legacy_hash($stored_hash_for_user)) {
  24.       $user->store_new_hash(Bcrypt::hash($_POST['password']));
  25.   }
  26.  
  27. */
  28.  
  29. class Bcrypt
  30. {
  31.     const DEFAULT_WORK_FACTOR = 8;
  32.  
  33.     public static function hash($password, $work_factor = 0)
  34.     {
  35.         if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');
  36.  
  37.         if (! function_exists('openssl_random_pseudo_bytes')) {
  38.             throw new Exception('Bcrypt requires openssl PHP extension');
  39.         }
  40.  
  41.         if ($work_factor < 4 || $work_factor > 31) $work_factor = self::DEFAULT_WORK_FACTOR;
  42.         $salt =
  43.             '$2a$' . str_pad($work_factor, 2, '0', STR_PAD_LEFT) . '$' .
  44.             substr(
  45.                 strtr(base64_encode(openssl_random_pseudo_bytes(16)), '+', '.'),
  46.                 0, 22
  47.             )
  48.         ;
  49.         return crypt($password, $salt);
  50.     }
  51.  
  52.     public static function check($password, $stored_hash, $legacy_handler = NULL)
  53.     {
  54.         if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');
  55.  
  56.         if (self::is_legacy_hash($stored_hash)) {
  57.             if ($legacy_handler) return call_user_func($legacy_handler, $password, $stored_hash);
  58.             else throw new Exception('Unsupported hash format');
  59.         }
  60.  
  61.         return crypt($password, $stored_hash) == $stored_hash;
  62.     }
  63.  
  64.     public static function is_legacy_hash($hash) { return substr($hash, 0, 4) != '$2a$'; }
  65. }
  66.  
  67.  
  68. // =============================================================================
  69. // Or, if you don't want the class structure and just want standalone functions:
  70. // =============================================================================
  71.  
  72. function bcrypt_hash($password, $work_factor = 8)
  73. {
  74.     if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');
  75.  
  76.     if (! function_exists('openssl_random_pseudo_bytes')) {
  77.         throw new Exception('Bcrypt requires openssl PHP extension');
  78.     }
  79.  
  80.     if ($work_factor < 4 || $work_factor > 31) $work_factor = 8;
  81.     $salt =
  82.         '$2a$' . str_pad($work_factor, 2, '0', STR_PAD_LEFT) . '$' .
  83.         substr(
  84.             strtr(base64_encode(openssl_random_pseudo_bytes(16)), '+', '.'),
  85.             0, 22
  86.         )
  87.     ;
  88.     return crypt($password, $salt);
  89. }
  90.  
  91. function bcrypt_check($password, $stored_hash, $legacy_handler = NULL)
  92. {
  93.     if (version_compare(PHP_VERSION, '5.3') < 0) throw new Exception('Bcrypt requires PHP 5.3 or above');
  94.  
  95.     if (bcrypt_is_legacy_hash($stored_hash)) {
  96.         if ($legacy_handler) return call_user_func($legacy_handler, $password, $stored_hash);
  97.         else throw new Exception('Unsupported hash format');
  98.     }
  99.  
  100.     return crypt($password, $stored_hash) == $stored_hash;
  101. }
  102.  
  103. function bcrypt_is_legacy_hash($hash) { return substr($hash, 0, 4) != '$2a$'; }