PHP 암호화(해시) - BCrypt
조회수 5.5k 등록일 2016.05.18 00:05:33


개요

대부분의 PHP 어플리케이션들은 중요한 사용자 정보를 데이터베이스에 저장하여 액세스 및 관리하고 있습니다. 

대표적인 예로 어플리케이션 내 회원가입 시스템입니다. 회원들의 중요한 정보인 이름, 비밀번호 등을 암호화 없이 일반 텍스트로 저장 하게 된다면 악의적인 생각을 가지고 침입한 해커로 부터 보호하지 못해 쉽게 탈취 당하게 됩니다. 

웹 어플리케이션을 개발하는 웹개발자라면 이런 악의적인 해커로 부터 사용자 정보를 보호하는 것은 아주 중요한 부분이며 비밀번호를 보호하기 위한 최소한의 방법으로 암호화(해시)라는 기술을 사용합니다.





암호화란?

암호화는 새로운 기술이 아니며, 오래전부터 실용화되어 사용되어 지고 기술입니다. 암호화의 중요한 특징 중 하나로는 알고리즘이 단방향이어야 한다는 것입니다. 단방향이란 암호화된 데이터를 다시 원본 텍스트로 복구하는게 불가능 하다는 것이며, 따라서 악의적인 해커가 데이터베이스에 접근하더라도 쉽게 원본 텍스트로 복구가 불가능하는걸 말합니다. 다만, 사용자의 로그인을 위해서는 사용자가 입력한 비밀번호 해시 값과 데이터베이스에 저장된 해시 값을 비교 하여 결과를 도출하여야 합니다.




회원가입 프로세스


  1. 사용자는 회원가입을 합니다.
  2. 암호를 해시하여 데이터베이스에 저장합니다.



로그인 프로세스


  1. 사용자 로그인 폼에 ID,PW를 입력합니다.
  2. 입력한 PW의 해시값과 데이터베이스에 저장된 해시값을 비교합니다.
  3. 비교하여 일치하면 로그인 성공, 일치하지 않으면 로그인이 실패합니다.



bcrypt

bcrypt는 Blowfish symmetric block cipher 알고리즘을 기반으로 설계부터 비밀번호 저장을 위한 목적으로 개발되었으며 오늘날까지 사용되는 가장 강력한 해시 기술 중 하나입니다. "Key Factor" 또는 "Work Factor"를 사용하여 하나의 해시 digest 생성하는 데 얼마만큼의 처리 과정을 수행할지 결정하며 이는 가장 주목할 기능입니다. 컴퓨터가 발전함에 따라 해싱의 속도도 더욱 좋아짐에 따라 "work factor" 를 조정하여 해싱의 속도를 느리게 함으로 오토 크래킹으로 부터 보안성을 높일 수 있습니다.


* Blowfish symmetric block cipher : 키 방식의 대칭형 블록 암호 




PHP에 bcrypt 사용

PHP 버전 5.3 이상부터는 bcrypt 해시 기술이 기본적으로 내장되어 있습니다. 

서버 내 bcrypt가 사용 가능한지는 아래 코드로 확인 가능합니다.

  1. <?
  2. if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH)
  3.     echo "CRYPT_BLOWFISH is enabled!";
  4. else
  5.     echo "CRYPT_BLOWFISH is not available";
  6. ?>


서버에 bcrypt가 활성화 되어 있다면 비밀번호를 해시하여 저장합니다.

아래는 간단한 비밀번호 저장 쿼리입니다.

  1. $salt = '$2a$07$R.gJb2U2N.FmZ4hPp1y2CN$';
  2. $passwd = crypt("password", $salt);
  3. $query = sprintf("INSERT INTO USER (email, passwd, cdate) VALUES ('user_email','$passwd',now())");


$salt 변수값 중 $2a$가 바로 "work factory" 입니다. "work factor" 에 대해 더 자세한 설명은 CRYPT_BLOWFISH security fix details 를 참조하세요.

데이터베이스를 확인하시면 입력한 비밀번호인 "password"가 해시된 값으로 저장된걸 볼 수 있습니다.


이제 사용자가 로그인 한 경우 입력한 비밀번호와 데이터베이스 내 해시값을 비교하여 일치하면 로그인 성공, 불일치하면 로그인 실패로 처리하면 됩니다. 


/*     $password = 로그인 시 사용자가 입력한 비밀번호     $hashedPassword = 데이터베이스 내 저장된 비밀번호 해시값  */

<?

function verify($password , $hashedPassword ) {

     #로그인시 입력한 비밀번호의 해시값과 저장된 해시값 비교 

     return crypt($password, $hashedPassword) == $hashedPassword; }

?>

#




PHP 버전 5.5 이상부터는 새로운 해시 API가 추가되었습니다.

아래 새로운 해시 API에 대해 간단히 설명합니다.


1. password_hash() 

    - 암호를 해시하는데 사용됩니다.

 <?

  1.     #첫번째 매개변수 - $password - 해시할 값(비밀번호)
  2.     #두번째 매개변수 - PASSWORD_BCRYPT - 해시에 사용될 알고리즘(PASSWORD_DEFAULT, PASSWORD_BCRYPT, ...)
  3.     $hash = password_hash($password, PASSWORD_BCRYPT);
  4. ?>

"work factory" 같은 옵션의 경우 세번째 매개변수로 정의합니다.

  1. <?    
  2.     $options = [ 'cost' => 12 ] #기본 10 ;
  3.     $hash = password_hash($password, PASSWORD_DEFAULT, $options);
  4. ?>



2. password_verify() 

    - 해시된 값을 확인하는데 사용됩니다. 

    - 로그인 시

  1. <?    
  2.     if(password_verify($password, $hashedPassword)) 
  3.          #true
  4.     else 
  5.          #false
  6. ?>



3. password_needs_rehash() 

    - 비밀번호가 재사용 될떄 사용됩니다. 

    - 보안상의 이유로 "work factory" 를 강화할 필요가 있는 경우 기존 해시값을 변경해야 하는 경우.

  1. <?
  2.     if (password_needs_rehash($hash, PASSWORD_DEFAULT, ['cost' => 12])) {
  3.        $hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
  4.     }
  5. ?>


4. password_get_info() 

    - 해시될 떄 사용된 정보를 반환합니다.




참고 자료

최종 수정 일자 : 2016/05/19 02:59

잘보고갑니다~ 표연학 2016.05.20 01:06:07