package com.ruoyi.common.third.utils;

import org.bouncycastle.util.encoders.Hex;

import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
/**
 * 类的用途：SM4加密解密工具类
 * <p>
 * 对称加密，密钥长度和分组长度均为128位 <br>
 */
public class SM4Util {
//	中招回传数据加密使用
	private static final String sm4Key="20e21dacfc5eff308d3132fc872396d0";

	public SM4Util() {
	}

	/**
	 * SM4 默认ECB加密逻辑，对UTF8格式字符串进行加密，返回字符串
	 * 
	 * @param plainText 明文
	 * @param key       密钥，32位16进制数据
	 * 
	 * @return 16进制字符串密文
	 */
	public static String encrypt(String plainText, String key) {
		try {
			return new String(Hex.encode(encryptData_ECB(Hex.decode(key), plainText.getBytes("UTF-8"))), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}

	/**
	 * SM4默认ECB解密逻辑，对16进制字符串进行解密，返回UTF8格式字符串
	 * 
	 * @param key        密钥，32位16进制数据
	 * @param cipherText 16进制字符串密文
	 * @return 明文
	 */
	public static String decrypt(String cipherText, String key) {
		try {
			return new String(decryptData_ECB(Hex.decode(key), Hex.decode(cipherText.getBytes("UTF-8"))), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}

	/**
	 * ECB模式加密
	 * 
	 * @param keyBytes  密钥，字节数组，要求为 128 比特
	 * @param plainText 明文 ，字节数组
	 * @return
	 */
	public static byte[] encryptData_ECB(byte[] keyBytes, byte[] plainText) {
		if (keyBytes != null && keyBytes.length == 16) {
			if (plainText != null && plainText.length > 0) {
				try {
					SM4Context ctx = new SM4Context();
					ctx.isPadding = true;
					ctx.mode = 1;
					SM4 sm4 = new SM4();
					sm4.sm4_setkey_enc(ctx, keyBytes);
					byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainText);
					return encrypted;
				} catch (Exception e) {
					e.printStackTrace();
					return null;
				}
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	/**
	 * ECB模式解密
	 * 
	 * @param keyBytes   密钥，字节数组，要求为 128 比特
	 * @param cipherText 密文，字节数组
	 * @return
	 */
	public static byte[] decryptData_ECB(byte[] keyBytes, byte[] cipherText) {
		if (keyBytes != null && keyBytes.length == 16) {
			if (cipherText != null && cipherText.length > 0 && cipherText.length % 16 == 0) {
				try {
					SM4Context ctx = new SM4Context();
					ctx.isPadding = true;
					ctx.mode = 0;
					SM4 sm4 = new SM4();
					sm4.sm4_setkey_dec(ctx, keyBytes);
					byte[] decrypted = sm4.sm4_crypt_ecb(ctx, cipherText);
					int decryptedLen = decrypted.length;

					for (int i = decrypted.length - 1; i >= 0 && decrypted[i] == 0; --decryptedLen) {
						--i;
					}

					byte[] temp = new byte[decryptedLen];
					System.arraycopy(decrypted, 0, temp, 0, decryptedLen);
					return temp;
				} catch (Exception e) {
					e.printStackTrace();
					return null;
				}
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	/**
	 *  SM4 加密 CBC方式
	 * @param ivBytes
	 * @param keyBytes
	 * @param plainText
	 * @return
	 */
	public static byte[] encryptData_CBC(byte[] ivBytes, byte[] keyBytes, byte[] plainText) {
		if (keyBytes != null && keyBytes.length != 0 && keyBytes.length % 16 == 0) {
			if (plainText != null && plainText.length > 0) {
				if (ivBytes != null && ivBytes.length > 0) {
					try {
						SM4Context ctx = new SM4Context();
						ctx.isPadding = true;
						ctx.mode = 1;
						SM4 sm4 = new SM4();
						sm4.sm4_setkey_enc(ctx, keyBytes);
						byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText);
						return encrypted;
					} catch (Exception e) {
						e.printStackTrace();
						return null;
					}
				} else {
					return null;
				}
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	/**
	 * SM4解密 CBC模式
	 * 
	 * @param ivBytes
	 * @param keyBytes
	 * @param cipherText
	 * @return
	 */
	public static byte[] decryptData_CBC(byte[] ivBytes, byte[] keyBytes, byte[] cipherText) {
		if (keyBytes != null && keyBytes.length != 0 && keyBytes.length % 16 == 0) {
			if (cipherText != null && cipherText.length > 0) {
				if (ivBytes != null && ivBytes.length > 0) {
					try {
						SM4Context ctx = new SM4Context();
						ctx.isPadding = true;
						ctx.mode = 0;
						SM4 sm4 = new SM4();
						sm4.sm4_setkey_dec(ctx, keyBytes);
						byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, cipherText);
						return decrypted;
					} catch (Exception e) {
						e.printStackTrace();
						return null;
					}
				} else {
					return null;
				}
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	/**
	 * 获取随机密钥 getRandomKey
	 * 
	 * @author: WangBinBin
	 * @return 随机密钥
	 */
	public static String getRandomKey() {
		String keys = "0123456789abcdef";
		StringBuffer key = new StringBuffer();
		;
		int length = keys.length();
		for (int i = 0; i < 32; i++) {
			key.append(keys.charAt(new SecureRandom().nextInt(length)));
		}
		return key.toString();
	}

	/**
	 * 解密中招数据使用
	 * @param cipherText
	 * @return
	 */
	public static String decrypt(String cipherText) {
		try {
			return new String(decryptData_ECB(Hex.decode(sm4Key), Hex.decode(cipherText.getBytes("UTF-8"))), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
}
