Graceful Light

PHP 7.1에서 mcrypt 대체하기

2017-07-07


MCRYPT

암호화 함수인 mcrypt가 PHP 7.1버전부터 Deprecated 되었다.
왜 사라졌는지는 링크에 자세하게 나와있다.

기존 소스

PHP 구버전에서는 mcrypt와 MCRYPT_RIJNDAEL_128 알고리즘을 통해 AES128이 구현되어 있을 것이다.
MCRYPT_RIJNDAEL_128AES 128동일하다.

타 언어와는 조금 다른데, 호환을 위해선 pkcs5 padding으로 변경해주는 작업이 필요하다.
php mcrypt function의 기본 패딩은 zeros padding)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
// 이런 식이거나
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, pkcs5_pad($plaintext), MCRYPT_MODE_CBC, $iv);
// 이런 식일 것
$td = mcrypt_module_open("rijndael-128", "", "cbc", "");
@mcrypt_generic_init($td, $key, $iv);
$ciphertext = @mcrypt_generic($td, pkcs5_pad($plaintext));
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
function pkcs5_pad($text, $blocksize = 16) {
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}

대안

PHP 5.3부터 사용 가능한 openssl_encrypt 함수를 쓰면 된다. (openssl 확장 모듈이 설치되어야한다.)

OPENSSL

Encrypt

1
2
3
4
<?php
$ciphertext = openssl_encrypt($plaintext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
// decrypt에서 오류가 발생해 PKCS5로 패딩을 맞춰주고 보내야한다면.
$ciphertext = openssl_encrypt(pkcs5_pad($plaintext), 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);

Decrypt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$plaintext = openssl_decrypt($ciphertext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv);
// unpad가 필요하다면
$plaintext = pkcs5_unpad(openssl_decrypt($ciphertext, 'AES-128-CBC', $key, OPENSSL_RAW_DATA, $iv));
function pkcs5_unpad($text) {
$pad = ord($text{strlen($text)-1});
if ($pad > strlen($text)) {
return $text;
}
if (!strspn($text, chr($pad), strlen($text) - $pad)) {
return $text;
}
return substr($text, 0, -1 * $pad);
}

PKCS5 vs PKCS7

openssl_encrypt의 default padding은 PKCS7 padding인데, 어떻게 호환이 되는 것일까?
여기서 해답을 찾았다.

The difference between the PKCS#5 and PKCS#7 padding mechanisms is the block size;
PKCS#5 padding is defined for 8-byte block sizes, PKCS#7 padding would work for any block size from 1 to 255 bytes.
So fundamentally PKCS#5 padding is a subset of PKCS#7 padding for 8 byte block sizes.
so, data encrypted with PKCS#5 is able to decrypt with PKCS#7, but data encrypted with PKCS#7 may not be able to decrypt with PKCS#5.

triple des

des-ede3-cbc가 triple des 알고리즘이다.

1
2
3
4
5
6
<?php
// Encrypt
openssl_encrypt($text, "des-ede3-cbc", $key, OPENSSL_RAW_DATA, $iv);
// Decrypt
openssl_decrypt($ciphertext, "des-ede3-cbc", $key, OPENSSL_RAW_DATA, $iv);

여담

카카오페이가 PHP 5버전만 지원해 문의해봤지만 계획이 없어 이번 기회에 모듈을 다 뜯어봤는데 MCRYPT만 만져주면 정상적으로 결제가 되었다.

곧 이 짓을 안해도 될 듯하다.

이러다가 다시 선형대수학 공부하겠어.

🍺

Buy me a beer 🍗

공유하려면 QR코드를 스캔해주세요