import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.google.common.base.Charsets;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.*;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class Test {
/**
* sm2 加密解密
*/
public static class SM2Util{
static final BouncyCastleProvider bc = new BouncyCastleProvider();
/**
* 生成key
* @return
*/
public static Map<String,Object> generateKey(){
KeyPair pair = SecureUtil.generateKeyPair("SM2");
Map<String,Object> map = new HashMap<>();
map.put("publicKey",pair.getPublic());
map.put("privateKey",pair.getPrivate());
return map;
}
/**
* 加密
* @param data
* @param aPublic
* @return
*/
public static String encrypt(String data, PublicKey aPublic){
SM2 sm2 = SmUtil.sm2();
sm2.setPublicKey(aPublic);
String s = sm2.encryptBcd(data, KeyType.PublicKey);
return s;
}
/**
* 解密
* @param data
* @param privateKey
* @return
*/
public static String decrypt(String data, PrivateKey privateKey){
SM2 sm2 = SmUtil.sm2();
sm2.setPrivateKey(privateKey);
return StrUtil.utf8Str(sm2.decryptFromBcd(data,KeyType.PrivateKey));
}
/**
* 从字符串中读取 私钥 key
* @param privateKeyStr String
* @return PrivateKey
*/
public static PrivateKey strToPrivateKey(String privateKeyStr){
PrivateKey privateKey = null;
try {
byte[] encPriv = Base64.decode(privateKeyStr);
KeyFactory keyFact = KeyFactory.getInstance("EC", bc);
privateKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(encPriv));
}catch (Exception e){
e.printStackTrace();
}
return privateKey;
}
/**
* 从字符串中读取 公钥 key
* @param publicKeyStr String
* @return PublicKey
*/
public static PublicKey strToPublicKey(String publicKeyStr){
PublicKey publicKey = null;
try {
byte[] encPub = Base64.decode(publicKeyStr);
KeyFactory keyFact = KeyFactory.getInstance("EC", bc);
publicKey = keyFact.generatePublic(new X509EncodedKeySpec(encPub));
}catch (Exception e){
e.printStackTrace();
}
return publicKey;
}
/**
* 公钥 key 转文件
* @param publicKey PublicKey
* @param path String
*/
public static void exportPublicKey(PublicKey publicKey,String path){
File file = new File(path);
try {
File fileParent = file.getParentFile();
if(!fileParent.exists()){
fileParent.mkdirs();
}
file.createNewFile();
byte[] encPub = publicKey.getEncoded();
FileOutputStream fos = new FileOutputStream(file);
fos.write(encPub);
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 私钥 key 转文件
* @param privateKey PrivateKey
* @param keyPath String
*/
public static void exportPrivateKey(PrivateKey privateKey, String keyPath){
File file = new File(keyPath);
try {
File fileParent = file.getParentFile();
if(!fileParent.exists()){
fileParent.mkdirs();
}
file.createNewFile();
byte[] encPriv = privateKey.getEncoded();
FileOutputStream fos = new FileOutputStream(file);
fos.write(encPriv);
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 读取公钥文件
* @param path
* @return
*/
public static PublicKey importPublicKey(String path){
File file = new File(path);
try {
if (!file.exists()){
return null;
}
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[16];
int size;
while ((size = fis.read(buffer)) != -1){
baos.write(buffer,0,size);
}
fis.close();
byte[] bytes = baos.toByteArray();
String publicKeyStr = Base64.encode(bytes);
return strToPublicKey(publicKeyStr);
}catch (IOException e){
e.printStackTrace();
}
return null;
}
/**
* 读取私钥文件
* @param keyPath
* @return
*/
public static PrivateKey importPrivateKey(String keyPath){
File file = new File(keyPath);
try {
if (!file.exists()){
return null;
}
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buffer[] = new byte[16];
int size;
while ((size = fis.read(buffer)) != -1){
baos.write(buffer,0,size);
}
fis.close();
byte[] bytes = baos.toByteArray();
String privateKeyStr = Base64.encode(bytes);
return strToPrivateKey(privateKeyStr);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public static void test1(){
System.out.println("==============SM2 随机密钥对加密开始===============");
String text = "测试1111111";
SM2 sm2 = SmUtil.sm2();
//第一种 使用随机密钥对
String s = sm2.encryptBcd(text, KeyType.PublicKey);
System.out.println(s);
String s1 = StrUtil.utf8Str(sm2.decryptFromBcd(s, KeyType.PrivateKey));
System.out.println(s1);
System.out.println("==============SM2 随机密钥对加密结束===============");
}
public static void test2(){
System.out.println("==============SM2 自定义密钥对加密开始===============");
String text = "测试2222222";
SM2 sm = SmUtil.sm2();
String privateKeyBase64 = sm.getPrivateKeyBase64();
String publicKeyBase64 = sm.getPublicKeyBase64();
System.out.println("SM2 密钥:"+privateKeyBase64);
System.out.println("SM2 公钥:"+publicKeyBase64);
// 通过公钥进行加密
SM2 sm2 = SmUtil.sm2(null, publicKeyBase64);
String encryptStr = sm2.encryptBase64(text, KeyType.PublicKey);
System.out.println("SM2 加密后报文:"+ encryptStr);
// 通过密钥解密
SM2 sm22 = SmUtil.sm2(privateKeyBase64, null);
String s = sm22.decryptStr(encryptStr, KeyType.PrivateKey);
System.out.println("SM2 解密后报文:"+ s);
System.out.println("==============SM2 自定义密钥对加密结束===============");
}
public static void test3() {
System.out.println("==============SM2 文件密钥对加密开始===============");
String text = "测试aaaaaaaaa";
System.err.println("原文:"+text);
Map<String,Object> keyMap = generateKey();
//公钥 key 和私钥 key 转文件
exportPublicKey((PublicKey) keyMap.get("publicKey"),"F:\\sm2\\public_key.pem");
exportPrivateKey((PrivateKey) keyMap.get("privateKey"),"F:\\sm2\\private_key.pem");
//从pem文件里 读取 公钥 和 私钥
PublicKey pubk2 = importPublicKey("F:\\sm2\\public_key.pem");
PrivateKey priK2 = importPrivateKey("F:\\sm2\\private_key.pem");
//公钥加密
String sm2text = encrypt(text,pubk2);
System.err.println("SM2 加密后报文:"+sm2text);
//私钥解密
System.err.println("SM2 解密后报文:"+decrypt(sm2text,priK2));
System.out.println("==============SM2 文件密钥对加密结束===============");
}
}
/**
* sm4 加密解密
*/
public static class SM4Util{
/**
* 生成key
* @return
*/
public static String generateKey(){
return RandomUtil.randomString(16);
}
/**
* 加密
* @param data
* @param key
* @return
*/
public static String encrypt(String data, String key){
SymmetricCrypto sm4_en =SmUtil.sm4(key.getBytes(Charsets.UTF_8));
return sm4_en.encryptBase64(data);
}
/**
* 解密
* @param data
* @param key
* @return
*/
public static String decrypt(String data, String key){
SymmetricCrypto sm4_de =SmUtil.sm4(key.getBytes(Charsets.UTF_8));
return sm4_de.decryptStr(data, Charsets.UTF_8);
}
public static void test(){
System.out.println("==============SM4 加密开始===============");
String key = generateKey();
String ens = encrypt("测试123456",key);
System.out.println("SM4 加密:"+ens);
System.out.println("SM4 解密:"+decrypt(ens,key));
System.out.println("==============SM4 加密结束===============");
}
}
public static void main(String[] args) {
//sm2 加密解密
SM2Util.test1();
SM2Util.test2();
SM2Util.test3();
//sm3 加密
//需要注意的是 SM3 算法是不可逆的,只能从原文得到摘要签名,不能从摘要签名 反向得到原文
System.out.println("==============SM3 加密开始===============");
System.out.println("SM3 加密后报文:"+ SmUtil.sm3("123456"));
System.out.println("==============SM3 加密结束===============");
//sm4 加密解密
SM4Util.test();
}
}
Java 使用国密算法加密
最新推荐文章于 2025-03-02 17:56:46 发布