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


1255

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

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

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


13
यह प्रश्न पहले से संबोधित किया गया है , और एक मानक पुस्तकालय का उपयोग करने का उनका सुझाव उत्कृष्ट है। सुरक्षा एक जटिल मामला है, और किसी के द्वारा डिज़ाइन किए गए पैकेज का उपयोग करके, जो जानता है कि वे जो नरक कर रहे हैं वह केवल आपकी मदद कर रहा है।
पलक

59
@eykanal - उस पृष्ठ में भी bcrypt का उल्लेख नहीं है, बहुत कम व्याख्या करते हैं कि यह क्या है
विल्क्स-

8
@eykanal - मैं इस बारे में कोई स्पष्टीकरण नहीं देता कि यह कैसे काम करता है। मैं सिर्फ यह जानना चाहता हूं कि यह क्या है। क्योंकि जो कुछ भी मैं "bcrypt" कीवर्ड के तहत नेट पर खोद सकता हूं, वह हैशिंग पासवर्ड के लिए किसी भी तरह से उपयोग नहीं किया जा सकता है। वैसे भी सीधे नहीं, और PHP में नहीं। ठीक है, अब तक मैं समझता हूं कि यह वास्तव में "फ़ॉग" पैकेज है जो आपके पासवर्ड को कुंजी से एन्क्रिप्ट करने के लिए ब्लोफ़िश का उपयोग करता है जो आपके पासवर्ड से उत्पन्न होता है (संक्षेप में पासवर्ड को स्वयं के साथ एन्क्रिप्ट करना)। लेकिन इसे "bcrypt" के रूप में संदर्भित करना गंभीर रूप से भ्रामक है, और यही मैं इस प्रश्न में स्पष्ट करना चाहता था।
विलेक्स-

3
@Vilx: मैंने अधिक जानकारी जोड़ी है कि मेरे उत्तर मेंbcrypt एक एन्क्रिप्शन तरीका बनाम एक-एक हैशिंग एल्गोरिथ्म क्यों है । यह पूरी गलत धारणा है जो सिर्फ ब्लोफिश है जब वास्तव में इसकी एक पूरी तरह से महत्वपूर्ण अनुसूची होती है जो यह सुनिश्चित करती है कि साइफर पाठ को सिफर टेक्स्ट (नमक, गोल, कुंजी) की प्रारंभिक स्थिति को जाने बिना सिफर पाठ से पुनर्प्राप्त नहीं किया जा सकता है। bcrypt
एंड्रयू मूर

1
ओपनवॉल के पोर्टेबल PHP पासवर्ड हैशिंग (फ्रेमपास) पासवर्ड भी देखें । उपयोगकर्ता पासवर्ड पर कई आम हमलों के खिलाफ इसका कड़ा विरोध किया गया।
jww

जवाबों:


1065

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

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

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

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

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

<?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) का उपयोग करना

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

PHP <5.3.7 का उपयोग कर (हटाया गया)

आप crypt()इनपुट स्ट्रिंग्स के bcrypt हैश उत्पन्न करने के लिए फ़ंक्शन का उपयोग कर सकते हैं । यह वर्ग स्वचालित रूप से लवण उत्पन्न कर सकता है और एक इनपुट के खिलाफ मौजूदा हैश को सत्यापित कर सकता है। यदि आप 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 हाशिंग फ्रेमवर्क का भी उपयोग कर सकते हैं ।


7
@ द दुष्ट पिस्सू: आपको निराश करने के लिए क्षमा करें, लेकिन mt_rand()वर्तमान समय और वर्तमान प्रक्रिया आईडी का उपयोग करके भी वरीयता प्राप्त है। कृपया देखें GENERATE_SEED()में/ext/standard/php_rand.h
एंड्रयू मूर

53
@ माइक: आगे बढ़ो, यह बिल्कुल उसी कारण से है!
एंड्रयू मूर

