PHP में हैशिंग पासवर्ड के लिए आप bcrypt का उपयोग कैसे करते हैं?




passwords cryptography (8)

हर अब और फिर मैं सलाह सुनता हूं "PHP में पासवर्ड संग्रहीत करने के लिए bcrypt का उपयोग करें, bcrypt नियम"।

लेकिन bcrypt क्या है? PHP किसी भी ऐसे फ़ंक्शन की पेशकश नहीं करता है, एक फ़ाइल-एन्क्रिप्शन उपयोगिता और वेब खोजों के बारे में विकिपीडिया बब्बल अलग-अलग भाषाओं में Blowfish कुछ कार्यान्वयन को प्रकट करता है। अब Blowfish PHP में mcrypt माध्यम से भी उपलब्ध है, लेकिन यह पासवर्ड संग्रहीत करने में कैसे मदद करता है? Blowfish एक सामान्य उद्देश्य सिफर है, यह दो तरीकों से काम करता है। अगर इसे एन्क्रिप्ट किया जा सकता है, तो इसे डिक्रिप्ट किया जा सकता है। पासवर्ड को एक तरफा हैशिंग फ़ंक्शन की आवश्यकता होती है।

स्पष्टीकरण क्या है?


PHP के संस्करण 5.5 में BCrypt के लिए अंतर्निहित समर्थन होगा, फ़ंक्शंस password_hash() और password_verify() । दरअसल ये फ़ंक्शन crypt() आस-पास केवल रैपर होते हैं, और इसे सही तरीके से उपयोग करना आसान बना देंगे। यह एक सुरक्षित यादृच्छिक नमक की पीढ़ी का ख्याल रखता है, और अच्छे डिफ़ॉल्ट मान प्रदान करता है।

इस कार्यों का उपयोग करने का सबसे आसान तरीका यह होगा:

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

यह कोड बीसीआरपीटी (एल्गोरिदम 2y ) के साथ पासवर्ड हैश, ओएस यादृच्छिक स्रोत से यादृच्छिक नमक उत्पन्न करता है, और डिफ़ॉल्ट लागत पैरामीटर का उपयोग करता है (फिलहाल यह 10 है)। दूसरी पंक्ति जांचती है, यदि उपयोगकर्ता दर्ज पासवर्ड पहले से संग्रहीत हैश-वैल्यू से मेल खाता है।

यदि आप लागत पैरामीटर को बदलना चाहते हैं, तो आप इसे इस तरह से कर सकते हैं, लागत पैरामीटर 1 से बढ़ाकर, हैश मान की गणना करने के लिए आवश्यक समय को दोगुना कर सकते हैं:

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

"cost" पैरामीटर के विपरीत, "salt" पैरामीटर को छोड़ना सबसे अच्छा है, क्योंकि फ़ंक्शन पहले से ही क्रिप्टोग्राफ़िक रूप से सुरक्षित नमक बनाने के लिए सर्वोत्तम होता है।

PHP संस्करण 5.3.7 और उसके बाद, एक ही लेखक से एक संगतता पैक मौजूद है जिसने password_hash() फ़ंक्शन बनाया है। 5.3.7 से पहले PHP संस्करणों के लिए crypt() के लिए 2y साथ कोई समर्थन नहीं है, यूनिकोड सुरक्षित बीसीक्रिप्ट एल्गोरिदम सुरक्षित है। कोई इसे 2a साथ प्रतिस्थापित कर सकता है, जो पहले के PHP संस्करणों के लिए सबसे अच्छा विकल्प है।


आप PHP के crypt() फ़ंक्शन का उपयोग करके bprypt के साथ एक-तरफा हैश बना सकते हैं और उचित ब्लॉफिश नमक में गुजर सकते हैं। पूरे समीकरण का सबसे महत्वपूर्ण यह है कि ए) एल्गोरिदम से समझौता नहीं किया गया है और बी) आप प्रत्येक पासवर्ड को सही ढंग से नमक करते हैं । आवेदन-व्यापी नमक का प्रयोग न करें; जो आपके पूरे एप्लिकेशन को इंद्रधनुष तालिकाओं के एक सेट से हमला करने के लिए खोलता है।

PHP - क्रिप्ट फ़ंक्शन


OAuth 2 पासवर्ड के लिए:

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

तो, आप bcrypt का उपयोग करना चाहते हैं? बहुत बढ़िया! हालांकि, क्रिप्टोग्राफी के अन्य क्षेत्रों की तरह, आपको इसे स्वयं नहीं करना चाहिए। यदि आपको प्रबंधन कुंजी जैसे कुछ भी, या लवण संग्रहीत करने या यादृच्छिक संख्याएं उत्पन्न करने की आवश्यकता है, तो आप इसे गलत कर रहे हैं।

कारण सरल है: यह bcrypt को पेंच करने के लिए बहुत ही आसान है। वास्तव में, यदि आप इस पृष्ठ पर कोड के लगभग हर टुकड़े को देखते हैं, तो आप देखेंगे कि यह कम से कम इन समस्याओं में से एक का उल्लंघन कर रहा है।

चेहरा यह, क्रिप्टोग्राफी मुश्किल है।

विशेषज्ञों के लिए इसे छोड़ दें। इसे उन लोगों के लिए छोड़ दें जो नौकरी करते हैं, इन पुस्तकालयों को बनाए रखना है। अगर आपको निर्णय लेने की ज़रूरत है, तो आप इसे गलत कर रहे हैं।

इसके बजाय, बस एक पुस्तकालय का उपयोग करें। आपकी आवश्यकताओं के आधार पर कई मौजूद हैं।

पुस्तकालय

यहां कुछ अधिक सामान्य एपीआई का टूटना है।

PHP 5.5 एपीआई - (5.3.7+ के लिए उपलब्ध)

PHP 5.5 में शुरू करना, हैशिंग पासवर्ड के लिए एक नया एपीआई पेश किया जा रहा है। 5.3.7+ के लिए बनाए गए एक शिम संगतता लाइब्रेरी (मेरे द्वारा) भी है। कार्यान्वयन का उपयोग करने के लिए एक सहकर्मी-समीक्षा और सरल होने का इसका लाभ है।

