2012-10-03 3 views
0

나는 예를 들어, Joe 아무 문제없이 사용자 이름 joe로 로그인 할 수 있습니다 로그인 시스템대소 문자 구분 사용자 이름과 암호 염은

에게 있습니다.

현재 사용자 이름을 소금으로 사용하는 암호 암호화를 사용하고 있습니다. 로그인 문제가 발생합니다. 예를 들어,

SELECT * FROM `users` WHERE LOWER(`username`) = LOWER(`:username`) 
$stmt->bindValue(':username', $_POST['user']); 

이 작동합니다. 당신이 볼 수 있듯이 사용자가이 이것에 해결되어 joe 대신

Joe의로 로그인 때문에

SELECT * FROM `users` WHERE LOWER(`username`) = LOWER(`:username`) 
    AND `password` = :password 
$stmt->bindValue(':username', $_POST['user']); 
$stmt->bindValue(':password', encrypt($_POST['password'], $_POST['user'])); //encrypt(password, salt) 

는, 암호 암호화 데이터베이스 확인하지 않을 : 문제는 암호를 포함 소금으로 다른 것을 사용해야합니까? 그렇다면 무엇을 소금으로 사용해야합니까? 이것은 내 암호화 기능입니다 :

function encrypt($password, $salt) { 
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($salt), $password, MCRYPT_MODE_CBC, md5(md5($salt)))); 
} 
+3

소금으로 사용자 이름을 사용하는 것은 좋은 생각이 아닙니다. 소금은 적당히 길고, 무작위이며, ASCII가 아니어야합니다. 또한 사용자가 암호를 변경할 때마다 변경해야합니다. – SLaks

+0

@SLaks 아, 그럼 그 소금을 저장해야할까요? – Norse

+0

@ 노르웨이 : 맞아. – SLaks

답변

2

먼저 strtolower($_POST['user'])을 소금으로 사용하면 어떤 문제가 있습니까? 그것이 효과가있는 것처럼 보입니다.

일반적으로 소금은 예측할 수 없어야합니다. 사용자 이름을 실제로 예측할 수는 없으므로 이것이 세상의 종말이되지는 않지만 사용자 이름을 무작위로 생성 된 임의의 길이의 문자열로 바꾸면 사용자의 보안이 향상됩니다 (암호 강도가 무작위 일 필요는 없습니다. 그냥 예측할 수없는).

그러나 여기서 가장 큰 문제는 MD5의 사용으로, 얼마 동안은 안전하지 않은 것으로 간주되었습니다. 다른 해시 함수로 전환하면 보안이 향상됩니다. SHA-1은 특히 나쁜 선택이 아닙니다 (계산하기가 빠르다는 바람직하지 않은 속성이 있습니다). 그러나 이러한 응용 프로그램에 가장 적합한 것은 bcrypt과 같은 가변 부하 계수가있는 해시 함수입니다.

1

lower을 건너 뛰고 PHP의 strtolower()을 사용하십시오. 그렇게하면 사용자 이름이 일관되게 유지됩니다.

1

문제는 사용자 이름을 소금으로 사용해서는 안되는 이유 중 하나입니다. 암호 해시를 더 잘 수행하는 방법은 crypt()입니다. 당신은 그걸로 사용할 무작위 소금을 생성하면됩니다. 반환하는 문자열에는 해시 및 해시 알고리즘이 포함되어 있으므로 코드를 다시 작성하지 않고도 알고리즘이나 난이도를 변경할 수 있습니다. 해시가 7 비트로 안전하면 전체 문자열이되므로 base64_encode()은 필요하지 않습니다.

2

몇 문제는 여기에 있습니다 :

  1. 당신의 소금의 대소 문자 구분
  2. 암호 "암호화"귀하의 방법은

첫 번째 문제는 당신에 대해 질문 한 것입니다

  • , 그래서 그것을 보자.

    그래서 암호는 사용자 이름으로 소금이 채워지고 사용자는 로그인 중에 사용자가 소금으로 입력 한 사용자 이름을 사용할 수 있기를 기대합니다. 소금에 대한 표준화 계획을 정하면이 방법이 효과적입니다. 입력 된대로 사용하는 대신 함수에서 사용하기 전에 소문자 또는 대문자로 변환하십시오.

    다른 옵션은 데이터베이스에 대해 두 개의 쿼리를 수행하는 것입니다. 하나는 저장된 사용자 이름을 가져오고 다른 하나는 실제로 비밀번호를 확인하는 것입니다. 이것은 최적은 아니지만 실제로 문제의 가장 적은 것입니다.

    해결 방법이 있습니까? 아니면 소금으로 다른 것을 사용해야합니까? 그렇다면 무엇을 소금으로 사용해야합니까?

    질문 했으므로 두 번째 문제인 암호 "암호화"를 살펴 보겠습니다.

    자신의 암호 해시/암호화 체계를 만들려고 시도하는 것은 결코 좋은 생각이 아닙니다. 가장 좋은 방법은 bcrypt 또는 PBKDF2의 일부 파생물과 같이 이미 널리 사용되는 암호 해시 체계를 사용하는 것입니다. 둘 다 염도와 키 스트레칭을 모두 포함하기 때문에 위대합니다. 그들은 느리게 (상대적으로, 어쨌든) 설계되었으므로 이러한 유형의 해시는 매우 계산적으로 비쌉니다.

    위의 암호 해시 체계 중 하나를 사용하면 첫 번째 문제도 해결됩니다. 이러한 체계는 사용자 별 기본 제공되는 소금을 사용하기 때문입니다. 이러한 계획을 어떻게 구현 하느냐에 따라 직접 소금을 제공 할 필요는 없습니다. 최고 도서관은 당신을 위해 소금을 생성합니다.

    암호 해시이 도서관에서 살펴 본다보십시오 :

    • Openwall's PasswordHash class - PHP4 용으로 작성하지만,뿐만 아니라 최신 버전에서 작동합니다. bcrypt를 지원하지만 bcrypt가 지원되지 않는 경우 자체 체계로 되돌아갑니다 (PHP < 5.3).
    • Anthony Ferrara's (ircmaxell's) PHP Password Library - 훌륭한 라이브러리이지만 PHP 5.3 이상이 필요합니다.
    • My own PHPassLib - Anthony의 라이브러리와 유사하지만 구현 방식이 다릅니다. 3.x 브랜치는 파이썬의 PassLib과 비슷한 방식으로 시도합니다. 또한 PHP 5.3 이상이 필요합니다.