package com.palacesun.masking.tools;

import com.palacesun.engine.gateway.EncryptionGatewayManager;
import com.palacesun.masking.adapter.StringUtils;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.util.Properties;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.DecoderException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

public class DES3Util {
   private static final String ENCODING = "UTF-8";
   public static final String ALGORITHM_NAME = "DESede";
   public static final int DEFAULT_KEY_SIZE = 168;
   private static final String ALGORITHM_NAME_CBC_PADDING = "DESede/CBC/PKCS5Padding";
   private static final String ALGORITHM_NAME_ECB_PADDING = "DESede/ECB/PKCS5Padding";
   private static String ENCRYPT_LIKE_SPLIT = EncryptionGatewayManager.getParameterValue("encryption.like.split");
   private static Properties properties;
   private static final String ENCRYPT_LIKE_OPEN = "1";

   public static String generateKey() throws Exception {
      return byteToHexString(generateKey(168));
   }

   private static String byteToHexString(byte[] bytes) {
      StringBuffer sb = new StringBuffer(bytes.length);

      for(int i = 0; i < bytes.length; ++i) {
         String sTemp = Integer.toHexString(255 & bytes[i]);
         if (sTemp.length() < 2) {
            sb.append(0);
         }

         sb.append(sTemp.toUpperCase());
      }

      return sb.toString();
   }

   static byte[] generateKey(int keySize) throws Exception {
      KeyGenerator kg = KeyGenerator.getInstance("DESede");
      kg.init(keySize, new SecureRandom());
      return kg.generateKey().getEncoded();
   }

   private static Key getSecretKey(byte[] key) {
      try {
         DESedeKeySpec spec = new DESedeKeySpec(key);
         SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");
         return keyfactory.generateSecret(spec);
      } catch (InvalidKeyException var3) {
         throw new RuntimeException("DES获取密钥出现错误,非法key异常");
      } catch (NoSuchAlgorithmException var4) {
         throw new RuntimeException("DES获取密钥出现错误,算法异常");
      } catch (InvalidKeySpecException var5) {
         throw new RuntimeException("DES获取密钥出现错误,密钥规范异常");
      }
   }

   public static String encryptEcb(String hexKey, String paramStr, String isLike, String keepfirst, String encdigit, String twoindex, String... encryptMode) throws DecoderException, NoSuchPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, InvalidKeyException {
      try {
         String cipherText = "";
         byte[] key = hexKey.getBytes("UTF-8");
         Key secretKey = getSecretKey(key);
         String prefix = null;
         String enc = paramStr;
         String suffix = null;
         String encryptModeSwitch = "3DES";
         if (encryptMode.length > 0) {
            encryptModeSwitch = encryptMode[0];
         }

         if (!StringUtils.isBlank(keepfirst)) {
            if (!"0".equals(keepfirst) && !"1".equals(keepfirst)) {
               if (!"2".equals(keepfirst)) {
                  return paramStr;
               }

               int first = 0;
               if (StringUtils.isNotBlank(encdigit)) {
                  first = Integer.parseInt(encdigit);
               }

               int last = 0;
               if (StringUtils.isNotBlank(twoindex)) {
                  last = Integer.parseInt(twoindex);
               }

               if (first + last >= paramStr.length() || first >= paramStr.length() || last >= paramStr.length()) {
                  return paramStr;
               }

               prefix = paramStr.substring(0, first);
               enc = paramStr.substring(first, paramStr.length() - last);
               suffix = paramStr.substring(paramStr.length() - last);
            } else if (StringUtils.isNotBlank(encdigit)) {
               if (Integer.parseInt(encdigit) >= paramStr.length()) {
                  return paramStr;
               }

               if (Integer.parseInt(encdigit) != 0) {
                  if ("0".equals(keepfirst)) {
                     prefix = paramStr.substring(0, Integer.parseInt(encdigit));
                     enc = paramStr.substring(Integer.parseInt(encdigit));
                  } else if ("1".equals(keepfirst)) {
                     enc = paramStr.substring(0, paramStr.length() - Integer.parseInt(encdigit));
                     suffix = paramStr.substring(paramStr.length() - Integer.parseInt(encdigit));
                  }
               }
            }
         }

         if ("1".equals(isLike)) {
            StringBuilder sb = new StringBuilder();

            for(int i = 0; i < enc.length(); ++i) {
               char c = enc.charAt(i);
               byte[] srcData = (c + "").getBytes("UTF-8");
               byte[] cipherArray = new byte[0];
               if ("3DES".equals(encryptModeSwitch)) {
                  cipherArray = encrypt_Ecb_Padding(secretKey, srcData);
               }

               cipherText = ByteUtils.toHexString(cipherArray);
               sb.append(cipherText).append(ENCRYPT_LIKE_SPLIT);
            }

            cipherText = sb.deleteCharAt(sb.length() - 1).toString();
         } else {
            byte[] srcData = enc.getBytes("UTF-8");
            byte[] cipherArray = new byte[0];
            if ("3DES".equals(encryptModeSwitch)) {
               cipherArray = encrypt_Ecb_Padding(secretKey, srcData);
            }

            cipherText = ByteUtils.toHexString(cipherArray);
         }

         if ("0".equals(keepfirst) && null != prefix) {
            cipherText = prefix + cipherText;
         } else if ("1".equals(keepfirst) && null != suffix) {
            cipherText = cipherText + suffix;
         } else if ("2".equals(keepfirst)) {
            if (null != prefix) {
               cipherText = prefix + cipherText;
            }

            if (null != suffix) {
               cipherText = cipherText + suffix;
            }
         }

         return cipherText;
      } catch (Exception var19) {
         return paramStr;
      }
   }

