package com.skr.mdm.util;



import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * @author kaku
 * @since 2017/6/19
 */
public class AESUtils {
    //秘钥算法
    private static final String KEY_ALGORITHM = "AES";
    //加密算法：algorithm/mode/padding 算法/工作模式/填充模式
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
    public static final String KEY = "6NXT2bLqsBA0hmlD";

  public static String encrypt(String plaintext) {
        // 初始化iv长度为16字节
        IvParameterSpec iv = new IvParameterSpec(KEY.substring(0, 16).getBytes());
        SecretKeySpec secretKeySpec = new SecretKeySpec(KEY.getBytes(), KEY_ALGORITHM);
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
            byte[] result = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
            return bytesToHexString(result);
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String plaintext) throws Exception {
    	byte[] result = hexStringToBytes(plaintext);
        IvParameterSpec iv = new IvParameterSpec(KEY.substring(0, 16).getBytes());
        SecretKeySpec secretKeySpec = new SecretKeySpec(KEY.getBytes(), KEY_ALGORITHM);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);
        return new String(cipher.doFinal(result), StandardCharsets.UTF_8);
    }


    /**
     * 文件进行加密并保存加密后的文件到指定目录
     *
     * @param fromFilePath 要加密的文件 如c:/test/待加密文件.txt
     * @param toFilePath   加密后存放的文件 如c:/加密后文件.txt
     * @param isMove       是否移动
     * @return 加密是否成功
     */
    public static boolean encryptFile(String fromFilePath, String toFilePath, boolean isMove) {
        File fromFile = new File(fromFilePath);
        if (!fromFile.exists()) {
            System.out.println("to be encrypt file no exist!");
            return false;
        }
        File toFile = getFile(toFilePath);
        // 初始化iv长度为16字节
        IvParameterSpec iv = new IvParameterSpec(KEY.substring(0, 16).getBytes());
        SecretKey secretKey = new SecretKeySpec(KEY.getBytes(), KEY_ALGORITHM);
        InputStream is = null;
        OutputStream out = null;
        CipherInputStream cis = null;
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            is = new FileInputStream(fromFile);
            out = new FileOutputStream(toFile);
            cis = new CipherInputStream(is, cipher);
            byte[] buffer = new byte[8192];
            int r;
            while ((r = cis.read(buffer)) > 0) {
                out.write(buffer, 0, r);
            }

        } catch (Exception e) {
        	e.printStackTrace();
            return false;
        } finally {
            try {
                if (cis != null) {
                    cis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (isMove && fromFile.exists() && fromFile.isFile()) {
                fromFile.delete();
            }
        }

        return true;
    }

   
    private static File getFile(String filePath) {
        File fromFile = new File(filePath);
        if (!fromFile.getParentFile().exists()) {
            boolean result = fromFile.getParentFile().mkdirs();
            System.out.println("mkdirs is success: " + result);
        }
        return fromFile;
    }

    /**
     * 文件进行解密并保存解密后的文件到指定目录
     *
     * @param fromFilePath 已加密的文件 如c:/加密后文件.txt
     * @param toFilePath   解密后存放的文件 如c:/ test/解密后文件.txt
     * @param isMove       是否移动
     */
    public static boolean decryptFile(String fromFilePath, String toFilePath, boolean isMove) {
        String fileName = fromFilePath.substring(fromFilePath.lastIndexOf("/") + 1);
        System.out.println(fileName + " decrypting...");
        File fromFile = new File(fromFilePath);
        if (!fromFile.exists()) {
            System.out.println("to be decrypt file no exist!");
            return false;
        }
        File toFile = getFile(toFilePath);

        IvParameterSpec iv = new IvParameterSpec(KEY.substring(0, 16).getBytes());
        SecretKey secretKey = new SecretKeySpec(KEY.getBytes(), KEY_ALGORITHM);

        InputStream is = null;
        OutputStream out = null;
        CipherOutputStream cos = null;
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            is = new FileInputStream(fromFile);
            out = new FileOutputStream(toFile);
            cos = new CipherOutputStream(out, cipher);
            byte[] buffer = new byte[1024 * 1024];
            int r;
            while ((r = is.read(buffer)) >= 0) {
                cos.write(buffer, 0, r);
            }

            System.out.println(fileName + " decrypt completed");
            if (isMove) {
                boolean result = new File(fromFilePath).delete();
                System.out.println("delete source file is success: " + result);
            }
        } catch (Exception e) {
            //KLog.e(e.toString());
            e.printStackTrace(); 
            return false;
        } finally {
            try {
                if (cos != null) {
                    cos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return true;
    }
    

         
   public static String bytesToHexString(byte[] src){  
       StringBuilder stringBuilder = new StringBuilder();
       if (src == null || src.length <= 0) {  
           return null;  
       }  
       for (int i = 0; i < src.length; i++) {  
           int v = src[i] & 0xFF;  
           String hv = Integer.toHexString(v);  
           if (hv.length() < 2) {  
               stringBuilder.append(0);  
           }  
           stringBuilder.append(hv);  
       }  
       return stringBuilder.toString();  
   } 
    /** 
     * Convert hex string to byte[] 
     * @param hexString the hex string 
     * @return byte[] 
     */  
    public static byte[] hexStringToBytes(String hexString) {  
        if (null == hexString || "".equals(hexString)) {
            return null;  
        }  
        hexString = hexString.toUpperCase();  
        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;  
    }  
    /** 
     * Convert char to byte 
     * @param c char 
     * @return byte 
     */  
     private static byte charToByte(char c) {  
        return (byte) "0123456789ABCDEF".indexOf(c);  
    }
    
//   /**
//     * hexString转byteArr
//     * <p>例如：</p>
//     * hexString2Bytes("00A8") returns { 0, (byte) 0xA8 }
//     *
//     * @param hexString 十六进制字符串
//     * @return 字节数组
//     */
//    public static byte[] hexString2Bytes(String hexString) {
//        if (isSpace(hexString)) return null;
//        int len = hexString.length();
//        if (len % 2 != 0) {
//            hexString = "0" + hexString;
//            len = len + 1;
//        }
//        char[] hexBytes = hexString.toUpperCase().toCharArray();
//        byte[] ret = new byte[len >> 1];
//        for (int i = 0; i < len; i += 2) {
//            ret[i >> 1] = (byte) (hex2Dec(hexBytes[i]) << 4 | hex2Dec(hexBytes[i + 1]));
//        }
//        return ret;
//    }
//
//
//    /**
//     * hexChar转int
//     *
//     * @param hexChar hex单个字节
//     * @return 0..15
//     */
//    private static int hex2Dec(char hexChar) {
//        if (hexChar >= '0' && hexChar <= '9') {
//            return hexChar - '0';
//        } else if (hexChar >= 'A' && hexChar <= 'F') {
//            return hexChar - 'A' + 10;
//        } else {
//            throw new IllegalArgumentException();
//        }
//    }
//
//
//    /**
//     * 判断字符串是否为null或全为空格
//     *
//     * @param s 待校验字符串
//     * @return {@code true}: null或全空格<br> {@code false}: 不为null且不全空格
//     */
//   public static boolean isSpace(String s) {
//        return (s == null || s.trim().length() == 0);
//    }
    
    
}
