OpenSSL 1.1.1 开始已支持国密算法(https://www.openssl.org/news/changelog.txt),现在使用 PHP8 的 OpenSSL 扩展就可以实现国密算法加解密了,本文示例使用的是 PHP 8.1.17。

 

SM4-CBC 算法加解密示例:

if (!in_array('sm4-cbc', openssl_get_cipher_methods())) {
    printf("不支持 sm4\n");
}

$key = 'her-cat.com';
$iv = random_bytes(openssl_cipher_iv_length('sm4-cbc'));

$plaintext = '她和她的猫';

$ciphertext = openssl_encrypt($plaintext, 'sm4-cbc', $key, OPENSSL_RAW_DATA , $iv);

printf("加密结果: %s\n", bin2hex($ciphertext));

$original_plaintext = openssl_decrypt($ciphertext, 'sm4-cbc', $key, OPENSSL_RAW_DATA , $iv);

printf("解密结果: %s\n", $original_plaintext);

 

SM4-ECB 算法加解密示例:

if (!in_array('sm4-ecb', openssl_get_cipher_methods())) {
    printf("不支持 sm4\n");
}

$key = 'her-cat.com';

$plaintext = '她和她的猫';

$ciphertext = openssl_encrypt($plaintext, 'sm4-ecb', $key, OPENSSL_RAW_DATA);

printf("加密结果: %s\n", bin2hex($ciphertext));

$original_plaintext = openssl_decrypt($ciphertext, 'sm4-ecb', $key, OPENSSL_RAW_DATA);

printf("解密结果: %s\n", $original_plaintext);

 

有些合作平台给的 key 是经过 base64 编码的,使用前需要解码成原来的二进制字符串:

$key = 'dRzPaYd7z6vYn9sL/JTZ3A==';
$key = base64_decode($key);

 

又或者给的 key 被转成了16进制字符串,需使用 hex2bin 函数转回原来的二进制字符串:

$key = '29cce00263d98b736ed03319ba06307b';
$key = hex2bin($key);

 

参考文章:https://her-cat.com/posts/2021/08/23/php-openssl-sm4/