赞
踩
常用的国密算法包含SM2,SM3,SM4。以下针对每个算法使用场景进行说明以比较其差异
注:
如果用于加密,那么加密是用公钥进行的,解密是用私钥进行的。
如果用于数字签名,那么签名是用私钥进行的,验证签名则使用公钥。
基于Java的SM4(ECB模式,CBC模式)对称加解密实现
简单说明:加密算法依赖了groupId:org.bouncycastle中的bcprov-jdk15to18,Bouncy Castle (bcprov-jdk15to18
)提供了JDK 1.5 to 1.8可使用的大量标准加密算法实现,其中包含了SM2,SM3,SM4。在这个类库基础上实现了一个SM4Util加解密工具类。注意: 此版本我在JDK1.8环境下,不同版本JDK需要找到匹配的依赖版本1.8及以上可以使用bcprov-jdk18on。Bouncy Castle同时也提供了bcutil-jdk15to18可以实现SM4加解密。
方式一:依赖bcprov-jdk15to18(以ECB模式为例) 注如果用jdk1.8的话使用bcprov-jdk18on比bcprov-jdk15to18的加密性能要好。
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk15to18</artifactId>
- <version>1.77</version>
- </dependency>
字节数组处理工具类:
- public class ByteUtils {
-
- private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
- 'f' };
-
- private ByteUtils() {
- // Utility class
- }
-
- public static byte[] fromHexString(String s) {
- int len = s.length();
- //
- // // Data length must be even
- // if (len % 2 != 0) {
- // throw new IllegalArgumentException("Hex string has an odd number of
- // characters");
- // }
-
- byte[] data = new byte[len / 2];
- for (int i = 0; i < len; i += 2) {
- data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
- }
- return data;
- }
-
-
-
- public static String toHexString(byte[] input) {
- StringBuilder sb = new StringBuilder();
- for (byte b : input) {
- sb.append(HEX_CHARS[(b >>> 4) & 0x0f]);
- sb.append(HEX_CHARS[b & 0x0f]);
- }
- return sb.toString();
- }
-
-
- public static String toHexString(byte[] input, String prefix, String separator) {
- StringBuilder sb = new StringBuilder(prefix);
- for (int i = 0; i < input.length; i++) {
- sb.append(HEX_CHARS[(input[i] >>> 4) & 0x0f]);
- sb.append(HEX_CHARS[input[i] & 0x0f]);
- if (i < input.length - 1) {
- sb.append(separator);
- }
- }
- return sb.toString();
- }
-
- }
加解密工具类:
- import java.nio.charset.StandardCharsets;
- import java.security.Key;
- import java.security.MessageDigest;
- import java.security.SecureRandom;
- import java.security.Security;
- import java.util.Arrays;
- import javax.crypto.Cipher;
- import javax.crypto.KeyGenerator;
- import javax.crypto.spec.SecretKeySpec;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
- public class Sm4Utils {
- static {
- Security.addProvider(new BouncyCastleProvider());
- }
- private static final String ENCODING = "UTF-8";
- public static final String ALGORIGTHM_NAME = "SM4";
- public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS7Padding";
- public static final int DEFAULT_KEY_SIZE = 128;
-
- private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
- Cipher cipher = Cipher.getInstance(algorithmName, "BC");
- Key sm4Key = new SecretKeySpec(key, ALGORIGTHM_NAME);
- cipher.init(mode, sm4Key);
- return cipher;
- }
-
- public static byte[] generateKey(String keyString) throws Exception {
- // Use SHA-256 to hash the string and then take first 128 bits (16 bytes)
- MessageDigest digest = MessageDigest.getInstance("SHA-256");
- byte[] hash = digest.digest(keyString.getBytes(StandardCharsets.UTF_8));
- byte[] key = new byte[16];
- System.arraycopy(hash, 0, key, 0, 16);
- return key;
- }
-
- public static String encryptEcb(String key, String paramStr, String charset) throws Exception {
- String cipherText = "";
- if (null != paramStr && !"".equals(paramStr)) {
- byte[] keyData = generateKey(key);
- charset = charset.trim();
- if (charset.length() <= 0) {
- charset = ENCODING;
- }
- byte[] srcData = paramStr.getBytes(charset);
- byte[] cipherArray = encryptEcbPadding(keyData, srcData);
- cipherText = ByteUtils.toHexString(cipherArray);
- }
-
- return cipherText;
- }
-
- public static byte[] encryptEcbPadding(byte[] key, byte[] data) throws Exception {
- Cipher cipher = generateEcbCipher("SM4/ECB/PKCS7Padding", Cipher.ENCRYPT_MODE, key);
- byte[] bs = cipher.doFinal(data);
- return bs;
- }
-
- public static String decryptEcb(String key, String cipherText, String charset) throws Exception {
- String decryptStr = "";
- byte[] keyData = generateKey(key);
- byte[] cipherData = ByteUtils.fromHexString(cipherText);
- byte[] srcData = decryptEcbPadding(keyData, cipherData);
- charset = charset.trim();
- if (charset.length() <= 0) {
- charset = ENCODING;
- }
-
- decryptStr = new String(srcData, charset);
- return decryptStr;
- }
-
- public static byte[] decryptEcbPadding(byte[] key, byte[] cipherText) throws Exception {
- Cipher cipher = generateEcbCipher("SM4/ECB/PKCS7Padding", Cipher.DECRYPT_MODE, key);
- return cipher.doFinal(cipherText);
- }
-
- public static void main(String[] args) {
- try {
- String json = "311111190001010001";
- String key = "test";
- String cipher = encryptEcb(key, json, ENCODING);
- System.out.println(cipher);
- System.out.println(decryptEcb(key, cipher, ENCODING));
- } catch (Exception var5) {
- var5.printStackTrace();
- }
-
- }
- }
方式二:依赖bcprov-jdk15to18(以CBC模式为例),代码根据GPT-4生成修改调试,可运行。
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk15to18</artifactId>
- <version>1.77</version>
- </dependency>
-
- import org.bouncycastle.crypto.CipherParameters;
- import org.bouncycastle.crypto.engines.SM4Engine;
- import org.bouncycastle.crypto.modes.CBCBlockCipher;
- import org.bouncycastle.crypto.modes.CBCModeCipher;
- import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
- import org.bouncycastle.crypto.params.KeyParameter;
- import org.bouncycastle.crypto.params.ParametersWithIV;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
- import java.security.Security;
- import java.util.Arrays;
-
- public class SM4Example {
- static {
- Security.addProvider(new BouncyCastleProvider());
- }
-
- public static byte[] encrypt(byte[] key, byte[] iv, byte[] data) throws Exception {
- SM4Engine engine = new SM4Engine();
- CBCModeCipher cbcBlockCipher = CBCBlockCipher.newInstance(engine);
- PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(cbcBlockCipher);
- CipherParameters params = new ParametersWithIV(new KeyParameter(key), iv);
- cipher.init(true, params);
-
- byte[] temp = new byte[cipher.getOutputSize(data.length)];
- int len = cipher.processBytes(data, 0, data.length, temp, 0);
- len += cipher.doFinal(temp, len);
-
- byte[] out = new byte[len];
- System.arraycopy(temp, 0, out, 0, len);
- return out;
- }
-
- public static byte[] decrypt(byte[] key, byte[] iv, byte[] data) throws Exception {
- SM4Engine engine = new SM4Engine();
- CBCModeCipher cbcBlockCipher = CBCBlockCipher.newInstance(engine);
- PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(cbcBlockCipher);
- CipherParameters params = new ParametersWithIV(new KeyParameter(key), iv);
- cipher.init(false, params);
-
- byte[] temp = new byte[cipher.getOutputSize(data.length)];
- int len = cipher.processBytes(data, 0, data.length, temp, 0);
- len += cipher.doFinal(temp, len);
-
- byte[] out = new byte[len];
- System.arraycopy(temp, 0, out, 0, len);
- return out;
- }
-
- public static void main(String[] args) throws Exception {
- byte[] key = "0123456789abcdef".getBytes(); // 16-byte key for SM4
- byte[] iv = "abcdef9876543210".getBytes(); // 16-byte IV for CBC mode
- byte[] dataToEncrypt = "Hello, Bouncy Castle SM4!".getBytes();
-
- byte[] encryptedData = encrypt(key, iv, dataToEncrypt);
- System.out.println("Encrypted Data: " + java.util.Base64.getEncoder().encodeToString(encryptedData));
-
- byte[] decryptedData = decrypt(key, iv, encryptedData);
- System.out.println("Decrypted Data: " + new String(decryptedData));
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。