function register($username, $password) {
    $hash = password_hash($password, PASSWORD_BCRYPT);
    save($username, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    if (password_verify($password, $hash)) {
        //login
    } else {
        // failure
    }
}

वास्तव में, इसका लक्ष्य बेहद सरल होना है।

संसाधन:

ज़ेंड \ क्रिप्ट \ पासवर्ड \ Bcrypt (5.3.2+)

यह एक और एपीआई है जो PHP 5.5 के समान है, और इसी तरह का उद्देश्य करता है।

function register($username, $password) {
    $bcrypt = new Zend\Crypt\Password\Bcrypt();
    $hash = $bcrypt->create($password);
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $bcrypt = new Zend\Crypt\Password\Bcrypt();
    if ($bcrypt->verify($password, $hash)) {
        //login
    } else {
        // failure
    }
}

संसाधन:

PasswordLib

यह पासवर्ड हैशिंग के लिए थोड़ा अलग दृष्टिकोण है। बस bcrypt का समर्थन करने के बजाय, पासवर्डलिब बड़ी संख्या में हैशिंग एल्गोरिदम का समर्थन करता है। यह मुख्य रूप से उन संदर्भों में उपयोगी है जहां आपको विरासत और अलग-अलग प्रणालियों के साथ संगतता का समर्थन करने की आवश्यकता है जो आपके नियंत्रण से बाहर हो सकते हैं। यह बड़ी संख्या में हैशिंग एल्गोरिदम का समर्थन करता है। और 5.3.2+ समर्थित है

function register($username, $password) {
    $lib = new PasswordLib\PasswordLib();
    $hash = $lib->createPasswordHash($password, '$2y$', array('cost' => 12));
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $lib = new PasswordLib\PasswordLib();
    if ($lib->verifyPasswordHash($password, $hash)) {
        //login
    } else {
        // failure
    }
}

संदर्भ:

  • स्रोत कोड / दस्तावेज़ीकरण: GitHub

PHPass

यह एक परत है जो bcrypt का समर्थन करता है, लेकिन एक मजबूत मजबूत एल्गोरिदम का भी समर्थन करता है जो उपयोगी है यदि आपके पास PHP> = 5.3.2 तक पहुंच नहीं है ... यह वास्तव में PHP 3.0+ का समर्थन करता है (हालांकि bcrypt के साथ नहीं)।

function register($username, $password) {
    $phpass = new PasswordHash(12, false);
    $hash = $phpass->HashPassword($password);
    save($user, $hash);
}

function login($username, $password) {
    $hash = loadHashByUsername($username);
    $phpass = new PasswordHash(12, false);
    if ($phpass->CheckPassword($password, $hash)) {
        //login
    } else {
        // failure
    }
}

साधन

नोट: PHPASS विकल्पों का उपयोग न करें जो ओपनवॉल पर होस्ट नहीं हैं, वे अलग-अलग परियोजनाएं हैं !!!

बीक्रीप्ट के बारे में

यदि आप देखते हैं, इन पुस्तकालयों में से प्रत्येक एक एकल स्ट्रिंग देता है। यही कारण है कि बीसीआरपीटी आंतरिक रूप से कैसे काम करता है। और इसके बारे में उत्तर के एक टन हैं। यहां एक चयन है जो मैंने लिखा है, कि मैं यहां कॉपी / पेस्ट नहीं करूंगा, लेकिन इससे लिंक करूँगा:

लपेटें

कई अलग-अलग विकल्प हैं। जो आप चुनते हैं वह आपके ऊपर है। हालांकि, मैं अत्यधिक अनुशंसा करता हूं कि आप उपरोक्त पुस्तकालयों में से किसी एक को अपने लिए संभालने के लिए उपयोग करें।

दोबारा, यदि आप सीधे crypt() का उपयोग कर रहे हैं, तो आप शायद कुछ गलत कर रहे हैं। यदि आपका कोड hash() (या md5() या sha1() ) का उपयोग कर रहा है, तो आप लगभग निश्चित रूप से कुछ गलत कर रहे हैं।

बस एक पुस्तकालय का उपयोग करें ...


एक विकल्प है स्क्रिप का उपयोग करना, विशेष रूप से अपने पेपर में कॉलिन पेर्सिवल द्वारा बीक्रिप्ट से बेहतर होने के लिए डिज़ाइन किया गया है। पीईसीएल में एक स्क्रिप PHP एक्सटेंशन है । आदर्श रूप से यह एल्गोरिदम PHP में घुमाया जाएगा ताकि इसे पासवर्ड_ * फ़ंक्शंस (आदर्श रूप से "PASSWORD_SCRYPT") के लिए निर्दिष्ट किया जा सके, लेकिन यह अभी तक नहीं है।


bcrypt एक हैशिंग एल्गोरिदम है जो हार्डवेयर के साथ स्केलेबल है (राउंड की कॉन्फ़िगर करने योग्य संख्या के माध्यम से)। इसकी धीमी गति और एकाधिक राउंड यह सुनिश्चित करता है कि एक हमलावर को आपके पासवर्ड को क्रैक करने में सक्षम होने के लिए भारी धन और हार्डवेयर को तैनात करना होगा। उस प्रति-पासवर्ड salts जोड़ें ( bcrypt लवण) और आप यह सुनिश्चित कर सकते हैं कि एक हमला धन या हार्डवेयर की bcrypt राशि के बिना लगभग असुरक्षित है।

bcrypt हैश पासवर्ड के लिए Eksblowfish एल्गोरिदम का उपयोग करता है। जबकि एक्स्ब्लॉफिश और ब्लोफिश का एन्क्रिप्शन चरण बिल्कुल वही है, एक्सब्लॉफिश का मुख्य शेड्यूल चरण यह सुनिश्चित करता है कि कोई भी बाद का राज्य नमक और कुंजी (उपयोगकर्ता पासवर्ड) दोनों पर निर्भर करता है, और दोनों के ज्ञान के बिना कोई भी राज्य प्रीकंप्यूट नहीं किया जा सकता है। इस महत्वपूर्ण अंतर के कारण, bcrypt एक तरफा हैशिंग एल्गोरिदम है। आप नमक, राउंड और कुंजी (पासवर्ड) को पहले से ही बिना सादे पाठ पासवर्ड पुनर्प्राप्त नहीं कर सकते हैं। [ Source ]

Bcrypt का उपयोग कैसे करें:

PHP> = 5.5-DEV का उपयोग करना

पासवर्ड हैशिंग फ़ंक्शन अब सीधे PHP> = 5.5 में बनाए गए हैं । अब आप किसी भी पासवर्ड का एक bcrypt हैश बनाने के लिए password_hash() का उपयोग कर सकते हैं:

<?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

किसी उपयोगकर्ता को मौजूदा हैश के विरुद्ध पासवर्ड प्रदान करने के लिए, आप password_verify() उपयोग इस प्रकार कर सकते हैं:

<?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 (RedHat PHP> = 5.3.3)

मूल रूप से सी में लिखे गए उपर्युक्त कार्यों के स्रोत कोड के आधार पर GitHub पर एक संगतता लाइब्रेरी है, जो समान कार्यक्षमता प्रदान करती है। एक बार संगतता लाइब्रेरी स्थापित हो जाने के बाद, उपरोक्त के रूप में उपयोग समान है (यदि आप अभी भी 5.3.x शाखा पर हैं तो शॉर्टैंड सरणी नोटेशन घटाएं)।

PHP का उपयोग करना <5.3.7 (अस्वीकृत)

इनपुट स्ट्रिंग्स के bcrypt हैश उत्पन्न करने के लिए आप crypt() फ़ंक्शन का उपयोग कर सकते हैं। यह कक्षा स्वचालित रूप से लवण उत्पन्न कर सकती है और इनपुट के विरुद्ध मौजूदा हैश सत्यापित कर सकती है। यदि आप PHP के संस्करण को उच्च या 5.3.7 के बराबर उपयोग कर रहे हैं, तो अत्यधिक अनुशंसा की जाती है कि आप अंतर्निहित फ़ंक्शन या कंपैट लाइब्रेरी का उपयोग करें । यह विकल्प केवल ऐतिहासिक उद्देश्यों के लिए प्रदान किया जाता है।

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;
  }
}

आप इस कोड का उपयोग इस तरह कर सकते हैं:

$bcrypt = new Bcrypt(15);

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

वैकल्पिक रूप से, आप पोर्टेबल PHP हैशिंग फ्रेमवर्क का भी उपयोग कर सकते हैं।


आपको इंद्रधनुष सारणी के साथ पर्याप्त जानकारी मिल जाएगी : आपको सुरक्षित पासवर्ड योजनाओं या पोर्टेबल PHP पासवर्ड हैशिंग ढांचे के बारे में क्या पता होना चाहिए

लक्ष्य कुछ धीमा होने के साथ पासवर्ड हैश करना है, इसलिए कोई भी अपना पासवर्ड डेटाबेस प्राप्त करने के लिए मजबूर हो जाएगा (पासवर्ड की जांच करने में 10 मिनट की देरी आपके लिए कुछ भी नहीं है, जो किसी को मजबूर करने की कोशिश कर रहा है)। Bcrypt धीमा है और यह निर्धारित करने के लिए पैरामीटर के साथ उपयोग किया जा सकता है कि यह कितना धीमा है।


वर्तमान सोच: हैश सबसे धीमी गति से उपलब्ध होना चाहिए, सबसे तेज़ संभव नहीं है। यह इंद्रधनुष तालिका हमलों को दबाता है।

इसके अलावा, लेकिन सावधानी बरतें: किसी हमलावर को आपकी लॉगिन स्क्रीन पर असीमित पहुंच नहीं होनी चाहिए। इसे रोकने के लिए: एक आईपी एड्रेस ट्रैकिंग टेबल सेट करें जो प्रत्येक हिट को यूआरआई के साथ रिकॉर्ड करता है। यदि लॉगिन करने के 5 से अधिक प्रयास किसी भी पांच मिनट की अवधि में एक ही आईपी पते से आते हैं, तो स्पष्टीकरण के साथ ब्लॉक करें। एक माध्यमिक दृष्टिकोण दो-स्तरीय पासवर्ड योजना है, जैसे कि बैंक करते हैं। दूसरी पास विफलताओं के लिए लॉक-आउट डालने से सुरक्षा बढ़ जाती है।

सारांश: समय लेने वाले हैश कार्यों का उपयोग करके हमलावर को धीमा कर दें। साथ ही, अपने लॉगिन में बहुत से एक्सेस पर ब्लॉक करें, और दूसरा पासवर्ड स्तरीय जोड़ें।





bcrypt