一、概述
- SM1-无具体实现
SM1作为一种对称加密算法,由于其算法细节并未公开,且主要在中国国内使用,因此在国际通用的加密库(如Bouncy Castle)中并不直接支持SM1算法。
SM1算法的具体实现涉及国家密码管理局的规范,通常需要使用国家指定的安全模块(如SSF33、SC1/SC2卡)或通过国家认证的加密硬件/软件产品来实现。
不过,如果你有合法授权并且在合规的环境下需要使用SM1算法,可能需要依赖特定的国产加密库或SDK,比如某些商用的密码机提供的SDK,这些SDK会封装好SM1的加解密接口供开发者调用。
但具体的实现代码和工具类因为涉及知识产权和国家安全规定,无法在这里直接提供。
- SM2
非对称加密、签名算法
加密 解密 加签 验签可替换
RSA
- SM3
签名算法 杂凑算法
加签 验签可替换
MD5
等Hash算法
- SM4
对称加解密密算法
加密 解密可替换
DES
- SM9-无具体实现
目前,标准的Java库如Bouncy Castle并不直接支持SM9算法;
因此可能需要使用特定的国密算法支持库或遵循国家密码管理局推荐的实现;
准备-添加依赖
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.64</version>
</dependency>
二、国密详解
2.1 SM2实现
import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;/*** SM2实现工具类*/
public class SM2Util {/** 这行代码是在Java中用于向安全系统添加Bouncy Castle安全提供器的。* Bouncy Castle是一个流行的开源加密库,它提供了许多密码学算法和安全协议的实现。* 通过调用Security.addProvider并传入BouncyCastleProvider对象,你可以注册Bouncy Castle提供的安全服务和算法到Java的安全框架中。* 这样一来,你就可以在你的应用程序中使用Bouncy Castle所提供的加密算法、密钥生成和管理等功能。*/static {Security.addProvider(new BouncyCastleProvider());}public static KeyPair generateKeyPair() throws Exception {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");keyPairGenerator.initialize(new ECGenParameterSpec("sm2p256v1"));return keyPairGenerator.generateKeyPair();}public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {Cipher cipher = Cipher.getInstance("SM2", "BC");cipher.init(Cipher.ENCRYPT_MODE, publicKey);return cipher.doFinal(data);}public static byte[] decrypt(PrivateKey privateKey, byte[] encryptedData) throws Exception {Cipher cipher = Cipher.getInstance("SM2", "BC");cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(encryptedData);}public static byte[] sign(PrivateKey privateKey, byte[] data) throws Exception {Signature signature = Signature.getInstance("SM3withSM2", "BC");signature.initSign(privateKey);signature.update(data);return signature.sign();}public static boolean verifySignature(PublicKey publicKey, byte[] data, byte[] signature) throws Exception {Signature sig = Signature.getInstance("SM3withSM2", "BC");sig.initVerify(publicKey);sig.update(data);return sig.verify(signature);}public static void main(String[] args) throws Exception {// 将公钥私钥字符串转换为PublicKey和PrivateKey对象KeyPair keyPair = generateKeyPair();PublicKey publicKey = keyPair.getPublic();System.out.println("Public Key: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));PrivateKey privateKey = keyPair.getPrivate();System.out.printf("Private Key: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));// 待加密数据byte[] dataToEncrypt = "Hello, SM2!".getBytes();// 加密byte[] encryptedData = encrypt(publicKey, dataToEncrypt);System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encryptedData));// 解密byte[] decryptedData = decrypt(privateKey, encryptedData);System.out.println("Decrypted: " + new String(decryptedData));// 加签byte[] signature = sign(privateKey, dataToEncrypt);System.out.println("Signature: " + Base64.getEncoder().encodeToString(signature));// 验签boolean isVerified = verifySignature(publicKey, dataToEncrypt, signature);System.out.println("Signature verified: " + isVerified);}}
2.2 SM3实现
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;/*** sm3工具类* 2024/6/25 16:29*/
public class SM3Util {/*** sm3签名* @param signString 待签名信息* @return 签名*/public static String sign(String signString) {byte[] bytes = signString.getBytes();byte[] result = new byte[32];SM3Digest sm3 = new SM3Digest();sm3.update(bytes, 0, bytes.length);sm3.doFinal(result, 0);return Hex.toHexString(result);}
}
2.3 SM4实现
import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;public class SM4Util {/*** 加密算法*/public static final String ALGORITHM = "SM4";/*** 加密工作模式:GCM* 数据填充模式:PKCS5Padding*/public static final String ALGORITHM_MODEL_GCM_PADDING = "SM4/GCM/NoPadding";/*** 随机数的长度*/public static final int NONCE_LENGTH = 128;static {// 添加Bouncy Castle providerSecurity.addProvider(new BouncyCastleProvider());}/*** 使用SM4-GCM模式加密** @param plainText 需要加密的内容* @param keyBytes 密钥字节数组* @param ivBytes 初始化向量字节数组* @return 加密之后的内容* @throws Exception 加密过程中可能发生的异常*/public static String encryptWithGCM(String plainText, byte[] keyBytes, byte[] ivBytes) throws Exception {SecretKeySpec sm4Key = new SecretKeySpec(keyBytes, ALGORITHM);GCMParameterSpec ivSpec = new GCMParameterSpec(NONCE_LENGTH, ivBytes);Cipher cipher = Cipher.getInstance(ALGORITHM_MODEL_GCM_PADDING, "BC");cipher.init(Cipher.ENCRYPT_MODE, sm4Key, ivSpec);byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(encryptedBytes);}/*** 使用SM4-GCM模式解密** @param cipherText 需要解密的内容* @param keyBytes 密钥字节数组* @param ivBytes 初始化向量字节数据* @return 解密之后内容* @throws Exception 解密过程中可能发生的异常*/public static String decryptWithGCM(String cipherText, byte[] keyBytes, byte[] ivBytes) throws Exception {SecretKeySpec sm4Key = new SecretKeySpec(keyBytes, ALGORITHM);GCMParameterSpec ivSpec = new GCMParameterSpec(NONCE_LENGTH, ivBytes);Cipher cipher = Cipher.getInstance(ALGORITHM_MODEL_GCM_PADDING, "BC");cipher.init(Cipher.DECRYPT_MODE, sm4Key, ivSpec);byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(cipherText));return new String(decryptedBytes, StandardCharsets.UTF_8);}/*** 使用SecureRandom生成指定长度的密钥或IV** @param length 密钥或IV的长度(字节数)* @return 生成的随机字节数组*/public static byte[] generateKey(int length) {SecureRandom secureRandom = new SecureRandom();byte[] bytes = new byte[length];secureRandom.nextBytes(bytes);return bytes;}/*** 生成指定长度的初始化向量(IV)** @param length IV的长度(字节数)* @return 生成的随机字节数组*/public static byte[] generateIV(int length) {// IV的生成方式与密钥相同,使用SecureRandomreturn generateKey(length);}public static void main(String[] args) throws Exception {String plainText = "1234测试567";// 使用随机的byte[] key = generateKey(16);byte[] iv = generateIV(16);String cipherText1 = encryptWithGCM(plainText, key, iv);System.out.println("加密后:" + cipherText1);String decryptedText1 = decryptWithGCM(cipherText1, key, iv);System.out.println("解密后:" + decryptedText1);}
}
三、聚合工具类SMUtil
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;public abstract class SMUtil {/*** SM1作为一种对称加密算法,由于其算法细节并未公开,且主要在中国国内使用,因此在国际通用的加密库(如Bouncy Castle)中并不直接支持SM1算法。* SM1算法的具体实现涉及国家密码管理局的规范,通常需要使用国家指定的安全模块(如SSF33、SC1/SC2卡)或通过国家认证的加密硬件/软件产品来实现。* 不过,如果你有合法授权并且在合规的环境下需要使用SM1算法,可能需要依赖特定的国产加密库或SDK,比如某些商用的密码机提供的SDK,这些SDK会封装好SM1的加解密接口供开发者调用。* 但具体的实现代码和工具类因为涉及知识产权和国家安全规定,无法在这里直接提供。**/abstract void sm1();/*** SM2生成 私钥和公钥* @return 私钥和公钥*/public static KeyPair sm2GenerateKeyPair() {try {return SM2Util.generateKeyPair();} catch (Exception e) {throw new RuntimeException(e);}}/*** sm2签名* @param privateKey 私钥* @param data 待签名内容* @return 签名*/public static String sm2Sign(PrivateKey privateKey, String data) {try {byte[] sign = SM2Util.sign(privateKey, data.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(sign);} catch (Exception e) {throw new RuntimeException(e);}}/*** sm2验签* @param publicKey 公钥* @param data 待验签内容* @param sign 签名* @return 是否验签通过*/public static boolean sm2VerifySign(PublicKey publicKey, String data, String sign) {try {return SM2Util.verifySignature(publicKey, data.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(sign));} catch (Exception e) {throw new RuntimeException(e);}}/*** sm2加密* @param publicKey 公钥* @param data 待加密内容* @return 加密之后的内容*/public static String sm2Encrypt(PublicKey publicKey, String data) {try {byte[] encrypt = SM2Util.encrypt(publicKey, data.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(encrypt);} catch (Exception e) {throw new RuntimeException(e);}}/*** sm2解密* @param privateKey 私钥* @param data 待解密内容* @return 解密之后的内容*/public static String sm2Decrypt(PrivateKey privateKey, String data) {try {byte[] decrypt = SM2Util.decrypt(privateKey, Base64.getDecoder().decode(data));return new String(decrypt, StandardCharsets.UTF_8);} catch (Exception e) {throw new RuntimeException(e);}}/*** sm3签名* @param signString 待签名信息* @return 签名*/public static String sm3Sign(String signString) {return SM3Util.sign(signString);}/*** sm4加密* 使用传输的密钥和初始化向量进行加密* @param plainText 需要加密的内容* @param key 密钥 长度必须为16* @param iv 初始化向量 长度必须为16* @return 加密之后的内容* @throws Exception 加密过程中可能发生的异常*/public static String sm4Encrypt(String plainText, String key, String iv) throws Exception {return SM4Util.encryptWithGCM(plainText, key.getBytes(StandardCharsets.UTF_8), iv.getBytes(StandardCharsets.UTF_8));}/**** sm4解密* 使用传输的密钥和初始化向量进行加密* @param plainText 需要加密的内容* @param key 密钥 长度必须为16* @param iv 初始化向量 长度必须为16* @return 加密之后的内容* @throws Exception 加密过程中可能发生的异常*/public static String sm4Decrypt(String plainText, String key, String iv) throws Exception {return SM4Util.decryptWithGCM(plainText, key.getBytes(StandardCharsets.UTF_8), iv.getBytes(StandardCharsets.UTF_8));}/*** 目前,标准的Java库如Bouncy Castle并不直接支持SM9算法;* 因此可能需要使用特定的国密算法支持库或遵循国家密码管理局推荐的实现;*/abstract void sm9();public static void main(String[] args) throws Exception {// sm2 演示// 生成密钥对KeyPair keyPair = sm2GenerateKeyPair();System.out.println(keyPair.getPrivate());System.out.println(keyPair.getPublic());String x = sm2Sign(keyPair.getPrivate(), "12谢谢哈哈");System.out.println(sm2VerifySign(keyPair.getPublic(), "12谢谢哈哈", x));String y = sm2Encrypt(keyPair.getPublic(), "12谢谢哈哈");System.out.println(sm2Decrypt(keyPair.getPrivate(), y));// sm3 演示String s = sm3Sign("12谢谢哈哈");System.out.println(s);// sm4String key = "jsikjrblkwqb79ik";String iv = "1224567890998880";String sm4Encrypt = sm4Encrypt("123测试!@456",key, iv);System.out.println(sm4Encrypt);String sm4Decrypt = sm4Decrypt(sm4Encrypt, key, iv);System.out.println(sm4Decrypt);}
}