[php] 사용자의 비밀번호를 안전하게 저장하려면 어떻게해야합니까?

일반 MD5 보다 훨씬 더 안전 합니까? 방금 비밀번호 보안을 조사하기 시작했습니다. 저는 PHP를 처음 접했습니다.

$salt = 'csdnfgksdgojnmfnb';

$password = md5($salt.$_POST['password']);
$result = mysql_query("SELECT id FROM users
                       WHERE username = '".mysql_real_escape_string($_POST['username'])."'
                       AND password = '$password'");

if (mysql_num_rows($result) < 1) {
    /* Access denied */
    echo "The username or password you entered is incorrect.";
}
else {
    $_SESSION['id'] = mysql_result($result, 0, 'id');
    #header("Location: ./");
    echo "Hello $_SESSION[id]!";
}



답변

암호 저장 체계를 안전하게 유지하는 가장 쉬운 방법 은 표준 라이브러리사용하는 것 입니다.

보안은 대부분의 프로그래머가 단독으로 처리 할 수있는 것보다 훨씬 더 복잡하고 보이지 않는 스크류 업 가능성으로 인해 표준 라이브러리를 사용하는 것이 가장 쉽고 가장 안전한 옵션 일뿐입니다.

새로운 PHP 비밀번호 API (5.5.0+)

PHP 버전 5.5.0 이상을 사용하는 경우 새로운 단순화 된 비밀번호 해싱 API를 사용할 수 있습니다

PHP의 비밀번호 API를 사용하는 코드의 예 :

<?php
// $hash is what you would store in your database
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT, ['cost' => 12]);

