pbkdf2 암호화 함수 적용
This commit is contained in:
+1
-1
@@ -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비밀번호는 대소문자를 구분합니다.');
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -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 로 변경
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
include_once(dirname(__FILE__) .'/pbkdf2.compat.php');
|
||||
|
||||
/*************************************************************************
|
||||
**
|
||||
** 일반 함수 모음
|
||||
@@ -3023,11 +3025,43 @@ function get_encrypt_string($str)
|
||||
// 비밀번호 비교
|
||||
function check_password($pass, $hash)
|
||||
{
|
||||
if(defined('G5_STRING_ENCRYPT_FUNCTION') && G5_STRING_ENCRYPT_FUNCTION === 'create_hash') {
|
||||
return validate_password($pass, $hash);
|
||||
}
|
||||
|
||||
$password = get_encrypt_string($pass);
|
||||
|
||||
return ($password === $hash);
|
||||
}
|
||||
|
||||
// 로그인 패스워드 체크
|
||||
function login_password_check($mb, $pass, $hash)
|
||||
{
|
||||
global $g5;
|
||||
|
||||
$mb_id = isset($mb['mb_id']) ? $mb['mb_id'] : '';
|
||||
|
||||
if(!$mb_id)
|
||||
return false;
|
||||
|
||||
if(G5_STRING_ENCRYPT_FUNCTION === 'create_hash' && strlen($hash) === G5_MYSQL_PASSWORD_LENGTH) {
|
||||
if( sql_password($pass) === $hash ){
|
||||
|
||||
if( ! isset($mb['mb_password2']) ){
|
||||
$sql = "ALTER TABLE `{$g5['member_table']}` ADD `mb_password2` varchar(255) NOT NULL default '' AFTER `mb_password`";
|
||||
sql_query($sql);
|
||||
}
|
||||
|
||||
$new_password = create_hash($pass);
|
||||
$sql = " update {$g5['member_table']} set mb_password = '$new_password', mb_password2 = '$hash' where mb_id = '$mb_id' ";
|
||||
sql_query($sql);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return check_password($pass, $hash);
|
||||
}
|
||||
|
||||
// 동일한 host url 인지
|
||||
function check_url_host($url, $msg='', $return_url=G5_URL, $is_redirect=false)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
if (!defined('_GNUBOARD_')) exit;
|
||||
|
||||
/*
|
||||
* Password Hashing with PBKDF2 (http://crackstation.net/hashing-security.htm).
|
||||
* Copyright (c) 2013, Taylor Hornby
|
||||
* All rights reserved.
|
||||
*
|
||||
* Modified to Work with Older Versions of PHP
|
||||
* Copyright (c) 2014, Kijin Sung
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// These constants may be changed without breaking existing hashes.
|
||||
|
||||
define('PBKDF2_COMPAT_HASH_ALGORITHM', 'SHA256');
|
||||
define('PBKDF2_COMPAT_ITERATIONS', 12000);
|
||||
define('PBKDF2_COMPAT_SALT_BYTES', 24);
|
||||
define('PBKDF2_COMPAT_HASH_BYTES', 24);
|
||||
|
||||
// Calculates a hash from the given password.
|
||||
|
||||
function create_hash($password, $force_compat = false)
|
||||
{
|
||||
// Generate the salt.
|
||||
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
$salt = base64_encode(mcrypt_create_iv(PBKDF2_COMPAT_SALT_BYTES, MCRYPT_DEV_URANDOM));
|
||||
} elseif (file_exists('/dev/urandom') && $fp = @fopen('/dev/urandom', 'r')) {
|
||||
$salt = base64_encode(fread($fp, PBKDF2_COMPAT_SALT_BYTES));
|
||||
} else {
|
||||
$salt = '';
|
||||
for ($i = 0; $i < PBKDF2_COMPAT_SALT_BYTES; $i += 2) {
|
||||
$salt .= pack('S', mt_rand(0, 65535));
|
||||
}
|
||||
$salt = base64_encode(substr($salt, 0, PBKDF2_COMPAT_SALT_BYTES));
|
||||
}
|
||||
|
||||
// Determine the best supported algorithm and iteration count.
|
||||
|
||||
$algo = strtolower(PBKDF2_COMPAT_HASH_ALGORITHM);
|
||||
$iterations = PBKDF2_COMPAT_ITERATIONS;
|
||||
if ($force_compat || !function_exists('hash_algos') || !in_array($algo, hash_algos())) {
|
||||
$algo = false; // This flag will be detected by pbkdf2_default()
|
||||
$iterations = round($iterations / 5); // PHP 4 is very slow. Don't cause too much server load.
|
||||
}
|
||||
|
||||
// Return format: algorithm:iterations:salt:hash
|
||||
|
||||
$pbkdf2 = pbkdf2_default($algo, $password, $salt, $iterations, PBKDF2_COMPAT_HASH_BYTES);
|
||||
$prefix = $algo ? $algo : 'sha1';
|
||||
return $prefix . ':' . $iterations . ':' . $salt . ':' . base64_encode($pbkdf2);
|
||||
}
|
||||
|
||||
// Checks whether a password matches a previously calculated hash
|
||||
|
||||
function validate_password($password, $hash)
|
||||
{
|
||||
// Split the hash into 4 parts.
|
||||
|
||||
$params = explode(':', $hash);
|
||||
if (count($params) < 4) return false;
|
||||
|
||||
// Recalculate the hash and compare it with the original.
|
||||
|
||||
$pbkdf2 = base64_decode($params[3]);
|
||||
$pbkdf2_check = pbkdf2_default($params[0], $password, $params[2], (int)$params[1], strlen($pbkdf2));
|
||||
return slow_equals($pbkdf2, $pbkdf2_check);
|
||||
}
|
||||
|
||||
// Checks whether a hash needs upgrading.
|
||||
|
||||
function needs_upgrade($hash)
|
||||
{
|
||||
// Get the current algorithm and iteration count.
|
||||
|
||||
$params = explode(':', $hash);
|
||||
if (count($params) < 4) return true;
|
||||
$algo = $params[0];
|
||||
$iterations = (int)$params[1];
|
||||
|
||||
// Compare the current hash with the best supported options.
|
||||
|
||||
if (!function_exists('hash_algos') || !in_array($algo, hash_algos())) {
|
||||
return false;
|
||||
} elseif ($algo === strtolower(PBKDF2_COMPAT_HASH_ALGORITHM) && $iterations >= 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);
|
||||
}
|
||||
Reference in New Issue
Block a user