前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「安全系列」基于OpenSSL实现国密 SM4 加密和解密

「安全系列」基于OpenSSL实现国密 SM4 加密和解密

作者头像
Tinywan
发布2023-11-06 11:00:49
8260
发布2023-11-06 11:00:49
举报
文章被收录于专栏:开源技术小栈开源技术小栈

数据加密基础概念

在互联网发展的今天,数据传输已经成为了一项非常重要的技术,并且作为一种开放的网络,几乎所有的用户都有机会参与其中。但同时,数据的安全加密问题也成为了一个非常重要的话题,如何保障数据的传输安全也是一个重要的问题。

数据加密是一种常用的保护数据安全的手段。其基本思想就是将明文通过特定的算法加密处理,并将加密后的密文传输到目标地址,接收方再通过相应的解密算法将密文转换为明文。

openssl_encrypt介绍

openssl_encrypt 方法是PHP中的一个非常常用的加密方法,也是数据传输中常用的加密手段之一。它可以通过一个密钥和一个初始化向量,以及加密算法模式来加密数据。

代码语言:javascript
复制
/**
 *  openssl_encrypt — 使用openssl加密数据
 *  @param string $data    需要加密的数据
 *  @param string $method  加密算法
 *  @param string $key     密钥
 *  @param int $options    加密模式
 *  @param string $iv      初始化向量
 *  @return string
 *
 *  Example:
 *  openssl_encrypt("开源技术小栈", "AES-128-ECB", "123456", OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING);
 */
function openssl_encrypt(string $data , string $method , string $key , int $options = 0, string $iv = '') : string {}

加密模式介绍

openssl_encrypt方法中的加密模式通常包含以下几种:

  1. ECB(Electronic Codebook,电子密码本)模式:简单的将数据分块,然后对每个分块进行独立的加密
  2. CBC(Cipher-Block Chaining,密码块链接)模式:和ECB模式类似,「但是需要添加补齐位,避免可能存在的数据重复」
  3. CFB(Ciphertext Feedback,密文反馈)模式:将密文再次加密来防止重复,从而提高数据安全性
  4. OFB(Output Feedback,输出反馈)模式:和CFB模式类似,但是OFP模式不会对加密的数据再次进行加密

密钥和初始化向量方法

在使用openssl_encrypt方法进行加密时,我们需要生产密钥和初始化向量。密钥通常使用随机字节数组生成,可以使用openssl_random_pseudo_bytes函数来实现,如下所示:

代码语言:javascript
复制
$key = openssl_random_pseudo_bytes(16);

// 这里以上生成key为二进制。可以通过 bin2hex 函数转换为十六进制值

初始化向量通常也是由随机字节数组生成,使用方法如下所示:

代码语言:javascript
复制
$iv =openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-128-CBC'));

实现国密 SM4 加解密

使用SM4-CBC加密模式对数据进行加密

代码语言:javascript
复制
/**
* 1. 加密算法
* 注意:该算法需要添加补齐位 iv,避免可能存在的数据重复。iv值就是一个16位的随机数
*/
$cipherAlgo = 'SM4-CBC';


/**
* 2. 根据加密算法获取密码iv长度
*/
$ivLength = openssl_cipher_iv_length($cipherAlgo);
printf("[SM4加密iv长度]: %s\n", $ivLength);


/**
* 3. 根据iv长度获取对应算法的key
*/
$keyASCII = openssl_random_pseudo_bytes($ivLength);


/**
* 4. 把生成的key值 ASCII 字符的字符串转换为十六进制值
*/
$key = bin2hex($keyASCII);
printf("[SM4加密key值]: %s\n", $key);


/**
* 5. 初始化向量
*/
$ivBytes = openssl_random_pseudo_bytes(8);


/**
* 6. 初始化向量转换为十六进制值
*/
$iv = bin2hex($ivBytes); // 国密SM4算法这里会生成16位随机数,如:"0123456789123456"
printf("[SM4加密iv值]: %s\n", $iv);