   public static byte[] encrypt_Ecb_Padding(Key key, byte[] data) throws Exception {
      Cipher cipher = generateEcbCipher("DESede/ECB/PKCS5Padding", 1, key);
      return cipher.doFinal(data);
   }

   private static Cipher generateEcbCipher(String algorithmName, int mode, Key key) throws Exception {
      Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
      cipher.init(mode, key);
      return cipher;
   }

   public static String decryptEcb(String hexKey, String paramStr, String isLike, String keepfirst, String encdigit, String twoindex, String... encryptMode) throws Exception {
      String decryptStr = "";

      try {
         byte[] srcData = new byte[0];
         byte[] key = hexKey.getBytes("UTF-8");
         Key secretKey = getSecretKey(key);
         String prefix = null;
         String enc = paramStr;
         String suffix = null;
         String encryptModeSwitch = "3DES";
         if (encryptMode.length > 0) {
            encryptModeSwitch = encryptMode[0];
         }

         if (!StringUtils.isBlank(encdigit)) {
            if (!"0".equals(keepfirst) && !"1".equals(keepfirst)) {
               if (!"2".equals(keepfirst)) {
                  return paramStr;
               }

               int first = 0;
               if (StringUtils.isNotBlank(encdigit)) {
                  first = Integer.parseInt(encdigit);
               }

               int last = 0;
               if (StringUtils.isNotBlank(twoindex)) {
                  last = Integer.parseInt(twoindex);
               }

               if (first + last >= paramStr.length() || first >= paramStr.length() || last >= paramStr.length()) {
                  return paramStr;
               }

               prefix = paramStr.substring(0, first);
               enc = paramStr.substring(first, paramStr.length() - last);
               suffix = paramStr.substring(paramStr.length() - last);
            } else if (StringUtils.isNotBlank(encdigit)) {
               if (Integer.parseInt(encdigit) >= paramStr.length()) {
                  return paramStr;
               }

               if (Integer.parseInt(encdigit) != 0) {
                  if ("0".equals(keepfirst)) {
                     prefix = paramStr.substring(0, Integer.parseInt(encdigit));
                     enc = paramStr.substring(Integer.parseInt(encdigit));
                  } else if ("1".equals(keepfirst)) {
                     suffix = paramStr.substring(paramStr.length() - Integer.parseInt(encdigit));
                     enc = paramStr.substring(0, paramStr.length() - Integer.parseInt(encdigit));
                  }
               }
            }
         }

         if ("1".equals(isLike)) {
            StringBuilder sb = new StringBuilder();
            String[] split = enc.split(ENCRYPT_LIKE_SPLIT);

            for(String s : split) {
               byte[] cipherData = ByteUtils.fromHexString(s);

               try {
                  if ("3DES".equals(encryptModeSwitch)) {
                     srcData = decrypt_Ecb_Padding(secretKey, cipherData);
                  }

                  decryptStr = new String(srcData, "UTF-8");
                  sb.append(decryptStr);
               } catch (Exception e) {
                  e.printStackTrace();
               }
            }

            decryptStr = sb.toString();
         } else {
            byte[] cipherData = ByteUtils.fromHexString(enc);
            if ("3DES".equals(encryptModeSwitch)) {
               srcData = decrypt_Ecb_Padding(secretKey, cipherData);
            }

            decryptStr = new String(srcData, "UTF-8");
         }

         if ("0".equals(keepfirst) && null != prefix) {
            decryptStr = prefix + decryptStr;
         } else if ("1".equals(keepfirst) && null != suffix) {
            decryptStr = decryptStr + suffix;
         } else if ("2".equals(keepfirst)) {
            if (null != prefix) {
               decryptStr = prefix + decryptStr;
            }

            if (null != suffix) {
               decryptStr = decryptStr + suffix;
            }
         }

         return decryptStr;
      } catch (Exception e) {
         throw e;
      }
   }

   public static byte[] decrypt_Ecb_Padding(Key key, byte[] cipherText) throws Exception {
      Cipher cipher = generateEcbCipher("DESede/ECB/PKCS5Padding", 2, key);
      return cipher.doFinal(cipherText);
   }

   public static void main(String[] args) throws Exception {
      String desKey = "8F264CBC7304CE29197CB67A07D5F2B5AB01F86E5BD334FE";
      String encode = "cb370aa02b7a2c422#ff7a2793ece1fe40#ff7a2793ece1fe40#ff7a2793ece1fe40#ff7a2793ece1fe40";
      String decodeStr = decryptEcb(desKey, encode, "1", "2", "1", "0", "3DES");
      System.out.println("3DES解密后转字符串数据：" + decodeStr);
   }

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