开源AES/SM4/3DES对称加密算法介绍及其实现

news/2024/7/10 21:53:07 标签: AES, SM4, 3DES, 对称加密, 开源, java, 国密

AESSM43DES_0">AES/SM4/3DES对称秘钥加密介绍及其实现

  • 对称秘钥加密一般叫做对称加密对称主要是指秘钥对是对称的,对称相等的意思;
  • 密钥对就是指加密时使用的秘钥和解密时使用的秘钥,对称秘钥也就是加密秘钥和解密秘钥相同;

综上,对称秘钥加解密就是加密和解密的秘钥相同的加密算法,即实际只有1个秘钥的加密算法;

1. bq-encryptor对称秘钥加密介绍

  • 加密组件引入方法:
    <dependency>
        <groupId>com.biuqu</groupId>
        <artifactId>bq-encryptor</artifactId>
        <version>1.0.1</version>
    </dependency>
    

1.1 对称秘钥加密算法列表如下:

名称全称秘钥长度分组长度常用模式填充模式生成秘钥?常用算法特点
AESAdvanced Encryption Standard128
192
256
128ECB
CBC
CTR
CFB
NoPadding
PKCS5Padding
AES/ECB/PKCS5Padding
AES/CBC/PKCS5Padding
加密效率高
通常使用CBC/CTR模式
SM4SM4分组密码算法128128ECB
CBC
CTR
CFB
NoPadding
PKCS5Padding
SM4/CBC/PKCS5Padding
SM4/CTR/NoPadding
国密算法,安全性优于AES 256,可用于替换AES
通常使用CBC/CTR模式
3DESTriple Data Encryption Algorithm19264ECB
CBC
CTR
CFB
NoPadding
PKCS5Padding
DESede/ECB/PKCS5Padding
DESede/CBC/PKCS5Padding
安全性较差,建议使用AES/SM4来替代
  1. 加密长度: 在加密算法中通常是指秘钥长度;在摘要算法中通常是指内容块的长度;
  2. 分组长度: 在对称加密算法中,通常是指一次性可加密的密文块大小,比如AES/SM4一次性可加密出128bit的数据,3DES只能加密出64bit的数据;
  3. 3DES:是3个64bit的秘钥组合而成,所以才叫3重数据加密算法,每个加密的秘钥长度是64bit;对应的分组长度也是64bit,而AES/SM4都是128bit;

1.2 对称秘钥加密算法的特点如下:

  • 对称秘钥加密算法基本上都支持分段加密(也叫做分组加密),即报文超过了单次加密的最大长度,则自动叠加采取多次加密的方式,理论上对称加密是不限定报文大小的;
  • 对称加密的明文长度和密文长度的关系如下:
    • 在无填充模式(如NoPadding)下,对应的密文长度为:(${data.length}/${groupLen})*${groupLen},即密文长度和明文长度相等,且要求明文数据长度必须为分组长度的整数倍,否则会报错;
    • 在有填充模式(如PKCS5Padding)下,密文长度为:(${data.length}/${groupLen}+1)*${groupLen}
  • 对称加密ECB工作模式不支持偏移,体现在加密实现逻辑上就是不能加盐值,ECB工作模式是不安全的,不推荐使用;
  • 基于BouncyCastle的封装,对称秘钥加密算法的加密逻辑和解密逻辑基本相同;
  • BouncyCastle中,AES/SM4/3DES都支持由外部生成的任意长度的秘钥,但是AES/SM4只支持许可秘钥长度的秘钥加解密,3DES支持大于或者等于合法秘钥长度的秘钥(实际是截取其前面的合法秘钥长度内容)加解密;
  • 对称加密的效率高,但是在请求双方都需要解密的场景下,需要把秘钥同时发给对方,存在一定的秘钥管理的安全风险;
  • 考虑到加密的安全性,特地把加密偏移量(俗称盐值)的加解密当成常规使用;而提供没有盐值的加解密则仅为了和外部对接(己方为客户端,被迫接受服务端的不安全加密方式);

备注:

  1. ${data.length}/${groupLen}计算为整除;
  2. ${data.length}表示明文长度,${groupLen}表示分组长度;
  3. 3DES超出合法秘钥长度的秘钥与截取其合法秘钥长度的秘钥的加解密效果相同;

2. bq-encryptor对称秘钥加密实现

2.1 对称秘钥加密代码设计

bq-encryptor对称秘钥加密代码设计
算法名称算法实现类抽象类是否安全补充说明
AESAesEncryptionBaseSingleEncryption只有256位是安全的
SM4Sm4EncryptionAES256的国内替代算法
3DESDes3Encryption不安全算法,不推荐使用
AESAesSecureEncryptionBaseSecureSingleEncryptionAES加解密时增加了盐值
SM4Sm4SecureEncryptionSM4加解密时增加了盐值

2.2 对称秘钥加密核心逻辑

  • 对称秘钥加密的核心逻辑在BaseSingleEncryption抽象类(BaseSecureSingleEncryption亦为其子类)中:

    java"> /**
     * 加解密
     *
     * @param data       报文
     * @param key        秘钥
     * @param salt       盐值(偏移向量)
     * @param cipherMode 加密/解密(1和2分别表示加密和解密,参见{@link  javax.crypto.Cipher#DECRYPT_MODE})
     * @return 加解密后的报文
     */
    public byte[] doCipher(byte[] data, byte[] key, byte[] salt, int cipherMode)
    {
        try
        {
            Key keyObj = toKey(key);
            Cipher cipher = Cipher.getInstance(this.getPaddingMode(), this.getProvider());
            if (null == salt)
            {
                salt = new byte[EncryptionConst.DEFAULT_SALT_LEN];
            }
            IvParameterSpec vector = new IvParameterSpec(salt, 0, cipher.getBlockSize());
            if (!this.getPaddingMode().contains(ECB_MODE))
            {
                cipher.init(cipherMode, keyObj, vector);
            }
            else
            {
                cipher.init(cipherMode, keyObj);
            }
            return cipher.doFinal(data);
        }
        catch (Exception e)
        {
            throw new EncryptionException("do single key encrypt/decrypt error.", e);
        }
    }
    

总结下加密/解密的处理逻辑:

  1. 根据二进制秘钥获取秘钥对象;
  2. 设置盐值(ECB模式没有盐值);
  3. 初始化cipher对象并加密/解密;
  • 在抽象类BaseSingleEncryption的基础上,AesEncryption/Sm4Encryption/Des3Encryption仅需要定义其默认的加密长度、加密算法及填充模式默认值即可;
  • BaseSecureSingleEncryption则是在抽象类BaseSingleEncryption的基础上,对加解密逻辑都拼接了盐值的处理:
    java">/**
     * 自动填充盐值的对称秘钥加密计算
     *
     * @param data 明文
     * @param key  秘钥
     * @param salt 盐值(安全加密中不使用)
     * @return 随机盐值拼接加密后的报文
     */
    @Override
    public byte[] encrypt(byte[] data, byte[] key, byte[] salt)
    {
        byte[] saltBytes = this.genSalt();
        byte[] enData = this.doCipher(data, key, saltBytes, Cipher.ENCRYPT_MODE);
        byte[] newData = new byte[saltBytes.length + enData.length];
        System.arraycopy(saltBytes, 0, newData, 0, saltBytes.length);
        System.arraycopy(enData, 0, newData, saltBytes.length, enData.length);
        return newData;
    }
    
    /**
     * 解密带盐值的对称加密数据
     *
     * @param data 盐值拼接密文的数据
     * @param key  秘钥
     * @param salt 盐值(安全加密中不使用)
     * @return 明文
     */
    @Override
    public byte[] decrypt(byte[] data, byte[] key, byte[] salt)
    {
        byte[] saltBytes = new byte[this.saltLen];
        byte[] enData = new byte[data.length - saltBytes.length];
        System.arraycopy(data, 0, saltBytes, 0, saltBytes.length);
        System.arraycopy(data, saltBytes.length, enData, 0, enData.length);
        return this.doCipher(enData, key, saltBytes, Cipher.DECRYPT_MODE);
    }
    
  • 在抽象类BaseSecureSingleEncryption的基础上,AesSecureEncryption/Sm4SecureEncryption仅需要定义其默认的加密长度、加密算法及填充模式默认值即可;

3. bq-encryptor对称秘钥加密使用

SM4算法为例,可以有如下3种使用方式:

  • 使用方式1:直接创建SM4加密对象
    java">BaseSingleEncryption encryption = new Sm4Encryption();
    
  • 使用方式2:通过算法工厂创建SM4加密对象
    java">BaseSingleEncryption encryption = EncryptionFactory.SM4.createAlgorithm();
    
  • 使用方式3:安全加密器(SecurityFacade)/加密器(HsmFacade)获取初始化好了的带初始秘钥的SM4加密器
    java">BaseSingleEncryptor encryptor1 = ((EncryptSecurityImpl)securityFacade.getEncryptSecurity()).getSingleEncryptor(true);
    BaseSingleEncryptor encryptor2 = ((EncryptHsmImpl)hsmFacade.getEncryptHsm()).getSingleEncryptor(true);
    

http://www.niftyadmin.cn/n/349465.html

相关文章

Pytorch——在一个Tensor中随机保留一个True,其他全为False

需求 让一个[false,false,false,false,true,true]的tensor&#xff0c;变成随机只保留一个true的tensor&#xff0c;且可以并行处理&#xff1a; 要将一个布尔类型的张量 [False, False, False, False, True, True] 变成随机只保留一个 True 的张量&#xff0c;并且可以并行处…

优秀的前端开发框架

优秀的前端开发框架 1.Vue Vue2文档&#xff1a;Vue.js Vue3文档&#xff1a;Vue.js - 渐进式 JavaScript 框架 | Vue.js 用于构建用户界面的渐进式框架 Vue的核心库只关注视图层。可与elementUI配合Element - The worlds most popular Vue UI framework 2.React 原先的Fa…

软件测试基础知识整理(六)- 测试用例、等价类划分法、边界值分析法、判定表法

目录 一、测试用例&#xff08;重点&#xff09; 1.1 测试用例八大要素 二、等价类划分法 2.1 操作步骤 2.2 举例说明 三、边界值分析法 3.1 操作步骤 3.2 举例说明 四、判定表法 4.1 操作步骤 4.2 举例说明 一、测试用例&#xff08;重点&#xff09; 测试用例&…

做一个属于自己的坐标系的高德地图(GIS)

第一步:创建node环境&#xff1b; 第二步&#xff1a;创建一个html文件 第三步&#xff1a;引入高德的样式和行为依赖 第四步&#xff1a;创建容器让地图挂载在上边 <div id"map"></div> 第五步&#xff1a;先把地图渲染出来 const gaode new ol.l…

01 Android开机启动之整体分析

Android开机启动之整体分析 一、Android系统整体架构图 Android是谷歌开发的一款基于Linux的开源操作系统 PowerManagement:系统最底层是电源管理,只有通过电源上电,系统才能开启 Linux kernel:驱动层,里面包括Audio、Carmera、usb等各种外设的驱动程序。 HAL层:硬件…

人大金仓KingBase-跨库连表查询(可参考修改)

目前只测试了dblink的方式,business服务和user服务之间有跨库的连表操作,但是一般直接指定库名.模式.表明去连表,肯定会报错 com.kingbase8.util.KSQLException: 错误: 未实现跨数据库关联: "user.public.sys_org" 原sql: select count(*) from tbl_business where…

【html】制作一个能生成图片的markdown在线编辑器

markdown是什么&#xff0c;为什么大家都会用它呢&#xff0c;如果你想写文章&#xff0c;写文档&#xff0c;写作&#xff0c;用markdown是最好的选择&#xff0c;它是一个很好用的文档排版工具&#xff0c;觉得好用&#xff0c;何不尝试把它弄下来做成自己的呢&#xff0c;接…