본문으로 바로가기

php 비밀번호를 암호화

category [ Web 관련 ]/php 2018. 11. 14. 14:18

PHP에서 회원 로그인 기능을 구현할 때 비밀번호 암호화 처리 과정을 살펴봅니다.

bcrypt를 이용하여 비밀번호를 암호화합니다. PHP 5.3.7 버전 이상에서 사용할 수 있습니다. PHP 5.5 버전 이상에서는 내장함수로 포함하고 있습니다. 추천하는 암호화 기법입니다.



1. 비밀번호를 암호화 하여 회원 DB Table에 기록하는 방법입니다.


<?

$id = "test";

$password = "1234567";  // 회원 가입시 입력받은 회원 비밀번호 


include "./password.php"; // 본 글 아래 첨부파일을 다운 받아 사용하세요. 

$hash = password_hash($password, PASSWORD_DEFAULT);  // 비밀번호 암호화 


// 회원가입시에는 비밀번호를 위의 암호화 과정을 거쳐 $hash 변수 값을 회원 DB Table에 저장합니다. 

$sql = "INSERT INTO member (num,id,password) VALUES ('$num', '$id', '$hash')"; 

if ($conn->query($sql) == TRUE) {

    echo "success";

} else {

    echo "Error";

}

$conn->close(); 

?>



2. 회원 로그인시 비밀번호를 비교하여 일치하면 로그인 세션을 생성합니다.


<?

$password = "1234567"; // 회원 로그인시 입력받은 비밀번호


// 회원 DB에서 회원 정보를 가져옵니다.

$result = mysql_query("SELECT * FROM  member WHERE id = '$id' LIMIT 1"); 

$array = mysql_fetch_array($result);

$hash_password  = $array['password']


include "./password.php"; // 본 글 아래 첨부파일을 다운 받아 사용하세요. 

if (password_verify($password, $hash_password)) { // 비밀번호가 일치하는지 비교합니다. 

echo "비밀번호 일치 !!!";  // 비밀번호가 일치할 경우 로그인 세션을 생성합니다.

} else { 

echo "비밀번호 불일치 !!!";

}

?>



* 비밀번호 암호화 방법 중 오래전 부터 사용하던 md5() 암호화는 보안에 취약하기 때문에 사용하지 마세요.


password.php 파일을 아래 첨부합니다. 다운받아서 사용하시면 됩니다.



password.zip



출처: http://kiwinote.tistory.com/40 [Kiwinote]






===================================================================================================== 



1. scrypt 



암호화 백업 서비스 tarsnap을 운영하는 

캐나다 프로그래머 콜린 퍼시벌(이름이 웬 ㅅㅂ이냐)이 개발한 암호화 알고리듬입니다. 

뚫기 어려운 걸로 말하자면 비교 대상이 없는 막강한 알고리듬이지만, 

너무 최신이라 PHP에서는 전혀 사용할 수 없으므로 패스. 



===================================================================================================== 



2. bcrypt 



해외에서 비밀번호 암호화에 대해 물어보면 즉시 돌아오는 모범답안입니다. 

예전부터 널리 사용되어 온 blowfish 양방향 암호화 알고리듬을 단방향으로 개조한 것으로, 

위에 언급한 scrypt를 제외하면 가장 막강한 후보입니다. 


PHP 5.5 이상에서는 아예 bcrypt 암호화 함수를 내장하고 있으므로 

아래와 같이 간단하게 사용 가능합니다. 



    암호화:  $hash = password_hash($password, PASSWORD_DEFAULT); 

                여기서 반환하는 $hash 값을 DB에 저장해 두었다가 아래에서 확인하는 데 씁니다. 


    확인:      if (password_verify($password, $hash)) { 

                    // 비밀번호가 맞음 

                } else { 

                    // 비밀번호가 틀림 

                } 



PHP 5.3.7 이상에서는 아래 링크의 파일을 인클루드한 후, 위와 똑같은 방법으로 쓰면 됩니다. 

위에서 사용한 내장 함수와 100% 호환됩니다. 

https://github.com/ircmaxell/password_compat/blob/master/lib/password.php 


그러나 대부분의 국내 웹호스팅에 설치되어 있는 PHP 5.2 버전에서는 bcrypt를 쓸 수가 없어요 ㅠㅠ 

예전부터 돌아다니던 phpass라는 라이브러리도 bcrypt를 지원한다고 하는데, 

