DES爆破程序 已知明文和密文 爆破密钥

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class RelynDictionary {
	// 密码可能会包含的字符集合
	private static char[] fullCharSource = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e',
			'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
			'V', 'W', 'X', 'Y', 'Z', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '{', '}', '|',
			':', '"', '<', '>', '?', ';', '\'', ',', '.', '/', '-', '=', '`' };
//    private static char[] fullCharSource = { '1','2','3','4','5','6','7','8','9','0',
//            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',  'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
//            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',  'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
//    private static char[] fullCharSource = { '1','2','3','4','5','6','7','8','9','0',
//            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',  'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
//    private static char[] fullCharSource = { '1','2','3','4','5','6','7','8','9','0'};
	// 密码集合长度
	private static int fullCharLength = fullCharSource.length;

	public static void main(String[] args) {
		// 明文
		String plainText = "123123";
		// 密文
		String secretCode = "1B0C23406F38F1AE";
		// 密钥位数
		int keyLength = 8;
		// DES密钥爆破
		RelynDictionary.generate(keyLength, plainText, secretCode);
	}

	public static void generate(int passLength, String plainText, String secretCode) {
		System.out.println("预设密码长度:" + passLength);
		System.out.println("组成密码的字符个数:" + fullCharLength);
		System.out.println("密码组合总数量(" + fullCharLength + "^" + passLength + "):" + Math.pow(fullCharLength, passLength));
		// x(1-x^n)/(1-x)
		BigDecimal allCounter = new BigDecimal(fullCharLength);
		BigDecimal a = allCounter.multiply(new BigDecimal(1).subtract(allCounter.pow(passLength)));
		BigDecimal b = new BigDecimal(1).subtract(allCounter);
		BigDecimal c = allCounter.multiply(new BigDecimal(1).subtract(allCounter.pow(passLength - 1)));
		BigDecimal d = new BigDecimal(1).subtract(allCounter);
		BigDecimal allPassword = a.divide(b, RoundingMode.HALF_UP).subtract(c.divide(d, RoundingMode.HALF_UP));
		BigDecimal startPos = c.divide(d, RoundingMode.HALF_UP);
		System.out.println("密码组开始位置 >> " + startPos);
		System.out.println("密码组合总数量 >> " + allPassword);
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		BigDecimal counter = startPos; // 起始位
		StringBuilder buider = new StringBuilder();
		while (buider.toString().length() <= passLength) {
			buider = new StringBuilder(passLength * 2);
			BigDecimal myCounter = counter;
			// 10进制转换成26进制
			while (myCounter.compareTo(new BigDecimal(fullCharLength)) == 1
					|| myCounter.compareTo(new BigDecimal(fullCharLength)) == 0) {
				// 获得低位
				buider.append(fullCharSource[myCounter.divideAndRemainder(new BigDecimal(fullCharLength))[1].intValue()]);
				myCounter = myCounter.divide(new BigDecimal(fullCharLength), RoundingMode.HALF_UP);
				// 处理进制体系中只有10没有01的问题,在穷举里面是可以存在01的
				myCounter = myCounter.subtract(new BigDecimal(1));
			}
			// 最高位
			buider.append(fullCharSource[myCounter.intValue()]);
			counter = counter.add(new BigDecimal(1));
			String password = buider.toString();
			String secret = "";
			try {
				secret = encodeECB(plainText, password);
				BigDecimal finish = counter.subtract(startPos).divide(allPassword, 10, RoundingMode.HALF_UP)
						.multiply(new BigDecimal(100));
				System.out.println(password + " >> " + secret + " >> " + counter + "......" + finish + "%");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (secretCode.equals(secret)) {
				System.out.println("找到密钥:" + password);
				try {
					File file = new File("pass.txt");
					if (!file.exists())
						file.createNewFile();
					FileWriter fw = new FileWriter(file, true);
					PrintWriter pw = new PrintWriter(fw);
					pw.println(password);
					pw.flush();
					fw.flush();
					pw.close();
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
				}
				return;
			}
		}
	}

	/**
	 * DES加密ECB
	 * 
	 * @param HexString          字符串(16位16进制字符串)
	 * @param keyStr             密钥
	 * @param keyENCODED         Keybyte转换编码
	 * @param HexStringENCODED   要加密值的转换byte编码
	 * @param CipherInstanceType 需要加密类型
	 * @return
	 * @throws Exception
	 */
	public static String encodeECB(String HexString, String keyStr) throws Exception {
		String jmstr = "";
		try {
			byte[] theKey = null;
			theKey = keyStr.getBytes("UTF-8");
			Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
			DESKeySpec desKeySpec = new DESKeySpec(theKey);
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
			SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
			cipher.init(Cipher.ENCRYPT_MODE, secretKey);
			byte[] theCph = cipher.doFinal(HexString.getBytes("UTF-8"));
			jmstr = toHexString(theCph).toUpperCase();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return jmstr;
	}

	public static String toHexString(byte b[]) {
		StringBuffer hexString = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			String plainText = Integer.toHexString(0xff & b[i]);
			if (plainText.length() < 2)
				plainText = "0" + plainText;
			hexString.append(plainText);
		}
		return hexString.toString();
	}
}