From 352cf069442eefa6c63e84244b1573936143e751 Mon Sep 17 00:00:00 2001 From: thisgun Date: Thu, 11 Oct 2018 09:59:42 +0900 Subject: [PATCH] =?UTF-8?q?pbkdf2=20=EC=95=94=ED=98=B8=ED=99=94=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bbs/login_check.php | 2 +- config.php | 4 +- install/install_db.php | 2 +- lib/common.lib.php | 34 +++++++ lib/pbkdf2.compat.php | 221 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 260 insertions(+), 3 deletions(-) create mode 100644 lib/pbkdf2.compat.php diff --git a/bbs/login_check.php b/bbs/login_check.php index 3fe856313..ba7c65987 100644 --- a/bbs/login_check.php +++ b/bbs/login_check.php @@ -29,7 +29,7 @@ if(function_exists('social_is_login_check')){ // 가입된 회원이 아니다. 비밀번호가 틀리다. 라는 메세지를 따로 보여주지 않는 이유는 // 회원아이디를 입력해 보고 맞으면 또 비밀번호를 입력해보는 경우를 방지하기 위해서입니다. // 불법사용자의 경우 회원아이디가 틀린지, 비밀번호가 틀린지를 알기까지는 많은 시간이 소요되기 때문입니다. -if (!$is_social_password_check && (!$mb['mb_id'] || !check_password($mb_password, $mb['mb_password'])) ) { +if (!$is_social_password_check && (!$mb['mb_id'] || !login_password_check($mb, $mb_password, $mb['mb_password'])) ) { alert('가입된 회원아이디가 아니거나 비밀번호가 틀립니다.\\n비밀번호는 대소문자를 구분합니다.'); } diff --git a/config.php b/config.php index 57cadaacb..6d69fe466 100644 --- a/config.php +++ b/config.php @@ -166,7 +166,9 @@ define('G5_SMTP_PORT', '25'); // 암호화 함수 지정 // 사이트 운영 중 설정을 변경하면 로그인이 안되는 등의 문제가 발생합니다. -define('G5_STRING_ENCRYPT_FUNCTION', 'sql_password'); +//define('G5_STRING_ENCRYPT_FUNCTION', 'sql_password'); +define('G5_STRING_ENCRYPT_FUNCTION', 'create_hash'); +define('G5_MYSQL_PASSWORD_LENGTH', 41); // mysql password length 41, old_password 의 경우에는 16 // SQL 에러를 표시할 것인지 지정 // 에러를 표시하려면 TRUE 로 변경 diff --git a/install/install_db.php b/install/install_db.php index 431ff1740..28914b4de 100644 --- a/install/install_db.php +++ b/install/install_db.php @@ -176,7 +176,7 @@ sql_query($sql, true, $dblink); // 관리자 회원가입 $sql = " insert into `{$table_prefix}member` set mb_id = '$admin_id', - mb_password = PASSWORD('$admin_pass'), + mb_password = '".get_encrypt_string($admin_pass)."', mb_name = '$admin_name', mb_nick = '$admin_name', mb_email = '$admin_email', diff --git a/lib/common.lib.php b/lib/common.lib.php index b9d16cc64..b4ec2c59a 100644 --- a/lib/common.lib.php +++ b/lib/common.lib.php @@ -1,6 +1,8 @@ = PBKDF2_COMPAT_ITERATIONS) { + return false; + } else { + return true; + } +} + +// Compares two strings $a and $b in length-constant time. + +function slow_equals($a, $b) +{ + $diff = strlen($a) ^ strlen($b); + for($i = 0; $i < strlen($a) && $i < strlen($b); $i++) { + $diff |= ord($a[$i]) ^ ord($b[$i]); + } + return $diff === 0; +} + +// PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt +// Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt +// This implementation of PBKDF2 was originally created by https://defuse.ca +// With improvements by http://www.variations-of-shadow.com + +function pbkdf2_default($algo, $password, $salt, $count, $key_length) +{ + // Sanity check. + + if ($count <= 0 || $key_length <= 0) { + trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR); + } + + // Check if we should use the fallback function. + + if (!$algo) return pbkdf2_fallback($password, $salt, $count, $key_length); + + // Check if the selected algorithm is available. + + $algo = strtolower($algo); + if (!function_exists('hash_algos') || !in_array($algo, hash_algos())) { + if ($algo === 'sha1') { + return pbkdf2_fallback($password, $salt, $count, $key_length); + } else { + trigger_error('PBKDF2 ERROR: Hash algorithm not supported.', E_USER_ERROR); + } + } + + // Use built-in function if available. + + if (function_exists('hash_pbkdf2')) { + return hash_pbkdf2($algo, $password, $salt, $count, $key_length, true); + } + + // Count the blocks. + + $hash_length = strlen(hash($algo, '', true)); + $block_count = ceil($key_length / $hash_length); + + // Hash it! + + $output = ''; + for ($i = 1; $i <= $block_count; $i++) { + $last = $salt . pack('N', $i); // $i encoded as 4 bytes, big endian. + $last = $xorsum = hash_hmac($algo, $last, $password, true); // first iteration. + for ($j = 1; $j < $count; $j++) { // The other $count - 1 iterations. + $xorsum ^= ($last = hash_hmac($algo, $last, $password, true)); + } + $output .= $xorsum; + } + + // Truncate and return. + + return substr($output, 0, $key_length); +} + +// Fallback function using sha1() and a pure-PHP implementation of HMAC. +// The result is identical to the default function when used with SHA-1. +// But it is approximately 1.6x slower than the hash_hmac() function of PHP 5.1.2+, +// And approximately 2.3x slower than the hash_pbkdf2() function of PHP 5.5+. + +function pbkdf2_fallback($password, $salt, $count, $key_length) +{ + // Count the blocks. + + $hash_length = 20; + $block_count = ceil($key_length / $hash_length); + + // Prepare the HMAC key and padding. + + if (strlen($password) > 64) { + $password = str_pad(sha1($password, true), 64, chr(0)); + } else { + $password = str_pad($password, 64, chr(0)); + } + + $opad = str_repeat(chr(0x5C), 64) ^ $password; + $ipad = str_repeat(chr(0x36), 64) ^ $password; + + // Hash it! + + $output = ''; + for ($i = 1; $i <= $block_count; $i++) { + $last = $salt . pack('N', $i); + $xorsum = $last = pack('H*', sha1($opad . pack('H*', sha1($ipad . $last)))); + for ($j = 1; $j < $count; $j++) { + $last = pack('H*', sha1($opad . pack('H*', sha1($ipad . $last)))); + $xorsum ^= $last; + } + $output .= $xorsum; + } + + // Truncate and return. + + return substr($output, 0, $key_length); +}