이건 PHP 버전에 따라 그냥 md5() 함수를 사용해 버리기도 하더군요. 절대 비추입니다. 


그럼 어떻게 해야 할까요? 



===================================================================================================== 



3. PBKDF2 



RFC 2898에 규정되어 있으며, 세계 각국의 정부와 민간기업에서 오래 전부터 표준으로 쓰고 있는 알고리듬입니다. 

수많은 전문가들의 검증을 거쳤기 때문에 이거 썼다고 나무랄 사람은 아무도 없다는 것이 최대 장점이죠. 


게다가 bcrypt와 달리, 이건 PHP 5.1, 5.2 등에서도 대부분 사용이 가능합니다. 

흔히 쓰는 mcrypt 라이브러리가 설치되어 있고, 

hash_algos() 함수의 반환값 중 sha256이 포함되어 있는지만 확인하면 됩니다. 


표준 포맷을 PHP로 구현하는 소스는 아래의 주소에서 다운받아 인클루드하세요. 

https://defuse.ca/php-pbkdf2.htm 


최신 슈퍼컴퓨터로도 뚫기 어려운 강력한 보안을 원하시면 

PBKDF2_ITERATION 상수를 10000 정도로 바꿔주시는 것이 좋습니다. 

기본값은 1000 인데, 이건 아주 옛날에 쓰던 설정이라 요즘은 너무 낮다는 평가를 받아요. 

그러나 너무 높게 잡아놓으면 느려지므로 주의하세요. 



    암호화:  $hash = create_hash($password); 

                여기서 반환하는 $hash 값을 DB에 저장해 두었다가 아래에서 확인하는 데 씁니다. 


    확인:      if (validate_password($password, $hash)) { 

                    // 비밀번호가 맞음 

                } else { 

                    // 비밀번호가 틀림 

                } 



===================================================================================================== 



[부록] "저는 이미 md5() 쓰는데요? 이거 복호화도 안되는데 어떻게 bcrypt나 PBKDF2로 바꾸죠?" 


이런 질문 하실 분이 많을 것 같아서 부록을 준비했습니다. 

지금 쓰시는 알고리듬이 md5(), sha1(), 또는 비슷한 함수들의 조합이라면 

아래와 같이 하시면 됩니다. 


- 변환 작업 들어가기 전에 DB의 비밀번호 필드 자료형을 확인하고, 필요하다면 자료형을 바꿉니다. 

  예를 들어 md5() 함수는 항상 32바이트를 반환하므로 CHAR(32)로 해두셨을지도 몰라요. 

  그런데 bcrypt와 PBKDF2는 경우에 따라 60바이트 이상 반환하기도 합니다. 

  잘리지 않도록 필드 길이를 늘려주세요. VARCHAR(100) 정도 해두면 어떤 알고리듬이라도 넉넉합니다. 


- 기존의 회원 비밀번호는 암호화된 상태 그대로 bcrypt나 PBKDF2를 적용합니다. 

  미리 복호화할 필요 없어요. 


- 새로 가입하거나 비번 변경하는 회원은 기존의 알고리듬 한 번, 새 알고리듬 한 번, 이렇게 두 번 연달아 적용합니다. 

  예를 들어 XE처럼 md5(sha1(md5($password))) 이런 방식이었다면 

  password_hash(md5(sha1(md5($password)))) 이렇게 함수를 하나 더하는 거죠. 

  그러면 기존의 회원 비밀번호와 동일한 형식으로 통일되겠죠? 


- 비밀번호 체크할 때도 똑같이 하면 됩니다. 알고 보니 쉽죠? 

  예를 들면 if (password_verify(md5(sha1(md5($password))), $hash)) 


- 함수를 여러 개 쓰면 느려지지 않냐고요? 

  md5() 수천 번 돌려봤자 bcrypt나 PBKDF2 한 번 돌리는 것보다 시간 적게 걸립니다. 

  bcrypt나 PBKDF2는 딱 한 번만 돌리세요. 나머지는 아무리 많이 돌려봤자 차이를 느낄 수 없습니다. 


- 주의!!! 기존의 알고리듬이 "솔트"를 사용하고 있다면 위와 같이 쉽게 변환할 수 없습니다. 예: crypt() 함수 

  이 경우는 좀더 복잡한 과정을 거쳐야 하고, 잘못하면 다 틀려지니 주의하세요. 

  만약 솔트가 뭔지 모르신다면 해당 없습니다.


출처 : http://www.phpschool.com/link/tipntech/78316