Java实现常用加密算法-SM4

Java实现常用加密算法-SM4

参考博客:https://blog.csdn.net/m0_46713218/article/details/143099878

参考博客:sm4前后端加密集成

pom:

org.bouncycastle

bcprov-jdk18on

1.78.1

SM4加解密工具类:

package com.test.encrypt;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.util.encoders.Hex;

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import javax.crypto.spec.SecretKeySpec;

import java.nio.charset.StandardCharsets;

import java.security.SecureRandom;

import java.security.Security;

import java.util.Base64;

/**

* @description com.test.encrypt

* @author: chengyu

* @date: 2024-11-11 19:34

*/

public class EncryptUtils {

/**

* 指定加密算法

*/

private static final String ALGORITHM_NAME = "SM4";

/**

* BC中SM4默认使用ECB模式和PKCS5Padding填充方式

*/

private static final String ALGORITHM_ECB_PKCS5PADDING = "SM4/ECB/PKCS5Padding";

/**

* SM4算法目前只支持128位(即密钥16字节)

*/

private static final int DEFAULT_KEY_SIZE = 128;

static {

// 防止内存中出现多次BouncyCastleProvider的实例

if (null == Security.getProvider(BouncyCastleProvider.PROVIDER_NAME)) {

Security.addProvider(new BouncyCastleProvider());

}

}

/**

* 生成密钥

*

建议使用org.bouncycastle.util.encoders.Hex将二进制转成HEX字符串

*

* @return 密钥16位

* @throws Exception 生成密钥异常

*/

public static String generateKey() throws Exception {

KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);

kg.init(DEFAULT_KEY_SIZE, new SecureRandom());

return Hex.toHexString(kg.generateKey().getEncoded());

}

/**

* SM4对称加解密 加密

*

* @param plainString 待加密的字符串

* @param key 密钥

* @return 密文

*/

public static String sm4Encrypt(String plainString, String key) {

String cipherString = null;

try {

// 创建密钥规范

SecretKeySpec secretKeySpec = new SecretKeySpec(hexStringToBytes(key), ALGORITHM_NAME);

// 获取Cipher对象实例

Cipher cipher = Cipher.getInstance(ALGORITHM_ECB_PKCS5PADDING, BouncyCastleProvider.PROVIDER_NAME);

// 初始化Cipher为加密模式

cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

// 获取加密byte数组

byte[] cipherBytes = cipher.doFinal(plainString.getBytes(StandardCharsets.UTF_8));

// 输出为Base64编码

cipherString = Base64.getEncoder().encodeToString(cipherBytes);

} catch (Exception e) {

e.printStackTrace();

}

return cipherString;

}

/**

* SM4对称加解密 解密

* @param cipherString 密文

* @param key 密钥

* @return 明文

*/

public static String sm4Decrypt(String cipherString, String key) {

String plainString = null;

try {

// 创建密钥规范

SecretKeySpec secretKeySpec = new SecretKeySpec(hexStringToBytes(key), ALGORITHM_NAME);

// 获取Cipher对象实例

Cipher cipher = Cipher.getInstance(ALGORITHM_ECB_PKCS5PADDING, BouncyCastleProvider.PROVIDER_NAME);

// 初始化Cipher为解密模式

cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

// 获取加密byte数组

byte[] cipherBytes = cipher.doFinal(Base64.getDecoder().decode(cipherString));

// 输出为字符串

plainString = new String(cipherBytes);

} catch (Exception e) {

e.printStackTrace();

}

return plainString;

}

public static byte[] hexStringToBytes(String hexString) {

if (hexString != null && !hexString.equals("")) {

hexString = hexString.toUpperCase();

if (hexString.length() % 2 != 0) {

hexString = "0" + hexString;

}

int length = hexString.length() / 2;

char[] hexChars = hexString.toCharArray();

byte[] d = new byte[length];

for(int i = 0; i < length; ++i) {

int pos = i * 2;

d[i] = (byte)(charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

}

return d;

} else {

return null;

}

}

private static byte charToByte(char c) {

return (byte)"0123456789ABCDEF".indexOf(c);

}

}

测试类:

package com.test.encrypt;

import java.util.Locale;

/**

* @description com.test.encrypt

* @author: chengyu

* @date: 2024-11-11 19:32

*/

public class TestSm4 {

/**

* 默认国密sm4 key值,128bit=32位16进制字符串

*/

public static final String SM4_HEX_KEY_NJTK = "A7C9D1A8D93E6CFD7A175D1505598B1E";

public static void main(String[] args) throws Exception {

String key = EncryptUtils.generateKey().toUpperCase();

System.out.println("生成的密钥key: " + key);

String data = "P1sw@d4Dw";

String encrypt = EncryptUtils.sm4Encrypt(data, SM4_HEX_KEY_NJTK);

System.out.println("使用SM4开源包加密后:" + encrypt);

String decrypt = EncryptUtils.sm4Decrypt(encrypt, SM4_HEX_KEY_NJTK);

System.out.println("使用SM4开源包解密后:" + decrypt);

String decrypt2 = AlgUtil.decryptBySm4(SM4_HEX_KEY_NJTK, encrypt);

System.out.println("使用SM4 KL包解密后:" + decrypt2);

}

}

--

相关阅读