Skip to content

Instantly share code, notes, and snippets.

@kijin
Last active September 18, 2019 14:44
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save kijin/8404004 to your computer and use it in GitHub Desktop.
Save kijin/8404004 to your computer and use it in GitHub Desktop.
PHP에서 AES-256과 HMAC을 사용하여 문자열을 암호화하고 위변조를 방지하는 법
<?php
// AES-256과 HMAC을 사용하여 문자열을 암호화하고 위변조를 방지하는 법.
// 비밀번호는 서버만 알고 있어야 한다. 절대 클라이언트에게 전송해서는 안된다.
// PHP 5.2 이상, mcrypt 모듈이 필요하다.
// 문자열을 암호화한다.
function aes_encrypt($plaintext, $password)
{
// 보안을 최대화하기 위해 비밀번호를 해싱한다.
$password = hash('sha256', $password, true);
// 용량 절감과 보안 향상을 위해 평문을 압축한다.
$plaintext = gzcompress($plaintext);
// 초기화 벡터를 생성한다.
$iv_source = defined('MCRYPT_DEV_URANDOM') ? MCRYPT_DEV_URANDOM : MCRYPT_RAND;
$iv = mcrypt_create_iv(32, $iv_source);
// 암호화한다.
$ciphertext = mcrypt_encrypt('rijndael-256', $password, $plaintext, 'cbc', $iv);
// 위변조 방지를 위한 HMAC 코드를 생성한다. (encrypt-then-MAC)
$hmac = hash_hmac('sha256', $ciphertext, $password, true);
// 암호문, 초기화 벡터, HMAC 코드를 합하여 반환한다.
return base64_encode($ciphertext . $iv . $hmac);
}
// 위의 함수로 암호화한 문자열을 복호화한다.
// 복호화 과정에서 오류가 발생하거나 위변조가 의심되는 경우 false를 반환한다.
function aes_decrypt($ciphertext, $password)
{
// 초기화 벡터와 HMAC 코드를 암호문에서 분리하고 각각의 길이를 체크한다.
$ciphertext = @base64_decode($ciphertext, true);
if ($ciphertext === false) return false;
$len = strlen($ciphertext);
if ($len < 64) return false;
$iv = substr($ciphertext, $len - 64, 32);
$hmac = substr($ciphertext, $len - 32, 32);
$ciphertext = substr($ciphertext, 0, $len - 64);
// 암호화 함수와 같이 비밀번호를 해싱한다.
$password = hash('sha256', $password, true);
// HMAC 코드를 사용하여 위변조 여부를 체크한다.
$hmac_check = hash_hmac('sha256', $ciphertext, $password, true);
if ($hmac !== $hmac_check) return false;
// 복호화한다.
$plaintext = @mcrypt_decrypt('rijndael-256', $password, $ciphertext, 'cbc', $iv);
if ($plaintext === false) return false;
// 압축을 해제하여 평문을 얻는다.
$plaintext = @gzuncompress($plaintext);
if ($plaintext === false) return false;
// 이상이 없는 경우 평문을 반환한다.
return $plaintext;
}
@sctaix
Copy link

sctaix commented May 16, 2017

php5 에서 생성한 암호문를 php7에서 복호화가 안되는 이유는 단지 php 환경이 다르기 때문인가요?

@76069884
Copy link

PHP 7.1 이후 encrypt삭제가 되었는데 해당 부분은 예정이 있으신가요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment