package com.ruoyi;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class FinalShellDecodePass {
  public static void main(String[] args) throws Exception {
    System.out.print(decodePassword("PjQxIS8pKi8fi8SeNbQtP1s3JUn5XPNs"));
  }

  public static byte[] decryptDes(byte[] data, byte[] key) throws Exception {
    SecureRandom secureRandom = new SecureRandom();
    DESKeySpec desKeySpec = new DESKeySpec(key);
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
    SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
    Cipher cipher = Cipher.getInstance("DES");
    cipher.init(Cipher.DECRYPT_MODE, secretKey, secureRandom);
    return cipher.doFinal(data);
  }

  public static String decodePassword(String data) throws Exception {
    if (data == null) {
      return null;
    } else {
      byte[] decodedData = Base64.getDecoder().decode(data);
      byte[] head = new byte[8];
      System.arraycopy(decodedData, 0, head, 0, head.length);

      byte[] encryptedData = new byte[decodedData.length - head.length];
      System.arraycopy(decodedData, head.length, encryptedData, 0, encryptedData.length);



      byte[] decryptedData = decryptDes(encryptedData, generateRandomKey(head));
      return new String(decryptedData);
    }
  }

  static byte[] generateRandomKey(byte[] head) {
    long seed = 3680984568597093857L / (long) (new Random((long) head[5])).nextInt(127);
    Random random = new Random(seed);
    int t = head[0];

    for (int i = 0; i < t; ++i) {
      random.nextLong();
    }

    long n = random.nextLong();
    Random random2 = new Random(n);

    long[] keyData = {(long) head[4], random2.nextLong(), (long) head[7], (long) head[3], random2.nextLong(),
      (long) head[1], random.nextLong(), (long) head[2]};

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);

    for (long l : keyData) {
      try {
        dos.writeLong(l);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    try {
      dos.close();
    } catch (IOException e) {
      e.printStackTrace();
    }

    byte[] key = bos.toByteArray();
    return md5Hash(key);
  }

  public static byte[] md5Hash(byte[] data) {
    try {
      MessageDigest messageDigest = MessageDigest.getInstance("MD5");
      messageDigest.update(data, 0, data.length);
      byte[] result = messageDigest.digest();
      return result;
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
      return null;
    }
  }
}
