web-gelistirme-sc.com

PHP'de şifre çözme için bcrypt nasıl kullanılır?

Her şimdi ve sonra "PHP, bcrypt kuralları içinde şifreleri saklamak için bcrypt kullanın" tavsiyesini dinliyorum.

Ama bcrypt nedir? PHP, bu tür işlevler sunmuyor, Wikipedia bir dosya şifreleme yardımcı programından bahsetti ve Web aramaları sadece Blowfish 'in birkaç farklı uygulamasını açıkladı. Şimdi Blowfish ayrıca PHP içinde mcrypt yoluyla da kullanılabilir, ancak bu parolaları saklamakta nasıl yardımcı olur? Blowfish genel amaçlı bir şifredir, iki şekilde çalışır. Şifrelenebiliyorsa şifresi çözülebilir. Parolalar tek yönlü bir karma işlevine ihtiyaç duyar.

Açıklama nedir?

1201
Vilx-

bcryptname__, donanıma göre ölçeklendirilebilen bir karma algoritmadır (yapılandırılabilir sayıda tur aracılığıyla). Yavaşlığı ve çoklu turları, bir saldırganın şifrelerinizi kırabilmek için büyük miktarda fon ve donanım kullanması gerektiğini garanti eder. Parola başına tuzları ekleyin (bcrypttuzları GEREKTİRİR) ve bir saldırganın çok fazla fon veya donanım olmadan neredeyse mümkün olmadığından emin olabilirsiniz.

bcryptname__, parolaları şifrelemek için Eksblowfish algoritmasını kullanır. Eksblowfish ve Blowfish şifreleme aşaması tamamen aynı olsa da, Eksblowfish anahtar zamanlama aşaması, daha sonraki herhangi bir durumun hem tuza hem de anahtara bağlı olmasını sağlar (kullanıcı şifre) ve hiçbir devletin ikisinin de bilgisi olmadan önceden hesaplanamaz. Bu anahtar fark nedeniyle, bcrypttek yönlü bir karma algoritmadır.Tuzu önceden bilmeden düz metin şifresini alamıyorsunuz, yuvarlar _ (ve key(password). [ Kaynak ]

Bcrypt nasıl kullanılır:

PHP> = 5.5-DEV kullanarak

Parola sağlama işlevleri şimdi doğrudan PHP> = 5.5 içine inşa edilmiştir. Artık herhangi bir şifrenin bcrypthashını oluşturmak için password_hash() kullanabilirsiniz:

<?php
// Usage 1:
echo password_hash('rasmuslerdorf', PASSWORD_DEFAULT)."\n";
// $2y$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// For example:
// $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

// Usage 2:
$options = [
  'cost' => 11
];
echo password_hash('rasmuslerdorf', PASSWORD_BCRYPT, $options)."\n";
// $2y$11$6DP.V0nO7YI3iSki4qog6OQI5eiO6Jnjsqg7vdnb.JgGIsxniOn4C

Mevcut bir karmaşa karşı bir kullanıcı tarafından sağlanan şifreyi doğrulamak için password_verify() işlevini şu şekilde kullanabilirsiniz:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

PHP> = 5.3.7, <5.5-DEV kullanarak (ayrıca RedHat PHP> = 5.3.3)

Aynı işlevi sağlayan, başlangıçta C dilinde yazılmış, yukarıdaki işlevlerin kaynak koduna dayanarak oluşturulan GitHub üzerinde bir uyumluluk kütüphanesi var. Uyumluluk kütüphanesi kurulduktan sonra, kullanım yukarıdakiyle aynıdır (eksi, eğer hala 5.3.x dalındaysanız, kısayol dizi gösterimi).

PHP <5.3.7 (DEPRECATED)} kullanarak _

Giriş dizelerinin bcrypt karma değerlerini oluşturmak için crypt() işlevini kullanabilirsiniz. Bu sınıf otomatik olarak tuz üretebilir ve mevcut girdilerin bir girişe karşı olduğunu doğrulayabilir. PHP sürümünün 5.3.7'ye eşit veya daha yüksek bir sürümünü kullanıyorsanız, yerleşik işlevi veya uyumluluk kütüphanesini kullanmanız şiddetle tavsiye edilir. Bu alternatif yalnızca tarihsel amaçlar için sağlanmıştır. .

class Bcrypt{
  private $rounds;

  public function __construct($rounds = 12) {
    if (CRYPT_BLOWFISH != 1) {
      throw new Exception("bcrypt not supported in this installation. See http://php.net/crypt");
    }

    $this->rounds = $rounds;
  }

  public function hash($input){
    $hash = crypt($input, $this->getSalt());

    if (strlen($hash) > 13)
      return $hash;

    return false;
  }

  public function verify($input, $existingHash){
    $hash = crypt($input, $existingHash);

    return $hash === $existingHash;
  }

  private function getSalt(){
    $salt = sprintf('$2a$%02d$', $this->rounds);

    $bytes = $this->getRandomBytes(16);

    $salt .= $this->encodeBytes($bytes);

    return $salt;
  }

  private $randomState;
  private function getRandomBytes($count){
    $bytes = '';

    if (function_exists('openssl_random_pseudo_bytes') &&
        (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL is slow on Windows
      $bytes = openssl_random_pseudo_bytes($count);
    }

    if ($bytes === '' && is_readable('/dev/urandom') &&
       ($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
      $bytes = fread($hRand, $count);
      fclose($hRand);
    }

    if (strlen($bytes) < $count) {
      $bytes = '';

      if ($this->randomState === null) {
        $this->randomState = microtime();
        if (function_exists('getmypid')) {
          $this->randomState .= getmypid();
        }
      }

      for ($i = 0; $i < $count; $i += 16) {
        $this->randomState = md5(microtime() . $this->randomState);

        if (PHP_VERSION >= '5') {
          $bytes .= md5($this->randomState, true);
        } else {
          $bytes .= pack('H*', md5($this->randomState));
        }
      }

      $bytes = substr($bytes, 0, $count);
    }

    return $bytes;
  }

  private function encodeBytes($input){
    // The following is code from the PHP Password Hashing Framework
    $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    $output = '';
    $i = 0;
    do {
      $c1 = ord($input[$i++]);
      $output .= $itoa64[$c1 >> 2];
      $c1 = ($c1 & 0x03) << 4;
      if ($i >= 16) {
        $output .= $itoa64[$c1];
        break;
      }

      $c2 = ord($input[$i++]);
      $c1 |= $c2 >> 4;
      $output .= $itoa64[$c1];
      $c1 = ($c2 & 0x0f) << 2;

      $c2 = ord($input[$i++]);
      $c1 |= $c2 >> 6;
      $output .= $itoa64[$c1];
      $output .= $itoa64[$c2 & 0x3f];
    } while (true);

    return $output;
  }
}

Bu kodu şöyle kullanabilirsiniz:

$bcrypt = new Bcrypt(15);

$hash = $bcrypt->hash('password');
$isGood = $bcrypt->verify('password', $hash);

Alternatif olarak, Portable PHP Hashing Framework öğesini de kullanabilirsiniz.

1025
Andrew Moore

Rainbow Tablolar Yeterli: Güvenli Şifre Programları Hakkında Bilmeniz GerekenlerveyaTaşınabilir PHP şifre karmaşası hakkında birçok bilgi edineceksiniz. çerçeve.

Amaç, şifreyi yavaş bir şeyle karıştırmaktır, bu yüzden şifre veritabanınızı alan bir kişi zorla zorlamaya çalışırken ölür (bir şifreyi kontrol etmek için 10 ms'lik bir gecikme sizin için hiçbir şeydir, kaba bir şekilde zorlamaya çalışan biri için çok fazladır). Bcrypt yavaştır ve ne kadar yavaş olduğunu seçmek için bir parametre ile kullanılabilir.

46
Arkh

PHP'nin crypt() işlevini kullanarak ve uygun bir Blowfish tuzundan geçirerek bcrypt ile tek yönlü bir karma oluşturabilirsiniz. Denklemin en önemlisi A) algoritmanın tehlikeye atılmadığı ve B) her bir şifreyi uygun şekilde tuzladığın. Uygulama çapında bir tuz kullanmayın; Tüm uygulamanızı açan bir dizi Rainbow tabloya saldırmak için açılır.

PHP - Şifreleme İşlevi

35
coreyward

Düzenleme: 2013.01.15 - Sunucunuz destekliyorsa, martinstoeckli'nin çözümünü kullanın.


Herkes bunu olduğundan daha karmaşık hale getirmek istiyor. Crypt () işlevi işin çoğunu yapar.

function blowfishCrypt($password,$cost)
{
    $chars='./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt=sprintf('$2y$%02d$',$cost);
//For PHP < PHP 5.3.7 use this instead
//    $salt=sprintf('$2a$%02d$',$cost);
    //Create a 22 character salt -edit- 2013.01.15 - replaced Rand with mt_Rand
    mt_srand();
    for($i=0;$i<22;$i++) $salt.=$chars[mt_Rand(0,63)];
    return crypt($password,$salt);
}

Örnek:

$hash=blowfishCrypt('password',10); //This creates the hash
$hash=blowfishCrypt('password',12); //This creates a more secure hash
if(crypt('password',$hash)==$hash){ /*ok*/ } //This checks a password

Açık olması gerektiğini biliyorum, ancak lütfen şifrenizi 'şifre' olarak kullanmayın.

33
Jon Hulka

PHP sürümünün 5.5 sürümünde BCrypt için yerleşik destek bulunacaktır, password_hash() ve password_verify() . Aslında bunlar sadece crypt() fonksiyonunun etrafındaki sarmalayıcılardır ve doğru şekilde kullanılmasını kolaylaştıracaklardır. Güvenli bir rastgele tuzun oluşumunu önemser ve iyi varsayılan değerler sağlar.

Bu işlevleri kullanmanın en kolay yolu:

$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

Bu kod, BCrypt ile şifreye sahip (algoritma 2y), işletim sistemi rasgele kaynağından rastgele bir tuz üretiyor ve varsayılan maliyet parametresini kullanıyor (şu anda bu 10'dur). İkinci satır, kullanıcı tarafından girilen parolanın önceden kaydedilmiş bir hash değeriyle eşleşip eşleşmediğini kontrol eder.

Maliyet parametresini değiştirmek isterseniz, bu şekilde yapabilirsiniz, maliyet parametresini 1 oranında artırmak, karma değerini hesaplamak için gereken süreyi iki katına çıkarır:

$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 11));

"cost" parametresinin aksine, "salt" parametresini atlamak en iyisidir, çünkü işlev zaten kriptografik olarak güvenli bir tuz oluşturmak için elinden gelenin en iyisini yapar.

PHP sürüm 5.3.7 ve sonraki sürümlerinde, password_hash() işlevini yapan aynı yazardan bir uyumluluk paketi vardır. PHP 5.3.7'den önceki sürümlerde, unicode safe BCrypt algoritması 2y ile crypt() için destek yoktur. Bunun yerine daha önce PHP sürümleri için en iyi alternatif olan 2a ile değiştirebiliriz.

27
martinstoeckli

Alternatif olarak, onun makalesinde içinde Colin Percival tarafından bcrypt'ten daha üstün olacak şekilde tasarlanmış scrypt kullanmaktır. PECL'de bir scrypt PHP uzantısı var . İdeal olarak, bu algoritma PHP içine yuvarlanır, böylece parola_ * işlevleri için belirtilebilir (ideal olarak "PASSWORD_SCRYPT" olarak), ancak henüz orada değil.

6
Synchro

Mevcut düşünce: karma değerler mümkün olan en hızlı değil, mümkün olan en yavaş olmalıdır. Bu, Rainbow tablosunu saldırıları bastırır.

Ayrıca ilgili, ancak ihtiyati tedbir: Bir saldırganın giriş ekranınıza asla sınırsız erişimi olmamalıdır. Bunu önlemek için: URI ile birlikte her isabetini kaydeden bir IP adresi izleme tablosu oluşturun. Herhangi bir beş dakikalık sürede 5'ten fazla giriş yapma denemesi aynı IP adresinden gelirse, açıklamayı engelleyin. İkincil bir yaklaşım, bankalar gibi iki katmanlı bir şifre programına sahip olmaktır. İkinci geçişte arızalar için bir kilitleme koymak güvenliği arttırır.

Özet: zaman alan karma işlevlerini kullanarak saldırganı yavaşlatın. Ayrıca, giriş bilgilerinize çok fazla erişimi engelleyin ve ikinci bir şifre seviyesi ekleyin.

6
FYA

OAuth 2 şifreleri için:

$bcrypt = new \Zend\Crypt\Password\Bcrypt;
$bcrypt->create("youpasswordhere", 10)
3
Shemeer M Ali