/**
* 7. 使用openssl_encrypt方法加密数据
*/
$encryptText = '开源技术小栈';
// $encryptedStr = openssl_encrypt($encryptText, $cipherAlgo, $keyASCII, OPENSSL_CIPHER_RC2_40, $iv);
$encryptedStr = openssl_encrypt($encryptText, $cipherAlgo, hex2bin($key), OPENSSL_CIPHER_RC2_40, $iv);
printf("[SM4加密结果]: %s\n", $encryptedStr);


/**
* 8. 使用openssl_decrypt方法加密数据
*/
$decryptedStr = openssl_decrypt($encryptedStr, $cipherAlgo, hex2bin($key), OPENSSL_CIPHER_RC2_40, $iv);
printf("[SM4解密结果]: %s\n", $decryptedStr);
完整代码
代码语言:javascript
复制
<?php
/**
 * @desc 国密 SM4 加解密
 * @author Tinywan(ShaoBo Wan)
 * @email 756684177@qq.com
 * @date 2023/11/4 21:05
 */

declare(strict_types=1);

namespace security;

class SM4Util
{
    // 加密算法
    private const ALGORITHM = 'SM4-CBC';

    /**
     * @desc 加密
     * @param string $encryptText
     * @param string $key 32位秘钥key
     * @param string $iv 法密码iv长度
     * @return string
     * @author Tinywan(ShaoBo Wan)
     */
    public static function encrypt(string $encryptText, string $key, string $iv): string
    {
        return openssl_encrypt($encryptText, self::ALGORITHM, hex2bin($key), OPENSSL_CIPHER_RC2_40, $iv);
    }

    /**
     * @desc 解密
     * @param string $decryptText
     * @param string $key 32位秘钥key
     * @param string $iv 法密码iv长度
     * @return string
     * @author Tinywan(ShaoBo Wan)
     */
    public static function decrypt(string $decryptText, string $key, string $iv): string
    {
        return openssl_decrypt($decryptText, self::ALGORITHM, hex2bin($key), OPENSSL_CIPHER_RC2_40, $iv);
    }

    /**
     * @desc 获取iv值
     * @author Tinywan(ShaoBo Wan)
     */
    public static function main()
    {
        // 32位key
        $key = '4d7f2e7fe8e450385253bf379b13e432';

        // 获取对应算法密码iv长度
        $ivLength = openssl_cipher_iv_length(self::ALGORITHM);
        $iv = (string)rand(pow(10, ($ivLength - 1)), pow(10, $ivLength) - 1);

        // 加密字符串
        $plaintext = '开源技术小栈';
        $ciphertext = self::encrypt($plaintext, $key, $iv);
        printf("加密结果1: %s\n", $ciphertext);
        printf("解密结果2: %s\n", self::decrypt($ciphertext, $key, $iv));

    }
}

注意事项

  1. 在使用openssl_encrypt方法进行数据加密时,加密算法和模式需要根据实际情况选择,以提高加密的安全性
  2. 加密过程中生成的密钥和初始化向量需要保密存储,防止被攻击者窃取
  3. 对于特定的加密算法和模式,我们需要对其进行充分了解,以便能够更好地保护数据的安全性

总结

openssl_encrypt方法是一种常用的保护数据安全的手段,它可以通过一个密钥和一个初始化向量,以及加密算法模式来加密数据,从而保证数据传输的安全。

在使用openssl_encrypt方法进行数据加密时,我们需要注意算法和模式的选择,以提高加密算法的安全性。同时,加密过程中生成的密钥和初始化向量需要保密存储,并且需要对加密算法和模式进行充分了解,以便更好地保护数据的安全性。

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-11-05,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数据加密基础概念
  • openssl_encrypt介绍
  • 加密模式介绍
  • 密钥和初始化向量方法
  • 实现国密 SM4 加解密
  • 注意事项
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com