14
किसी को भी यह सोचकर कि उन्हें गेटसाल्ट फ़ंक्शन में $ नमक स्ट्रिंग की शुरुआत को संशोधित करने की आवश्यकता है, यह आवश्यक नहीं है। $ 2a $ __ CRYPT_BLOWFISH नमक का हिस्सा है। डॉक्स से: "ब्लोफ़िश हैशिंग एक नमक के साथ निम्नानुसार है:" $ 2 ए $ ", एक दो अंक लागत पैरामीटर," $ ", और वर्णमाला से 22 अंक"।
jwinn

18
@MichaelLang: अच्छी बात यह है crypt()कि सहकर्मी की समीक्षा की और फिर सत्यापित किया गया। ऊपर का कोड PHP का है crypt(), जो POSIX crypt()फ़ंक्शन को कॉल करता है। ऊपर दिए गए सभी कोड अधिक एक यादृच्छिक नमक उत्पन्न कर रहे हैं (जिसे क्रिप्टोग्राफिक रूप से सुरक्षित होने की आवश्यकता नहीं है, कॉल करने से पहले नमक को गुप्त नहीं माना जाता है) crypt()हो सकता है कि भेड़िये को बुलाने से पहले आपको खुद थोड़ा शोध करना चाहिए।
एंड्रयू मूर

31
कृपया ध्यान दें कि यह उत्तर, जबकि अच्छा, अपनी उम्र दिखाना शुरू कर रहा है। यह कोड (जैसे किसी भी PHP कार्यान्वयन पर निर्भर करता है crypt()) एक सुरक्षा भेद्यता पूर्व 5.3.7 के अधीन है, और (बहुत थोड़ा) अक्षम पोस्ट 5.3.7 - प्रासंगिक मुद्दे का विवरण यहां पाया जा सकता है । कृपया यह भी ध्यान रखें कि नया पासवर्ड हैशिंग एपीआई ( बैकवर्ड कॉम्पिटिट लिब ) अब आपके आवेदन में बीसीक्रिप्ट पासवर्ड हैशिंग को लागू करने का पसंदीदा तरीका है।
डेवग्रैंडम

295

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

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

फेस इट, क्रिप्टोग्राफी कठिन है।

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

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

पुस्तकालय

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

PHP 5.5 API - (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
    }
}

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

संसाधन:

Zend \ Crypt \ Password \ 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 का समर्थन करने के बजाय, PasswordLib बड़ी संख्या में हैशिंग एल्गोरिदम का समर्थन करता है। यह मुख्य रूप से संदर्भों में उपयोगी है जहां आपको विरासत और विषम प्रणालियों के साथ संगतता का समर्थन करने की आवश्यकता होती है जो आपके नियंत्रण से बाहर हो सकती हैं। यह बड़ी संख्या में हैशिंग एल्गोरिदम का समर्थन करता है। और 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 विकल्पों का उपयोग न करें जो ओपनवॉल पर होस्ट नहीं किए गए हैं, वे अलग-अलग प्रोजेक्ट हैं !!!

BCrypt के बारे में

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

लपेटें

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

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

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


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

7
@AndrewMoore बिलकुल सही! हालांकि, नमक को सांख्यिकीय रूप से अद्वितीय होने के लिए पर्याप्त एन्ट्रापी होना चाहिए। न केवल आपके आवेदन में, बल्कि सभी अनुप्रयोगों में। तो mt_rand()पर्याप्त उच्च अवधि है, लेकिन बीज का मूल्य केवल 32 बिट्स है। तो mt_rand()प्रभावी ढंग से उपयोग करने से आप केवल 32 बिट्स एन्ट्रापी तक सीमित हो जाते हैं। बर्थडे प्रॉब्लम के लिए धन्यवाद का मतलब है कि आपके पास केवल 7k जनरेट किए गए साल्ट (विश्व स्तर पर) पर 50% टकराने की संभावना है। चूंकि bcryptनमक के 128 बिट्स को स्वीकार करता है, ऐसे स्रोत का उपयोग करना बेहतर होता है जो सभी 128 बिट्स ;-) की आपूर्ति कर सकता है। (128 बिट्स पर, 50% टकराने की संभावना 2e19 हैश में होती है) ...
ircmaxell

1
@ircmaxell: "डेटा के पर्याप्त बड़े पूल" को सघन करें। हालाँकि आपके स्रोत में बहुत उच्च एन्ट्रापी स्रोत नहीं है, बस 128 बिट्स के लिए पर्याप्त उच्च है। हालाँकि, यदि आपने अपने सभी उपलब्ध स्रोतों (OpenSSL, आदि नहीं है ...) को समाप्त कर दिया है और आपकी एकमात्र गिरावट mt_rand () है, तो यह अभी भी विकल्प से बेहतर है (जो रैंड () है)।
एंड्रयू मूर

4
@AndrewMoore: बिल्कुल। इस पर बहस नहीं हो रही है। बस वह mt_randऔर uniqid(और इसलिए lcg_valueऔर rand) पहली पसंद नहीं हैं ...
ircmaxell

1
ircmaxell, 5.3.xx के लिए password_compat लाइब्रेरी के लिए बहुत-बहुत धन्यवाद, हमें पहले इसकी आवश्यकता नहीं थी, लेकिन अब हम 5.3.xx php सर्वर पर करते हैं, और इस तर्क को करने की कोशिश न करने के लिए आपकी स्पष्ट सलाह के लिए धन्यवाद। अपने आप को।
छिपकली

47

आपको रेनबो टेबल्स के साथ पर्याप्त जानकारी प्राप्त होगी : सिक्योर पासवर्ड स्कीम या पोर्टेबल PHP पासवर्ड हैशिंग फ्रेमवर्क के बारे में आपको क्या जानना चाहिए

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


7
आप जो भी चाहते हैं उसे लागू करें, उपयोगकर्ता कई चीजों पर एक ही पासवर्ड का उपयोग करने के लिए प्रबंधन करेंगे। इसलिए आपको इसे जितना संभव हो उतना सुरक्षित रखना होगा या कुछ ऐसा लागू करना होगा जिससे आपको कोई पासवर्ड (SSO, OpenID आदि) स्टोर न करने पड़े।
आर्क

41
पासवर्ड हैशिंग का उपयोग एक हमले से बचाने के लिए किया जाता है: कोई आपके डेटाबेस को चुरा लेता है और क्लियरटेक्स्ट लॉगिन + पासवर्ड प्राप्त करना चाहता है।
15

4
@ जोश के। मैं आपको प्रोत्साहित करता हूं कि कुछ सरल पासवर्डों को फॉग ट्यून के माध्यम से प्राप्त करने की कोशिश करें ताकि आपके वेबसर्वर पर इसे गणना करने में 1ms और 10ms के बीच का समय लगे।
अर्क

3
माना। लेकिन जिस तरह का उपयोगकर्ता एक पासवर्ड के रूप में क्वर्टी का उपयोग करेगा, वह भी उस प्रकार का उपयोगकर्ता है जो किसी भी जटिल को चिह्नित करेगा, जहां वह (और हमलावर) इसे आसानी से पढ़ सकता है। Bcrypt उपलब्धियों का उपयोग करना क्या है कि जब आपकी db आपकी इच्छा के विरुद्ध सार्वजनिक हो जाती है, तो उन उपयोगकर्ताओं को प्राप्त करना कठिन होगा जिनके पास कुछ पासवर्ड है जैसे ^ $। $ & ZL6- £ यदि आपने एक पास में sha512 का उपयोग किया है।
अरख

4
@coreyward यह ध्यान देने योग्य है कि ऐसा करना अधिक हानिकारक है जो अवरुद्ध न हो; जिसे आसानी से "सेवा से वंचित" वेक्टर माना जाता है। बस किसी भी ज्ञात खाते पर खराब लॉगिन को स्पैम करना शुरू करें और आप बहुत से उपयोगकर्ताओं को बहुत आसानी से बाधित कर सकते हैं। यह बेहतर है कि हमलावर (देरी) हमलावर को सीधे इनकार करने की पहुंच से बेहतर है, खासकर अगर वह भुगतान करने वाला ग्राहक है।
डेमियनब

