SM4算法成为行业标准:
- SM4分组密码算法是2012年3月21日实施的一项行业标准;
- 2021年6月25日,我国SM4分组密码算法作为国际标准ISO/IEC 18033-3:2010/AMD1:2021《信息技术 安全技术 加密算法 第3部分:分组密码 补篇1:SM4》,由国际标准化组织ISO/IEC正式发布;
- 中文名SM4分组密码算法标准号GM/T 0002-2012实施日期2012-03-21发布日期2012-03-21技术归口国家密码管理局批准发布部门国家密码管理局。
SM4算法的重要性
- 是我国提出的分组密码算法,而且得到了国际的认可;
- 是继SM2/SM9数字签名算法、SM3密码杂凑算法、祖冲之密码算法和SM9标识加密算法之后,我国又一个商用密码算法被纳入ISO/IEC国际标准正式发布;
- 标志着我国商用密码算法国际标准体系进一步完善,展现了我国先进的密码科技水平和国际标准化能力,对提升我国商用密码产业发展、推动商用密码更好服务“一带一路”建设具有重要意义;
- 现在,国内已经掀起了国密算法改造的热潮。
SM4算法的特点
- SM4分组密码算法是一种迭代分组密码算法,由加解密算法和密钥扩展算法组成;
- SM4是一种Feistel结构的分组密码算法,其分组长度和密钥长度均为128bits。加密算法和密钥扩展算法迭代轮数均为32轮;
- SM4加解密过程的算法相同但是轮密钥的使用顺序相反;
- SM4密码算法使用模2加和循环移位作为基本运算;
- 密钥扩展算法:SM4算法使用128位的加密密钥,并采用32轮迭代加密结构,每一轮加密使用一个32位的轮密钥,总共使用32个轮密钥。因此需要使用密钥扩展算法,从加密密钥中产生32个轮密钥;
- 密钥:加密密钥的长度为128比特。
使用bcprov库实现SM4算法的封装
这里,使用maven编译。
1. pom文件中的引用:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.64</version>
</dependency>```
2. 工具类的实现(Sm4CryptTools)
package com.abc.smutilstest;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;
/**
* SM4算法工具类
*/
public class Sm4CryptTools {
//加解密的字节快大小
public static final int BlockSize = 16;
/**
* SM4ECB加密算法,对内
* @param in 待加密字节数组
* @param keyBytes 密钥
* @return
*/
private static byte[] ecb_encrypt(byte[] in, byte[] keyBytes) {
SM4Engine sm4Engine = new SM4Engine();
sm4Engine.init(true, new KeyParameter(keyBytes));
byte[] out = new byte[in.length];
int times = in.length / BlockSize;
for (int i = 0; i < times; i++) {
sm4Engine.processBlock(in, i * BlockSize, out, i * BlockSize);
}
return out;
}
/**
* SM4ECB加密算法
* @param in 待加密字节数组
* @param keyBytes 密钥
* @return
*/
public static String EcbEncrypt(byte[] in, byte[] keyBytes) {
byte[] out = ecb_encrypt(in, keyBytes);
String cipher = Hex.toHexString(out);
return cipher;
}
/**
* SM4的ECB加密算法
* @param content 待加密字符串, hex字符串
* @param key 密钥
* @return
*/
public static String EcbEncrypt(String content, String key) {
byte[] in = Hex.decode(content);
byte[] keyBytes = Hex.decode(key);
String cipher = EcbEncrypt(in, keyBytes);
return cipher;
}
/**
* SM4的ECB解密算法,对内
* @param in 输入的密文字符串
* @param keyBytes 密钥
* @return
*/
private static byte[] ecb_decrypt(byte[] in, byte[] keyBytes) {
SM4Engine sm4Engine = new SM4Engine();
sm4Engine.init(false, new KeyParameter(keyBytes));
int inLen = in.length;
byte[] out = new byte[inLen];
int times = inLen / BlockSize;
for (int i = 0; i < times; i++) {
sm4Engine.processBlock(in, i * BlockSize, out, i * BlockSize);
}
return out;
}
/**
* SM4的ECB解密算法,对外
* @param in 输入的密文字节数组
* @param keyBytes 密钥
* @return
*/
public static String EcbDecrypt(byte[] in, byte[] keyBytes) {
byte[] out = ecb_decrypt(in, keyBytes);
String plain = Hex.toHexString(out);
return plain;
}
/**
* SM4的ECB解密算法
* @param cipher 输入的密文字符串
* @param key 密钥
* @return
*/
public static String EcbDecrypt(String cipher, String key) {
byte[] in = Hex.decode(cipher);
byte[] keyBytes = Hex.decode(key);
String plain = EcbDecrypt(in, keyBytes);
return plain;
}
/**
* 测试函数
*/
public static void Sm4Test() {
String data = "FB8661A82ADD944230C3AD3957DAA224";
String key ="8012BADD542E2C182DFD84795E65A013";
String resCipherData = EcbEncrypt(data,key);
String resPlainData = EcbDecrypt(resCipherData,key);
System.out.println("原始明文:" + data);
System.out.println("加密后密文:" + resCipherData);
System.out.println("解密后明文:" + resPlainData);
}
/**
* 主函数
* @param args
*/
public static void main(String[] args) {
Sm4Test();
}
}
测试结果:
原始明文:FB8661A82ADD944230C3AD3957DAA224
加密后密文:bc5873a57ff7eda33d74a0b190f1b83f
解密后明文:fb8661a82add944230c3ad3957daa224
使用hutool库实现SM4算法的封装
pom.xml中引入hutool库:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
hutool库的使用:
/**
* hutool测试
*/
public static void TestcaseHutool1(String content){
SymmetricCrypto sm4Crypto = SmUtil.sm4();
String encryptHex = sm4Crypto.encryptHex(content);
System.out.println("原始明文:" + content);
System.out.println("加密结果:" + encryptHex);
String decryptStr = sm4Crypto.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
System.out.println("解密结果:" + decryptStr);
}
测试结果:
原始明文:abc
加密结果:b9e6c65f09bee33181d447416fe32271
解密结果:abc
结语:
SM4无需进行密钥交换,事先就可以直接指定密钥,也可以定期更新。更新后,旧的密文就无法用新的密钥解密了。
SM4可以防止明文传输数据被窃取。
相对于SM2非对称密码算法来说,SM4加解密速度快,适合数据内容比较大的加密场景。