基于 OpenSSL 实现国密 SM4 加解密

2021-08-23
次阅读
1 分钟阅读时长
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);

运行结果:

加密结果: 45cd787b0a84603ae8fd443b81af4d17
解密结果: 她和她的猫

2023.04.11 更新:

今天收到了一位读者的邮件,他在对接银联支付时遇到了问题,使用 PHP 生成的密文与银联支付提供的 Java 示例生成的密文不一致。

银联支付提供的 Java 示例代码:https://open.unionpay.com/tjweb/support/doc/online/14/393

针对这个问题,只需要在加密前将 key 从 16 进制字符串转换为二进制字符串,即可得到与 Java 示例相同的密文。

$key = '长度为 32 的字符串';
$iv = '0123456789123456';
$plaintext = '测试内容';
$key = hex2bin($key); // 增加这一行
$ciphertext = openssl_encrypt($plaintext, 'sm4-cbc', $key, 0, $iv);

希望能帮助到遇到相同问题的朋友。

本文作者:她和她的猫
本文地址https://her-cat.com/posts/2021/08/23/php-openssl-sm4/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!