질문 : PHP에서 암호를 해싱하기 위해 bcrypt를 어떻게 사용합니까?
때때로 나는 "PHP, bcrypt 규칙에 암호를 저장하기 위해 bcrypt 사용"이라는 조언을 듣습니다.
그러나 bcrypt
는 무엇입니까? PHP는 그러한 기능을 제공하지 않으며, Wikipedia는 파일 암호화 유틸리티에 대해 말하며 웹 검색은 여러 언어로 된 Blowfish의 몇 가지 구현을 보여줍니다. mcrypt
를 통해 PHP에서도 사용할 수 있지만 암호 저장에 어떻게 도움이됩니까? Blowfish는 범용 암호이며 두 가지 방식으로 작동합니다. 암호화 할 수 있으면 암호를 해독 할 수 있습니다. 암호에는 단방향 해싱 기능이 필요합니다.
설명은 무엇입니까?
답변
bcrypt
는 (구성 가능한 라운드 수를 통해) 하드웨어로 확장 가능한 해싱 알고리즘입니다. 속도가 느리고 여러 차례 진행되므로 공격자가 암호를 해독 할 수 있도록 막대한 자금과 하드웨어를 배치해야합니다. 암호 단위 솔트 ( bcrypt
솔트)에 추가하면 터무니없는 자금이나 하드웨어 없이는 공격이 사실상 불가능하다는 것을 확신 할 수 있습니다.
bcrypt
는 Eksblowfish 알고리즘을 사용하여 암호를 해시합니다. Eksblowfish와 복어의 암호화 단계는 동일하지만, Eksblowfish의 주요 일정 단계 이후의 상태가 모두 소금과 키 (사용자 암호)에 의존한다는 것을 보장하고, 어떤 상태는 모두의 지식없이 미리 계산 될 수 없다. 이 키 차이로 bcrypt
는 단방향 해싱 알고리즘입니다. 솔트, 반올림 및 키 (비밀번호)를 모르면 일반 텍스트 비밀번호를 검색 할 수 없습니다. [ 출처 ]
암호 해싱 기능 이 이제 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.';
}
GitHub 에는 원래 C로 작성된 위 함수의 소스 코드를 기반으로 생성 된 호환성 라이브러리 가 있으며 동일한 기능을 제공합니다. 호환성 라이브러리가 설치되면 사용법은 위와 동일합니다 (아직 5.3.x 브랜치에있는 경우 축약 형 배열 표기법 제외).
crypt()
함수를 사용하여 입력 문자열의 bcrypt 해시를 생성 할 수 있습니다. 이 클래스는 자동으로 솔트를 생성하고 입력에 대해 기존 해시를 확인할 수 있습니다. 5.3.7 이상의 PHP 버전을 사용하는 경우 내장 함수 또는 compat 라이브러리를 사용하는 것이 좋습니다 . 이 대안은 역사적 목적으로 만 제공됩니다.
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);
또는 Portable PHP Hashing Framework를 사용할 수도 있습니다.
출처 : https://stackoverflow.com/questions/4795385/how-do-you-use-bcrypt-for-hashing-passwords-in-php
'프로그래밍 언어 > PHP' 카테고리의 다른 글
PHP의 enumerations (0) | 2021.07.07 |
---|---|
객체 배열에 대한 PHPDoc 유형 (0) | 2021.07.06 |
PHP로 전체 URL 얻기 (0) | 2021.06.30 |
PHP 애플리케이션에서 멀티 스레딩을 사용하는 방법 (0) | 2021.06.30 |
PHP 치명적 (`E_ERROR`) 오류를 잡는 방법 (0) | 2021.06.30 |