수색…


소개

보다 안전한 웹 서비스가 암호를 일반 텍스트 형식으로 저장하지 않으므로 PHP와 같은 언어는보다 안전한 산업 표준을 지원하기 위해 다양한 (해독 할 수없는) 해시 함수를 제공합니다. 이 주제는 PHP로 적절한 해싱을위한 문서를 제공합니다.

통사론

  • string password_hash ( string $password , integer $algo [, array $options ] )
  • boolean password_verify ( string $password , string $hash )
  • boolean password_needs_rehash ( string $hash , integer $algo [, array $options ] )
  • array password_get_info ( string $hash )

비고

PHP 5.5 이전 버전에서는 호환성 팩 을 사용하여 password_* 기능을 제공 할 수 있습니다. 호환성 팩을 사용할 수있는 경우 호환성 팩을 사용하는 것이 좋습니다.

호환성 팩의 유무에 관계없이 crypt() 통한 올바른 Bcrypt 기능은 PHP 5.3.7 이상 을 사용 합니다. 그렇지 않으면 암호를 ASCII 전용 문자 집합으로 제한 해야 합니다.

참고 : PHP 5.5 이하를 사용하는 경우 더 이상 보안 업데이트를받지 않는 지원되지 않는 버전의 PHP 를 사용하고 있습니다. 최대한 빨리 업데이트하십시오. 나중에 비밀번호 해시를 업데이트 할 수 있습니다.

알고리즘 선택

보안 알고리즘

불안전 한 알고리즘

다음 해싱 알고리즘은 안전하지 않거나 목적에 부적합 하므로 사용 해서는 안됩니다 . 그들은 암호 해시에 적합하지 않았습니다. 암호 해시가 천천히 그리고 힘들지 않고 빠른 다이제스트를 위해 설계되었으므로 암호 해싱에 적합하지 않았습니다.

소금을 포함하여 중 하나를 사용하는 경우 가능한 한 빨리 권장 보안 알고리즘 중 하나로 전환 해야 합니다 .

불안정한 알고리즘 :

일부 알고리즘은 메시지 다이제스트 알고리즘으로 안전하게 사용될 수 있지만 암호 해싱 알고리즘으로 사용하지 마십시오 .

  • SHA-2
  • SHA-3

SHA256 및 SHA512와 같은 강력한 해시는 깨지지 않고 강력하지만 일반적으로 고전적인 컴퓨터에서는 이러한 알고리즘에 대한 무차별 대입 공격이 훨씬 어려워 bcrypt 또는 arg22 해시 함수를 사용하는 것이 더 안전합니다.

기존 암호 해시를 더 강력한 알고리즘으로 업그레이드 할 수 있는지 확인

PASSWORD_DEFAULT 메소드를 사용하여 시스템이 암호를 해시하는 가장 좋은 알고리즘을 선택하게하는 경우, 기본적으로 강도가 증가하므로 사용자가 로그인 할 때 이전 암호를 재실행 할 수 있습니다.

<?php
// first determine if a supplied password is valid
if (password_verify($plaintextPassword, $hashedPassword)) {

    // now determine if the existing hash was created with an algorithm that is
    // no longer the default
    if (password_needs_rehash($hashedPassword, PASSWORD_DEFAULT)) {

        // create a new hash with the new default
        $newHashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT);

        // and then save it to your data store
        //$db->update(...);
    }
}
?>

시스템에서 password_ * 기능을 사용할 수없는 경우 (아래 설명에서 링크 된 호환 팩을 사용할 수없는 경우) 알고리즘을 결정하고 다음과 유사한 방법으로 원래 해시를 만드는 데 사용할 수 있습니다.

<?php
if (substr($hashedPassword, 0, 4) == '$2y$' && strlen($hashedPassword) == 60) {
    echo 'Algorithm is Bcrypt';
    // the "cost" determines how strong this version of Bcrypt is
    preg_match('/\$2y\$(\d+)\$/', $hashedPassword, $matches);
    $cost = $matches[1];
    echo 'Bcrypt cost is '.$cost;
}
?>

비밀번호 해시 만들기

password_hash() 를 사용하여 암호 해시를 작성하면 현재 업계 최고의 표준 해시 또는 키 유도를 사용할 수 있습니다. 기입시, 표준이다 bcrypt 것을 의미 PASSWORD_DEFAULT 같은 값이 포함 PASSWORD_BCRYPT .

$options = [
    'cost' => 12,
];

$hashedPassword = password_hash($plaintextPassword, PASSWORD_DEFAULT, $options);

세 번째 매개 변수는 필수아닙니다 .

'cost' 값은 프로덕션 서버의 하드웨어를 기반으로 선택해야합니다. 암호를 늘리면 암호 생성에 더 많은 비용이 듭니다. 더 오래 걸리면 생성하는 데 더 많은 비용이 듭니다. 비용은 이상적으로 가능한 한 높을 것이지만 실제로는 모든 것을 너무 많이 감속시키지 않도록해야합니다. 0.1 초에서 0.4 초 사이의 어느 곳에서나 괜찮습니다. 의심스러운 경우 기본값을 사용하십시오.

