
package cd.casic.ci.process.util;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.security.crypto.bcrypt.BCrypt;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;

/**
 * @author HopeLi
 * @version v1.0
 * @ClassName PwdUtil
 * @Date: 2025/7/16 16:06
 * @Description: 使用 Bouncy Castle 实现的 SM4 加密工具类（输出格式改为 Hex）
 */
public class PwdUtil {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static final String key = "0123456789abcdeffedcba9876543210";
    public static final String IV = "fedcba98765432100123456789abcdef";

    /**
     * 加密方法（CBC 模式）
     *
     * @param str 待加密数据
     * @return 加密后的密文（Hex 编码）
     */
    public static String doEncrypt(String str) throws Exception {
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
        SecretKeySpec keySpec = new SecretKeySpec(hexStringToBytes(key), "SM4");
        IvParameterSpec ivSpec = new IvParameterSpec(hexStringToBytes(IV));
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
        return new String(Hex.encode(encrypted)); // 使用 Bouncy Castle 的 Hex 编码
    }

    /**
     * 解密方法（CBC 模式）
     *
     * @param hexStr 密文（Hex 编码）
     * @return 解密后的明文
     */
    public static String doDecrypt(String hexStr) throws Exception {
        Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
        SecretKeySpec keySpec = new SecretKeySpec(hexStringToBytes(key), "SM4");
        IvParameterSpec ivSpec = new IvParameterSpec(hexStringToBytes(IV));
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decrypted = cipher.doFinal(Hex.decode(hexStr)); // 使用 Bouncy Castle 的 Hex 解码
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    /**
     * 使用 BCrypt 对密码进行哈希加密
     *
     * @param password 明文密码
     * @return 加密后的 BCrypt Hash 字符串
     */
    public static String bcEncrypt(String password) {
        return BCrypt.hashpw(password, BCrypt.gensalt());
    }

    /**
     * 验证明文密码与 BCrypt 哈希是否匹配
     *
     * @param password 明文密码
     * @param hashed   BCrypt 哈希字符串
     * @return 是否匹配
     */
    public static boolean bcVerify(String password, String hashed) {
        return BCrypt.checkpw(password, hashed);
    }

    /**
     * 十六进制字符串转字节数组
     */
    private static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.isEmpty()) {
            return new byte[0];
        }
        int len = hexString.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }

    public static void main(String[] args) throws Exception {
        if (bcVerify("123456","$2a$04$vwq0mgqk/fvBSnouekE6R.kKKYoXBimQhUwefbrSBRC6voSjGxidK")){
            System.out.println(true);
        }else {
            System.out.println(false);
        }
    }
}