36

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

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


4
यह सही दृष्टिकोण है - PHP के crypt()फ़ंक्शन का उपयोग करें , जो कई अलग-अलग पासवर्ड हैशिंग कार्यों का समर्थन करता है। सुनिश्चित करें कि आप उपयोग नहीं कर रहे हैं CRYPT_STD_DESया CRYPT_EXT_DES- कोई भी अन्य समर्थित प्रकार ठीक है (और नाम के तहत bcrypt शामिल है CRYPT_BLOWFISH)।
कैफे

4
SHA के पास वास्तव में 'राउंड' विकल्प के माध्यम से एक लागत पैरामीटर है। इसका उपयोग करते समय, मुझे bcrypt के पक्ष में कोई कारण नहीं दिखता है।
पीटर एन जुले

3
वास्तव में, एक पासवर्ड का एक SHA-1 (या MD5) अभी भी आसानी से जानवर-बल-सक्षम है, नमक के साथ या बिना (नमक इंद्रधनुष तालिकाओं के खिलाफ मदद करता है, जानवर-बल के खिलाफ नहीं)। Bcrypt का उपयोग करें।
पाओलो एबरमन

मुझे यह परेशान लगता है कि हर कोई "bcrypt" कहने लगता है जब उनका मतलब php की क्रिप्ट () होता है।
Sliq

3
@Panique क्यों? एल्गोरिथ्म को bcrypt कहा जाता है । cryptकई पासवर्ड हैश को उजागर करता है, जिसमें bcrypt है जो कंटीन्यूअस के अनुरूप है CRYPT_BLOWFISH। Bcrypt वर्तमान में सबसे मजबूत एल्गोरिदम द्वारा समर्थित है cryptऔर कई अन्य जो इसका समर्थन करते हैं, वे काफी कमजोर हैं।
कोडइन्चोयोस

34

संपादित करें: 2013.01.15 - यदि आपका सर्वर इसका समर्थन करेगा, तो इसके बजाय मार्टिंस्टोकली के समाधान का उपयोग करें।


हर कोई इससे अधिक जटिल बनाना चाहता है। क्रिप्ट () फ़ंक्शन अधिकांश कार्य करता है।

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

उदाहरण:

$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

मुझे पता है कि यह स्पष्ट होना चाहिए, लेकिन कृपया अपने पासवर्ड के रूप में 'पासवर्ड' का उपयोग न करें।


3
नमक के निर्माण में सुधार किया जा सकता है (ओएस के यादृच्छिक स्रोत का उपयोग करें), अन्यथा यह मुझे अच्छा लगता है। नए PHP संस्करणों के लिए इसका उपयोग 2yकरना बेहतर है 2a
मार्टिंस्टेकली

mcrypt_create_iv($size, MCRYPT_DEV_URANDOM)नमक के स्रोत के रूप में उपयोग करें ।
कोडइन्चोस

मैं mcrypt_create_iv () पर करीब से नज़र डालूँगा, जब मुझे एक पल मिलेगा, अगर और कुछ नहीं तो उसे प्रदर्शन में थोड़ा सुधार करना चाहिए।
जॉन हल्का

2
Base64 एन्कोडिंग जोड़ें और कस्टम वर्णमाला bcryptउपयोगों में अनुवाद करें । mcrypt_create_iv(17, MCRYPT_DEV_URANDOM), str_replace('+', '.', base64_encode($rawSalt)),$salt = substr($salt, 0, 22);
CodesInChaos

1
@JonHulka - PHP के संगतता पैक [लाइन 127] पर एक नज़र डालें , यह एक सीधा कार्यान्वयन है।
मार्टिंस्टोकली

29

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

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

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

यह कोड BCrypt (एल्गोरिथम 2y) के साथ पासवर्ड हैश करेगा , OS यादृच्छिक स्रोत से एक यादृच्छिक नमक उत्पन्न करता है, और डिफ़ॉल्ट लागत पैरामीटर का उपयोग करता है (फिलहाल यह 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 संस्करणों के लिए सबसे अच्छा विकल्प है।


3
इसे पढ़ने के बाद, मेरा पहला विचार था कि "आप उस नमक को कैसे स्टोर करते हैं जो उत्पन्न होता है"? डॉक्स के माध्यम से प्रहार करने के बाद, password_hash () फ़ंक्शन एक स्ट्रिंग उत्पन्न करता है जो एन्क्रिप्शन विधि, नमक और उत्पन्न हैश को संग्रहीत करता है। इसलिए, यह काम करने के लिए password_verify () फ़ंक्शन के लिए बस एक स्ट्रिंग में अपनी जरूरत की सभी चीजों को संग्रहीत करता है। बस इसका उल्लेख करना चाहता था क्योंकि जब वे इसे देखते हैं तो यह दूसरों की मदद कर सकता है।
jzimmerman2011

@ jzimmerman2011 - बिल्कुल, एक अन्य जवाब में मैंने एक उदाहरण के साथ इस भंडारण प्रारूप को समझाने की कोशिश की।
Martinstoeckli

7

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

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

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


मुझे लगता है कि वे मानते हैं कि हमलावर पहले से ही मेरे डीबी को कुछ अन्य माध्यमों से चुराने में कामयाब रहा है, और अब उन्हें पेपैल या कुछ पर प्रयास करने के लिए पासवर्ड निकालने की कोशिश कर रहा है।
विल्क्स-

4
2012 के माध्यम से आधा रास्ता और यह जवाब अभी भी भारी है, धीमी गति से हैशिंग एल्गोरिथ्म इंद्रधनुष तालिका हमलों को कैसे रोकता है? मैंने सोचा कि एक यादृच्छिक बाइट रेंज नमक किया था? मैंने हमेशा सोचा है कि हैशिंग एल्गोरिथ्म की गति निर्धारित करती है कि वे कितने हैशटैग के साथ भेज सकते हैं, जो उन्होंने आपको एक विशिष्ट समय में रूप दिया है। इसके अलावा कभी भी विफल लोगो पर एक उपयोगकर्ता का उपयोग न करें, मुझे विश्वास है कि आपके उपयोगकर्ता तंग आ जाएंगे, अक्सर कुछ साइटों पर मुझे इसके लिए अपना पासवर्ड याद रखने से पहले कभी-कभी 5 से अधिक बार लॉगिन करने की आवश्यकता होती है। हालांकि दूसरा पास टियर काम नहीं करता है, हालांकि मोबाइल फोन कोड के साथ दो कदम ऑक्टोरी है।
15

1
@Sammaye मैं इस बात से सहमत होना चाहता हूँ। मैंने 5 विफल लॉगिन प्रयासों पर एक ब्लॉक सेटअप किया, 7 से इसे जल्दी से उठाने से पहले, फिर 10 को अब 20 पर बैठा। किसी भी सामान्य उपयोगकर्ता के पास 20 असफल लॉगिन प्रयास नहीं होने चाहिए, लेकिन इसके कम से कम आसानी से जानवर बल के हमलों को रोकने के लिए
ब्रूस एल्ड्रिज

@ ब्रूस एल्ड्रिज मुझे व्यक्तिगत रूप से लगता है कि बेहतर होगा कि आप अपनी स्क्रिप्ट को एक यादृच्छिक समय के लिए कहें, 7 असफल लॉगिन और ब्लॉक के बजाय कैप्चा दिखाने के लिए बेहतर होगा। ब्लॉकिंग एक बहुत ही आक्रामक कदम है।
सम्मे सिप

1
@Sammaye मैं मानता हूं कि स्थायी ब्लॉक खराब हैं। मैं एक अस्थायी ब्लॉक की बात कर रहा हूं जो विफल प्रयासों की संख्या के साथ बढ़ता है।
ब्रूस एल्ड्रिज

7

यहाँ इस पुराने सवाल का एक अद्यतन जवाब है!

5.5 से PHP में पासवर्ड हैश करने का सही तरीका है password_hash(), और उन्हें सत्यापित करने का सही तरीका है password_verify(), और PHP 8.0 में यह अभी भी सही है। ये फ़ंक्शन डिफ़ॉल्ट रूप से bcrypt हैश का उपयोग करते हैं, लेकिन अन्य मजबूत एल्गोरिदम जोड़े गए हैं। आप password_hashपैरामीटर के माध्यम से कार्य कारक (प्रभावी रूप से एन्क्रिप्शन कितना मजबूत है) को बदल सकते हैं ।

हालाँकि, यह अभी भी काफी मजबूत है, लेकिन bcrypt को अत्याधुनिक नहीं माना जाता है ; पासवर्ड हैश एल्गोरिदम का एक बेहतर सेट आर्गन 2 नामक आर्गन 2 आई, आर्गन 2 डी और आर्गन 2 डी वेरिएंट के साथ आया है। उनके बीच का अंतर (जैसा यहाँ वर्णित है ):

आर्गन 2 का एक प्राथमिक संस्करण है: आर्गन 2 डी, और दो पूरक संस्करण: आर्गन 2 डी और आर्गन 2 आई। आर्गन 2 डी डेटा-आधारित मेमोरी एक्सेस का उपयोग करता है, जो क्रिप्टोक्यूरेंसी और प्रूफ-ऑफ-वर्क अनुप्रयोगों के लिए उपयुक्त है, जो साइड-चैनल टाइमिंग हमलों से कोई खतरा नहीं है। आर्गन 2 आई डेटा-स्वतंत्र मेमोरी एक्सेस का उपयोग करता है, जो पासवर्ड हैशिंग और पासवर्ड-आधारित कुंजी व्युत्पत्ति के लिए पसंद किया जाता है। Argon2id मेमोरी पर पहले पुनरावृत्ति की पहली छमाही के लिए Argon2i के रूप में काम करता है, और बाकी के लिए Argon2d के रूप में, इस प्रकार समय-मेमोरी ट्रेडऑफ़्स के कारण साइड-चैनल अटैक प्रोटेक्शन और ब्रूट-फोर्स लागत बचत दोनों प्रदान करता है।

Argon2i समर्थन PHP 7.2 में जोड़ा गया था, और आप इसे इस तरह से अनुरोध करते हैं:

$hash = password_hash('mypassword', PASSWORD_ARGON2I);

और PHP 7.3 में Argon2id समर्थन जोड़ा गया था:

$hash = password_hash('mypassword', PASSWORD_ARGON2ID);

पासवर्ड को सत्यापित करने के लिए किसी भी बदलाव की आवश्यकता नहीं है क्योंकि परिणामी हैश स्ट्रिंग में एल्गोरिथ्म, नमक, और काम के कारकों के बारे में जानकारी होती है जब इसे बनाया गया था।

काफी अलग (और कुछ हद तक), libsodium (PHP 7.2 में जोड़ा गया) भी Argon2 हैशिंग को sodium_crypto_pwhash_str ()और sodium_crypto_pwhash_str_verify()कार्यों के माध्यम से प्रदान करता है , जो PHP बिल्ट-इन के समान ही काम करते हैं। इनका उपयोग करने का एक संभावित कारण यह है कि PHP को कभी-कभी libargon2 के बिना संकलित किया जा सकता है, जो Argon2 एल्गोरिदम को password_hash फ़ंक्शन के लिए अनुपलब्ध बनाता है; PHP 7.2 और उच्चतर में हमेशा लिबासोडियम सक्षम होना चाहिए, लेकिन यह नहीं हो सकता है - लेकिन कम से कम दो तरीके हैं जो आप उस एल्गोरिथ्म में प्राप्त कर सकते हैं। यहां बताया गया है कि आप libsodium के साथ एक Argon2id हैश कैसे बना सकते हैं (यहां तक ​​कि PHP 7.2 में, जिसमें अन्यथा Argon2id समर्थन का अभाव है):

$hash = sodium_crypto_pwhash_str(
    'mypassword',
    SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
    SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
);

ध्यान दें कि यह आपको मैन्युअल रूप से एक नमक निर्दिष्ट करने की अनुमति नहीं देता है; यह लिबासोडियम के लोकाचार का हिस्सा है - उपयोगकर्ताओं को उन मानों को सेट करने की अनुमति नहीं देता है जो सुरक्षा से समझौता कर सकते हैं - उदाहरण के लिए, PHP के password_hashफ़ंक्शन के लिए एक खाली नमक स्ट्रिंग को पारित करने से आपको रोकने के लिए कुछ भी नहीं है ; libsodium आपको कुछ भी मूर्खतापूर्ण नहीं करने देती है!



1

जैसा कि हम सभी जानते हैं कि डेटाबेस में स्पष्ट पाठ में पासवर्ड संग्रहीत करना सुरक्षित नहीं है। bcrypt एक हैशिंग पासवर्ड तकनीक है। इसका उपयोग पासवर्ड सुरक्षा के लिए किया जाता है। bcrypt का एक अद्भुत कार्य है यह हमें हैकर्स से बचाता है इसका उपयोग पासवर्ड को हैकिंग हमलों से बचाने के लिए किया जाता है क्योंकि पासवर्ड को bcrypted रूप में संग्रहीत किया जाता है।

password_hash () फ़ंक्शन का उपयोग एक नया पासवर्ड हैश बनाने के लिए किया जाता है। यह एक मजबूत और मजबूत हैशिंग एल्गोरिथ्म का उपयोग करता है। पासवर्ड_हश () फ़ंक्शन क्रिप्ट () फ़ंक्शन के साथ बहुत अधिक संगत है। इसलिए, क्रिप्ट () द्वारा बनाए गए पासवर्ड हैश का उपयोग पासवर्ड_हश () और इसके विपरीत किया जा सकता है। फ़ंक्शन क्रिप्ट () के चारों ओर बस काम करने वाले रैपर_ पासवर्ड (पासवर्ड) और पासवर्ड_हश (), और वे इसे सही तरीके से उपयोग करना अधिक आसान बनाते हैं।

वाक्य - विन्यास

string password_hash($password , $algo , $options)

निम्नलिखित एल्गोरिदम वर्तमान में password_hash () फ़ंक्शन द्वारा समर्थित हैं:

PASSWORD_DEFAULT PASSWORD_CRYPT PASSWORD_ARGON2I PASSWORD_ARGON2ID

पैरामीटर: यह फ़ंक्शन तीन मापदंडों को स्वीकार करता है जैसा कि ऊपर वर्णित है और नीचे वर्णित है:

पासवर्ड : यह उपयोगकर्ता के पासवर्ड को संग्रहीत करता है। algo : यह पासवर्ड एल्गोरिदम स्थिरांक है जिसका उपयोग एल्गोरिदम को निरूपित करते समय लगातार किया जाता है जिसका उपयोग पासवर्ड के हैशिंग के होने पर किया जाता है। विकल्प : यह एक सहयोगी सरणी है, जिसमें विकल्प होते हैं। यदि इसे हटा दिया जाता है और इसमें शामिल नहीं किया जाता है, तो एक यादृच्छिक नमक का उपयोग होने वाला है, और एक डिफ़ॉल्ट लागत का उपयोग होगा। रिटर्न वैल्यू : यह सफलता पर हैशेड पासवर्ड देता है या विफलता पर गलत।

उदाहरण :

Input : echo password_hash("GFG@123", PASSWORD_DEFAULT); Output : $2y$10$.vGA19Jh8YrwSJFDodbfoHJIOFH)DfhuofGv3Fykk1a

नीचे दिए गए प्रोग्राम PHP में password_hash () फ़ंक्शन का वर्णन करते हैं:

<?php echo password_hash("GFG@123", PASSWORD_DEFAULT); ?>

आउटपुट

$2y$10$Z166W1fBdsLcXPVQVfPw/uRq1ueWMA6sLt9bmdUFz9AmOGLdM393G

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.