// $hash would be the $hash (above) stored in your database for this user
$checked = password_verify($_POST['password'], $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

(여전히 레거시 5.3.7 이상을 사용하는 경우 내장 기능에 액세스 할 수 있도록 ircmaxell / password_compat 를 설치할 수 있습니다 )

소금에 절인 해시 개선 : 후추 추가

보안을 강화하려면 지금 보안 담당자 (2017)는 소금에 절인 암호 해시에 ‘ 후추 ‘를 추가 할 것을 권장 합니다.

Netsilik / PepperedPasswords
( github ) 는이 패턴을 안전하게 구현하는 클래스가 간단하고 좋습니다
.
MIT 라이센스와 함께 제공되므로 독점 프로젝트에서도 원하는대로 사용할 수 있습니다.

다음을 사용하는 코드 예 Netsilik/PepperedPasswords:

<?php
use Netsilik/Lib/PepperedPasswords;

// Some long, random, binary string, encoded as hexadecimal; stored in your configuration (NOT in your Database, as that would defeat the entire purpose of the pepper).
$config['pepper'] = hex2bin('012345679ABCDEF012345679ABCDEF012345679ABCDEF012345679ABCDEF');

$hasher = new PepperedPasswords($config['pepper']);

// $hash is what you would store in your database
$hash = $hasher->hash($_POST['password']);

// $hash would be the $hash (above) stored in your database for this user
$checked = $hasher->verify($_POST['password'], $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

OLD 표준 라이브러리

참고 : 더 이상 필요하지 않아야합니다! 이것은 역사적인 목적으로 만 여기에 있습니다.

휴대용 PHP 암호 해싱 프레임 워크 : phpass를 살펴보고 CRYPT_BLOWFISH가능한 경우 알고리즘 을 사용해야 합니다.

phpass (v0.2)를 사용하는 코드의 예 :

<?php
require('PasswordHash.php');

$pwdHasher = new PasswordHash(8, FALSE);

// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );

// $hash would be the $hash (above) stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

PHPass는 잘 알려진 일부 프로젝트에서 구현되었습니다.

  • phpBB3
  • bbPress뿐만 아니라 WordPress 2.5 이상
  • Drupal 7 릴리스 (Drupal 5 및 6에 사용 가능한 모듈)
  • 다른 사람

좋은 점은 세부 사항에 대해 걱정할 필요가 없다는 것입니다. 세부 사항은 경험이 많은 사람들이 프로그래밍했으며 인터넷의 많은 사람들이 검토했습니다.

암호 저장 체계에 대한 자세한 내용은 Jeff 의 블로그 게시물을 참조하십시오. 암호를 잘못 저장했을 수 있습니다

무엇 이건 당신이 ‘갈 경우 당신이 내가 그것을 자신을 감사합니다 ‘접근, 사용하지 않는 MD5또는 SHA1더 이상 . 그것들은 좋은 해싱 알고리즘이지만 보안상의 이유로 깨진 것으로 간주 됩니다. .

현재 CRYPT_BLOWFISH와 함께 crypt를 사용 하는 것이 가장 좋습니다.
PHP의 CRYPT_BLOWFISH는 Bcrypt 해시의 구현입니다. Bcrypt는 Blowfish 블록 암호를 기반으로하며 알고리즘을 느리게하기 위해 값 비싼 키 설정을 사용합니다.


답변

SQL 문을 연결하는 대신 매개 변수화 된 쿼리를 사용하면 사용자가 훨씬 안전합니다. 그리고 소금은 각 사용자에 대해 고유해야하며, 암호 해시와 함께 보관해야합니다.


답변

더 나은 방법은 각 사용자가 고유 한 소금을 먹는 것입니다.

솔트를 사용하면 공격자가 모든 사전 단어의 MD5 서명을 미리 생성하기가 더 어렵다는 이점이 있습니다. 그러나 공격자가 고정 소금이 있다는 것을 알게되면 고정 소금이 접두사로 추가 된 모든 사전 단어의 MD5 서명을 미리 생성 할 수 있습니다.

더 좋은 방법은 사용자가 비밀번호를 변경할 때마다 시스템이 임의의 소금을 생성하고 해당 소금을 사용자 레코드와 함께 저장하는 것입니다. MD5 서명을 생성하기 전에 소금을 찾아야하므로 암호를 확인하는 것이 약간 더 비싸지 만 공격자가 MD5를 미리 생성하기가 훨씬 어렵습니다.


답변

PHP 5.5 나는 새로운, 내장의 솔루션을 사용하는 것이 좋습니다 싶습니다 모퉁이 (내가 무엇을 설명하는 것은 그 이전 버전에서 사용할 수, 아래 참조) : password_hash()password_verify(). 필요한 암호 보안 수준을 달성하기 위해 몇 가지 옵션을 제공합니다 (예 : $options어레이를 통해 “cost”매개 변수를 지정 )

<?php
var_dump(password_hash("my-secret-password", PASSWORD_DEFAULT));

$options = array(
    'cost' => 7, // this is the number of rounds for bcrypt
    // 'salt' => 'TphfsM82o1uEKlfP9vf1f', // you could specify a salt but it is not recommended
);
var_dump(password_hash("my-secret-password", PASSWORD_BCRYPT, $options));
?>

돌아올 것이다

string(60) "$2y$10$w2LxXdIcqJpD6idFTNn.eeZbKesdu5y41ksL22iI8C4/6EweI7OK."
string(60) "$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d."

보시다시피, 문자열에는 소금과 옵션에 지정된 비용이 포함되어 있습니다. 사용 된 알고리즘도 포함되어 있습니다.

따라서 암호를 확인할 때 (예 : 사용자가 로그인 할 때) 무료를 사용할 때 password_verify() 기능을 비밀번호 해시 자체에서 필요한 암호화 매개 변수를 추출합니다.

솔트를 지정하지 않으면 생성 된 비밀번호 해시는 호출 할 때마다 다릅니다. password_hash() 솔트가 무작위로 생성되므로 . 따라서 올바른 암호라도 이전 해시와 새로 생성 된 해시를 비교할 수 없습니다.

확인은 다음과 같이 작동합니다.

var_dump(password_verify("my-secret-password", '$2y$10$BjHJbMCNWIJq7xiAeyFaHOGaO0jjNoE11e0YAer6Zu01OZHN/gk6K'));
var_dump(password_verify("wrong-password", '$2y$10$BjHJbMCNWIJq7xiAeyFaHOGaO0jjNoE11e0YAer6Zu01OZHN/gk6K'));

var_dump(password_verify("my-secret-password", '$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d.'));
var_dump(password_verify("wrong-password", '$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d.'));

이 내장 함수를 제공하면 데이터 도난시 더 나은 암호 보안을 제공 할 수 있기를 바랍니다. 프로그래머가 적절한 구현에 대해 생각해야하는 양이 줄어들 기 때문입니다.

password_hashPHP 5.3.7 이상에서 PHP 5.5를 제공하는 작은 라이브러리 (하나의 PHP 파일)가 있습니다 : https://github.com/ircmaxell/password_compat


답변

저도 괜찮습니다. Atwood는 레인보우 테이블에 대한 MD5의 강도에 대해 썼으며 기본적으로 당신이 꽤 앉아있는 것과 같은 긴 소금을 사용했습니다 (임의의 구두점 / 숫자는 향상시킬 수 있음).

요즘 인기가 높아지고있는 SHA-1도 볼 수 있습니다.


답변

추가하고 싶습니다 :

  • 사용자 비밀번호를 길이로 제한하지 마십시오

기존 시스템과의 호환성을 위해 종종 최대 암호 길이 제한을 설정합니다. 이는 잘못된 보안 정책입니다. 제한을 설정 한 경우 최소 암호 길이로만 설정하십시오.

  • 이메일을 통해 사용자 비밀번호를 보내지 마십시오

잊어 버린 비밀번호를 복구하려면 사용자가 비밀번호를 변경할 수있는 주소를 보내야합니다.

  • 사용자 비밀번호의 해시 업데이트

비밀번호 해시가 오래되었을 수 있습니다 (알고리즘의 매개 변수가 업데이트 될 수 있음). 이 기능 password_needs_rehash()을 사용하면 체크 아웃 할 수 있습니다.


답변