时间:2025-12-08 15:16
人气:
作者:admin
中华人民共和国政府采用的分组密码标准
SM4.0(原名SMS4.0)是中华人民共和国国家密码管理局于2012年3月21日发布的分组密码标准,对应行业标准为GM/T 0002-2012,采用128位分组长度和128位密钥结构,加密过程基于32轮非线性迭代,并配置固定8比特输入8比特输出的S盒,主要应用于商用数据加密领域
在密码学领域,国密算法 SM4 是我国自主研发的分组对称加密算法,凭借 128 位分组长度、128 位密钥长度的设计,在金融、政务、物联网等领域广泛应用。但分组密码本身仅能处理固定长度(SM4 为 128 位)的明文数据,而现实中需要加密的文件、数据流、存储块等往往是任意长度的。为解决这一问题,“工作模式” 应运而生 —— 它相当于分组密码的 “应用框架”,定义了如何将固定长度的分组加密逻辑扩展到任意长度数据,同时兼顾安全性、性能与实际场景需求。SM4 的 8 种主流工作模式:ECB、CBC、CFB、OFB、CTR、GCM、CCM 与 XTS
本文简单介绍SM4以下常用的加解密模式
流密码其余工作模式可参考博客:https://blog.csdn.net/openHiTLS/article/details/151288800
以下使用Bouncy Castle 开源加密库进行加解密
<!-- Maven 方式 -->
<!-- Bouncy Castle 开源加密库 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<!-- Gradle 方式 -->
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
package com.isoftstone.cascade02.utils;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
/**
* @Author:wk
* @Slogan:无论风雨,和自己一决胜负吧
* @Create:2025/12/5/18:16
* @Description:SM4算法 ECB 模式
* @Version:1.0
*/
public class SM4Utils {
public final static String KEY = "4c73aae48f4d5edba3a365837904dbc8";
private static final String ALGORITHM = "SM4";
private static final String TRANSFORM = "SM4/ECB/PKCS5Padding";
static {
Security.addProvider(new BouncyCastleProvider());
}
/** 生成 128-bit(16 字节)SM4 密钥,返回 Base64 字符串 */
/*public static String generateKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM, "BC");
kg.init(128, new SecureRandom());
byte[] keyBytes = kg.generateKey().getEncoded();
return Base64.getEncoder().encodeToString(keyBytes);
}*/
/** 生成UUID随机数,作为16进制密钥 */
public static String generateKey() throws Exception {
return CommonUtils.getUUID();
// byte[] keyBytes = kg.generateKey().getEncoded();
// return Base64.getEncoder().encodeToString(keyBytes);
}
/** 加密:明文 + Base64 密钥 → Base64 密文 */
public static String encrypt(String plainText, String base64Key) {
String encrypt = "";
try {
byte[] key = Hex.decodeHex(base64Key);
// byte[] key = Base64.getDecoder().decode(base64Key);
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORM, "BC");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
encrypt = Base64.getEncoder().encodeToString(encrypted);
} catch (DecoderException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return encrypt;
}
/** 解密:Base64 密文 + Base64 密钥 → 明文 */
public static String decrypt(String base64Cipher, String base64Key) {
String decrypt = "";
try {
byte[] key = Hex.decodeHex(base64Key);
// byte[] key = Base64.getDecoder().decode(base64Key);
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
Cipher cipher = Cipher.getInstance(TRANSFORM, "BC");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(base64Cipher));
decrypt = new String(decrypted, StandardCharsets.UTF_8);
} catch (DecoderException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decrypt;
}
/* ------ 简单测试 ------ */
public static void main(String[] args) throws Exception {
String plain = "你好,国密 SM4!";
String key = generateKey();
String cipher = encrypt(plain, key);
String result = decrypt(cipher, key);
System.out.println("密钥 :" + key);
System.out.println("密钥 :" + KEY);
System.out.println("明文 :" + plain);
System.out.println("密文 :" + cipher);
System.out.println("解密 :" + result);
}
}
package com.isoftstone.cascade02.utils;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
/**
* @Author:wk
* @Slogan:无论风雨,和自己一决胜负吧
* @Create:2025/12/5/18:16
* @Description:SM4 IV 算法
* @Version:1.0
*/
public class SM4IVUtils {
public final static String KEY = "4c73aae48f4d5edba3a365837904dbc8";
private static final String ALGORITHM = "SM4";
private static final String TRANSFORM = "SM4/CBC/PKCS5Padding";
static {
Security.addProvider(new BouncyCastleProvider());
}
/** 生成 128-bit(16 字节)SM4 密钥,返回 Base64 字符串 */
/*public static String generateKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM, "BC");
kg.init(128, new SecureRandom());
byte[] keyBytes = kg.generateKey().getEncoded();
return Base64.getEncoder().encodeToString(keyBytes);
}*/
/** 生成UUID随机数,作为16进制密钥 */
public static String generateKey() throws Exception {
return CommonUtils.getUUID();
}
/** 生成 16 字节 IV */
public static byte[] generateIV() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return iv;
}
/** 加密:返回 “Base64(IV) : Base64(密文)” 的拼接字符串 */
public static String encrypt(String plainText, String base64Key){
String encrypt = "";
try {
byte[] key = Hex.decodeHex(base64Key);
// byte[] key = Base64.getDecoder().decode(base64Key);
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
byte[] iv = generateIV();
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(TRANSFORM, "BC");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] cipherBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
// 把 IV 和密文一起发出去
String ivBase64 = Base64.getEncoder().encodeToString(iv);
String cipherBase64 = Base64.getEncoder().encodeToString(cipherBytes);
encrypt = ivBase64 + ":" + cipherBase64;
} catch (DecoderException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return encrypt;
}
/** 解密:传入 “Base64(IV) : Base64(密文)” 的拼接字符串 */
public static String decrypt(String pack, String base64Key) {
String decrypt = "";
try {
String[] parts = pack.split(":");
if (parts.length != 2) throw new IllegalArgumentException("数据格式错误");
byte[] key = Hex.decodeHex(base64Key);
// byte[] key = Base64.getDecoder().decode(base64Key);
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
byte[] iv = Base64.getDecoder().decode(parts[0]);
byte[] cipherBytes = Base64.getDecoder().decode(parts[1]);
Cipher cipher = Cipher.getInstance(TRANSFORM, "BC");
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
byte[] plainBytes = cipher.doFinal(cipherBytes);
decrypt = new String(plainBytes, StandardCharsets.UTF_8);
} catch (DecoderException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decrypt;
}
/* ------ 测试 ------ */
public static void main(String[] args) throws Exception {
String plain = "你好,国密 SM4-CBC!";
String key = generateKey(); // 复用上一篇的生成方法
String pack = encrypt(plain, KEY);
String ret = decrypt(pack, KEY);
System.out.println("密钥 :" + KEY);
System.out.println("明文 :" + plain);
System.out.println("包 :" + pack);
System.out.println("解密 :" + ret);
}
}
无论风雨,和自己一决胜负吧
【从0到1构建一个ClaudeAgent】协作-Agent团队