이 글에서는 주로 PHP7.1에서 mcrypt를 대체하기 위해 openssl을 사용한 상세한 예시를 소개하고 있습니다. 필요하신 분들은 참고하시면 됩니다.
PHP 개발 시 mcrypt 관련 기능을 이용하면 AES 암호화를 쉽게 수행할 수 있습니다. 및 암호 해독 작업을 수행하지만 mcrypt 확장은 PHP7.1에서 폐기되므로 다른 구현을 찾아야 합니다. mcrypt를 openssl로 바꾸는 것은 이미 마이그레이션 매뉴얼에서 지적되었지만 구체적인 예는 제공되지 않습니다. 대부분의 시나리오를 대체할 수 있는 많은 예가 온라인에 있지만 자세한 내용은 설명되지 않습니다. 마찬가지로, 단순히 온라인 예제를 사용하면 특정 코드 시나리오에서 코드 교체 전후에 호환성 문제가 발생할 수 있습니다. 아래에서 구체적인 코드와 이유에 대해 이야기해 보겠습니다.
먼저 대체 코드를 직접 제공한 후, 코드에서 문제를 분석합니다. (이 글에서 분석된 알고리즘은 AES-128-CBC입니다.)
교체 예시
이 예시에서는 주로 패딩이 다르기 때문에 mcrypt를 사용하는 두 가지 방법을 보여줍니다(패딩에 대해서는 아래에서 설명합니다). 전체 암호화 및 암호 해독 과정에서 더 완전한 코드는 자동으로 채우기 및 채우기 제거를 구현하고 간단한 코드는 채우기를 직접 무시하지만 두 방법 모두 실제 개발(7.1 이전 버전)에서는 정상적으로 실행될 수 있으므로 권장됩니다. 패딩을 추가합니다. 다음 구체적인 예를 참조하십시오.
mcrypt는 패딩을 사용하지 않습니다.
mcrypt 암호화:
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString'; $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($cipher, $key, $iv); $cipherText256 = mcrypt_generic($cipher, $data); mcrypt_generic_deinit($cipher); return bin2hex($cipherText256);
동일한 기능에 대한 openssl 암호화 코드:
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString';
$data = $data . str_repeat("\x00", 16 - (strlen($data) % 16)); // 双引号可以解析asc-ii码\x00 return bin2hex(openssl_encrypt($data, "AES-256-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
엠크립트 패딩 사용
mcrypt 암호화:
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString'; // 填充(移除填充反着移除即可) $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $pad = $block - (strlen($data) % $block); if ($pad <= $block) { $char = chr($pad); $data .= str_repeat($char, $pad); } $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); mcrypt_generic_init($cipher, $key, $iv); $cipherText256 = mcrypt_generic($cipher, $data); mcrypt_generic_deinit($cipher); return bin2hex($cipherText256);
동일한 기능에 대한 openssl 암호화 코드:
$key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; $iv = 'aaaaaaaaaaaaaaaa'; $data = 'dataString'; return bin2hex(openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
위 예제는 모두 성공적으로 실행됩니다. 첫 번째 예제에서는 패딩을 사용하지 않고 패딩을 사용합니다. openssl ) 및 두 번째 예(패딩 포함, openssl에서는 패딩이 사용되지 않음)는 교체 전후에 동일한 출력을 가지며 호환성 문제가 없습니다. 코드의 다양한 채우기 방법에 따라 다양한 교체 솔루션을 선택할 수 있지만 세 가지 세부 사항을 설명해야 합니다
왜 채우기가 있나요?
openssl로 대체한 후 알고리즘 이름이 다른 이유는 무엇인가요?
다음 장에서는 채우기 및 알고리즘을 자세히 분석합니다.
Padding
패딩이 있는 이유는 암호화 알고리즘에서 시작됩니다. AES-128-CBC 알고리즘에서는 암호화할 문자열이 길이가 16바이트마다 세그먼트로 분할되고 단계별로 계산되므로 16바이트 미만의 세그먼트가 채워지기 때문입니다. 따라서 두 가지 유형의 예제가 제공됩니다. 하나는 기본 채우기를 사용하는 것이고 다른 하나는 독립적 채우기를 사용하는 것입니다. openssl로 대체할 때 패딩 구성표를 선택하려면 mcrypt 및 openssl의 기본 및 자율 패딩에 대한 이해가 필요합니다.
mcrypt는 기본적으로 채워져 있습니다
php의 소스코드를 보면 기본적으로 x00으로 채워져 있는 것을 볼 수 있는데, 실제로는 x00으로 채워져 있지 않다는 것을 알 수 있습니다. String에는 16비트 널 문자가 먼저 적용되므로 초기화 중에는 각 바이트가 x00이 됩니다. 실제로는 패딩이 없다고 할 수 있지만 기본 패딩을 사용하여 얻은 암호화된 문자열은 16비트입니다. 다음 형식:
mcrypt 기본 패딩
따라서 해독할 때 추가 x00을 제거해야 합니다. 물론 게으르고 x00을 제거하지 않을 수도 있습니다. PHP에서는 문자열 "stringx00"과 문자열 "string"이 길이가 다르다는 점을 제외하면 동일한 성능을 가지므로 차이가 없는 것 같습니다. 다음 코드는
// 尾部包含若干个`\x00` 均可功输出true if ("string\x00" == "string") { // 用双引号可解析\x00 echo true; }
x00으로 채워진 예입니다. 문자열 길이에 주의를 기울이면 x00을 사용한 패딩이 길이에 영향을 미치는 것을 볼 수 있습니다.)
mcrypt 자율 패딩
패딩 알고리즘은 다음 알고리즘에 따라 수행되어야 합니다.
패딩 추가
/** * 填充算法 * @param string $source * @return string */ function addPKCS7Padding($source) { $source = trim($source); $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $pad = $block - (strlen($source) % $block); if ($pad <= $block) { $char = chr($pad); $source .= str_repeat($char, $pad); } return $source; }
패딩을 추가한 후 문자열은 실제로 다음과 같습니다.
패딩 제거
/** * 移去填充算法 * @param string $source * @return string */ function stripPKSC7Padding($source) { $source = trim($source); $char = substr($source, -1); $num = ord($char); if ($num == 62) return $source; $source = substr($source, 0, -$num); return $source; }
openssl 기본 패딩
기본 방법은 다음과 일치합니다. 표준 mcrypt의 자율 패딩 방식이므로 두 번째 예에서는 위 패딩 알고리즘을 사용한 후 호환성 문제 없이 openssl_encrypt로 직접 대체할 수 있습니다. 패딩된 암호화 문자열은 다음과 같은 형식을 갖습니다.
패딩 및 패딩 제거 기능은 openssl_encrypt 및 openssl_decrypt에 내장되어 있으므로 패딩을 독립적으로 구현할 필요가 없으면 직접 사용할 수 있습니다. 패딩을 고려해야 합니다
openssl 자율 채우기
openssl_encrypt는 자율 채우기를 지원하는 옵션 매개 변수를 제공하지만 PHP 소스 코드에서 openssl 테스트 사례 코드를 참조한 후 올바른 사용법을 찾았습니다.
// if we want to manage our own padding $padded_data = $data . str_repeat(' ', 16 - (strlen($data) % 16)); $encrypted = openssl_encrypt($padded_data, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); $output = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); var_dump(rtrim($output)); (备注:如上,OPENSSL_ZERO_PADDING 并非是为0填充的意思)
이것으로 첫 번째 예에서 openssl_encrypt 이전에 x00을 충전하는 독립 포인트 코드가 추가된 이유를 설명할 수 있습니다.
위의 암호화와 복호화에서 채우기 논리가 다릅니다. 위의 예는 잘 설명할 수 있습니다:
예 1:
mcrypt는 암호화할 때 패딩을 사용하지 않기 때문에 x00으로 패딩되므로 openssl로 교체할 때 x00 채우기를 독립적으로 구현해야 합니다.
예 2:
mcrypt는 암호화 시 표준 패딩을 사용하는데, openssl의 패딩 방식도 표준 패딩이므로 직접 사용할 수 있습니다.
이를 분석해 보면 패딩 전략이 무엇이든 암호화 시에는 패딩 추가에 주의가 필요하고, 복호화 시에는 패딩을 제거해야 한다는 사실을 알 수 있습니다. 이제 위 예제의 채우기 관련 분석이 완료되었습니다. 다음으로 대체 알고리즘을 선택하는 방법을 살펴보겠습니다.
알고리즘 선택
위의 예에서는 mcrypt에서 AES가 실행되는 문제가 있습니다- 128- CBC 알고리즘, openssl에서 어떻게 AES_256으로 대체할 수 있나요?
이 점에 대해서는 한동안 소스코드를 확인해봐도 이유를 찾지 못했는데(능력 제한~) 다음을 통해 알아냈습니다. 정보, 기능이 아직 완료되었습니다
openssl 암호 해독 mcrypt AES 데이터 비호환 문제
mcrypt_generic을 openssl_encrypt로 변환 질문하기
Summary
암호화에 mcrypt AES를 사용하는 부분에 대해, 암호화 과정에서 문제가 있는 경우 교체 프로세스에서는 알고리즘 교체 또는 채우기라는 두 가지 측면을 고려할 수 있습니다. 동시에 충족해야 할 조건 중 하나는 다양한 충전 방법에 따라 선택하는 것입니다. 교체 시 고려해야 할 가장 중요한 것은 교체 후 변경 사항이 발생하지 않는지 확인하는 것입니다. 약간의 차이(마지막 몇 개의 문자열의 차이)만 있지만 여러 플랫폼에서 동시에 수정하는 것은 번거롭지만 변경 사항이 적을수록 위험은 줄어듭니다. 이 기사에서는 AES 알고리즘에 대해 간략하게 설명할 뿐입니다. 다른 알고리즘이 적용 가능한지는 아직 연구되지 않았습니다. 위 내용은 모두의 학습에 도움이 되기를 바랍니다. 더 많은 관련 내용은 PHP 중국어 홈페이지를 주목해주세요! 관련 권장사항:PHP는 캔버스 이미지를 HTML5로 서버에 저장하는 것을 구현합니다
위 내용은 PHP7.1에서 mcrypt를 대체하기 위해 openssl을 사용하는 방법 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!