5.5

5.5.0보다 낮은 PHP에서는 password_* 함수를 사용할 수 없습니다. 호환성 팩 을 사용 하여 해당 기능을 대체해야합니다. 호환성 팩에는 PHP 5.3.7 이상 또는 $2y 수정본이 백 포트 된 버전 (예 : RedHat에서 제공)이 필요합니다.

이들을 사용할 수 없다면 crypt() 를 사용하여 암호 해시를 구현할 수 있습니다. crypt() 함수를 감싸는 래퍼로 password_hash() 가 구현 crypt() 기능을 잃지 않아도됩니다.

// this is a simple implementation of a bcrypt hash otherwise compatible
// with `password_hash()`
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation

// if `CRYPT_BLOWFISH` is 1, that means bcrypt (which uses blowfish) is available
// on your system
if (CRYPT_BLOWFISH == 1) {
    $salt = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
    $salt = base64_encode($salt);
    // crypt uses a modified base64 variant
    $source = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    $dest = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $salt = strtr(rtrim($salt, '='), $source, $dest);
    $salt = substr($salt, 0, 22);
    // `crypt()` determines which hashing algorithm to use by the form of the salt string
    // that is passed in
    $hashedPassword = crypt($plaintextPassword, '$2y$10$'.$salt.'$');
}

암호 해시 용 소금

암호 알고리즘의 안정성에도 불구하고 레인보우 테이블 에 대한 취약성은 여전히 ​​존재합니다. 그것이 소금 을 사용하는 것이 바람직한 이유입니다.

소금은 소스 문자열을 고유하게 만들기 위해 해시하기 전에 암호에 추가되는 내용입니다. 두 개의 동일한 암호가 주어지면 결과 소금물은 고유 한 소금이기 때문에 고유합니다.

무작위 소금은 암호 보안의 가장 중요한 부분 중 하나입니다. 즉, 알려진 암호 해시 테이블의 조회 테이블을 사용하더라도 공격자는 임의의 소금이 사용되었으므로 데이터베이스 암호 해시와 사용자 암호 해시를 일치시킬 수 없습니다. 항상 무작위로 그리고 암호로 안전한 소금을 사용해야합니다. 더 많은 것을 읽으십시오

password_hash() bcrypt 알고리즘을 사용하면 일반 텍스트 소금이 결과 해시와 함께 저장되므로 해시를 다른 시스템 및 플랫폼에서 전송할 수 있으며 원래 암호와 일치시킬 수 있습니다.

7.0

이것이 낙심 할지라도 salt 옵션을 사용하여 임의의 소금을 정의 할 수 있습니다.

 $options = [
        'salt' => $salt, //see example below
 ];

중요 . 이 옵션을 생략하면 암호 해시마다 password_hash ()가 임의의 소금을 생성합니다. 이것이 의도 된 작동 모드입니다.

7.0

salt 옵션은 PHP 7.0.0부터 사용되지 않습니다 . 기본적으로 생성되는 소금을 단순히 사용하는 것이 좋습니다.

해시에 대한 비밀번호 확인

password_verify() 는 알려진 해쉬에 대한 패스워드의 유효성을 검증하기 위해 PHP 5.5에서 제공하는 빌트인 함수입니다.

<?php
if (password_verify($plaintextPassword, $hashedPassword)) {
    echo 'Valid Password';
}
else {
    echo 'Invalid Password.';
}
?>

지원되는 모든 해싱 알고리즘은 해시 자체에서 사용 된 해시를 식별하는 정보를 저장하므로 일반 텍스트 암호를 인코딩하는 데 사용하는 알고리즘을 나타내지 않아도됩니다.

시스템에서 password_ * 기능을 사용할 수없고 (아래 설명에서 링크 된 호환 팩을 사용할 수없는 경우) crypt() 함수를 사용하여 비밀번호 확인을 구현할 수 있습니다. 타이밍 공격 을 피하기 위해 특별한주의를 기울여야합니다.

<?php
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation
if (CRYPT_BLOWFISH == 1) {
    // `crypt()` discards all characters beyond the salt length, so we can pass in
    // the full hashed password
    $hashedCheck = crypt($plaintextPassword, $hashedPassword);

    // this a basic constant-time comparison based on the full implementation used
    // in `password_hash()`
    $status = 0;
    for ($i=0; $i<strlen($hashedCheck); $i++) {
        $status |= (ord($hashedCheck[$i]) ^ ord($hashedPassword[$i]));
    }

    if ($status === 0) {
        echo 'Valid Password';
    }
    else {
        echo 'Invalid Password';
    }
}
?>


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow