package com.bohuikeji.frame.module.admin.sms;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;

public class CryptUtil {
    private static final String desAlgorithm = "DESede/CBC/NoPadding";
    private static final String desKeyAlgorithm = "DESede";
    private static final char[] DIGITS = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'a', 'b', 'c', 'd', 'e', 'f'};
    private static final byte[] defaultIV = new byte[]{'0', '0', '0', '0', '0', '0', '0', '0'};

    public CryptUtil() {
    }

    private static SecretKey KeyGenerator(String keyStr) throws Exception {
        byte[] input = md5Hex(keyStr).substring(0, 24).getBytes("GBK");
        SecretKey triDesKey = new SecretKeySpec(input, desKeyAlgorithm);
        return triDesKey;
    }

    public static String encryptBy3DesAndBase64(String content, String keyStr) throws Exception {
        return encryptBy3DesAndBase64(content, keyStr, "UTF-8");
    }

    public static String decryptBy3DesAndBase64(String content, String keyStr) throws Exception {
        return decryptBy3DesAndBase64(content, keyStr, "UTF-8");
    }

    public static String encryptBy3DesAndBase64(String content, String keyStr, String encoding) throws
            Exception {
        byte[] output = null;
        byte[] input = null;
        int residue = (content.getBytes(encoding).length) % 8;
        if (0 != residue) {
            int padLen = 8 - residue;
            StringBuffer strBuf = new StringBuffer(content);
            for (int i = 0; i < padLen; i++) {
                strBuf.append(' ');
            }
            input = (new String(strBuf)).getBytes(encoding);
        } else {
            input = content.getBytes(encoding);
        }
        output = encryptBy3Des(input, keyStr);
        return Base64Util.encode(output).replaceAll("[\\n\\r]", "");
    }

    public static String decryptBy3DesAndBase64(String content, String keyStr, String encoding) throws
            Exception {
        byte[] output = null;
        byte[] input = null;
        input = Base64Util.decode(content);
        output = decryptBy3Des(input, keyStr);
        String retStr = new String(output, encoding);
        return (retStr.trim());
    }

    public static byte[] encryptBy3Des(byte[] content, String keyStr) throws Exception {
        return cryptBy3Des(keyStr, 1, null, content);
    }

    public static byte[] decryptBy3Des(byte[] content, String keyStr) throws Exception {
        return cryptBy3Des(keyStr, 2, null, content);
    }

    public static byte[] cryptBy3Des(String keyStr, int cryptModel, byte[] iv, byte[] content) throws Exception {
        Cipher cipher = null;
        SecretKey key = KeyGenerator(keyStr);
        IvParameterSpec IVSpec = iv == null ? IvGenerator(defaultIV) : IvGenerator(iv);
        cipher = Cipher.getInstance(desAlgorithm);
        cipher.init(cryptModel, key, IVSpec);
        return cipher.doFinal(content);
    }

    public static String md5Hex(String content) throws Exception {
        MessageDigest md5 = null;
        md5 = MessageDigest.getInstance("MD5");
        md5.update(content.getBytes("GBK"));
        return new String(encodeHex(md5.digest()));
    }

    public static String md5Hex(String content, String charsetName) throws Exception {
        MessageDigest md5 = null;
        md5 = MessageDigest.getInstance("MD5");
        md5.update(content.getBytes(charsetName));
        return new String(encodeHex(md5.digest()));
    }

    public static char[] encodeHex(byte[] data) {
        int len = data.length;
        char[] out = new char[len << 1];
        int i = 0;
        int j = 0;
        for (; i < len; i++) {
            out[j++] = DIGITS[(0xf0 & data[i]) >>> 4];
            out[j++] = DIGITS[0xf & data[i]];
        }
        return out;
    }

    private static IvParameterSpec IvGenerator(byte[] b) {
        IvParameterSpec IV = new IvParameterSpec(b);
        return IV;
    }
}