Skip to content

Instantly share code, notes, and snippets.

@kijin
Created January 23, 2014 04:55
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save kijin/8573062 to your computer and use it in GitHub Desktop.
Save kijin/8573062 to your computer and use it in GitHub Desktop.
PHP에서 RSA 개인키/공개키 조합을 사용하여 서버에 비밀번호를 저장할 필요 없이 문자열을 암호화하는 법
<?php
// 비대칭 알고리듬인 RSA를 사용하여 문자열을 암호화하는 법.
// 개인키 비밀번호는 암호화할 때는 필요없고 복호화할 때만 입력하면 되므로
// 서버에 저장할 필요 없이 그때그때 관리자가 입력하도록 해도 된다.
// PHP 5.2 이상, openssl 모듈이 필요하다.
// RSA 개인키, 공개키 조합을 생성한다.
// 키 생성에는 시간이 많이 걸리므로, 한 번만 생성하여 저장해 두고 사용하면 된다.
// 단, 비밀번호는 개인키를 사용할 때마다 필요하다.
function rsa_generate_keys($password, $bits = 2048, $digest_algorithm = 'sha256')
{
$res = openssl_pkey_new(array(
'digest_alg' => $digest_algorithm,
'private_key_bits' => $bits,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
));
openssl_pkey_export($res, $private_key, $password);
$public_key = openssl_pkey_get_details($res);
$public_key = $public_key['key'];
return array(
'private_key' => $private_key,
'public_key' => $public_key,
);
}
// RSA 공개키를 사용하여 문자열을 암호화한다.
// 암호화할 때는 비밀번호가 필요하지 않다.
// 오류가 발생할 경우 false를 반환한다.
function rsa_encrypt($plaintext, $public_key)
{
// 용량 절감과 보안 향상을 위해 평문을 압축한다.
$plaintext = gzcompress($plaintext);
// 공개키를 사용하여 암호화한다.
$pubkey_decoded = @openssl_pkey_get_public($public_key);
if ($pubkey_decoded === false) return false;
$ciphertext = false;
$status = @openssl_public_encrypt($plaintext, $ciphertext, $pubkey_decoded);
if (!$status || $ciphertext === false) return false;
// 암호문을 base64로 인코딩하여 반환한다.
return base64_encode($ciphertext);
}
// RSA 개인키를 사용하여 문자열을 복호화한다.
// 복호화할 때는 비밀번호가 필요하다.
// 오류가 발생할 경우 false를 반환한다.
function rsa_decrypt($ciphertext, $private_key, $password)
{
// 암호문을 base64로 디코딩한다.
$ciphertext = @base64_decode($ciphertext, true);
if ($ciphertext === false) return false;
// 개인키를 사용하여 복호화한다.
$privkey_decoded = @openssl_pkey_get_private($private_key, $password);
if ($privkey_decoded === false) return false;
$plaintext = false;
$status = @openssl_private_decrypt($ciphertext, $plaintext, $privkey_decoded);
@openssl_pkey_free($privkey_decoded);
if (!$status || $plaintext === false) return false;
// 압축을 해제하여 평문을 얻는다.
$plaintext = @gzuncompress($plaintext);
if ($plaintext === false) return false;
// 이상이 없는 경우 평문을 반환한다.
return $plaintext;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment