欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DES单倍和双倍长**算法使用8字节key

程序员文章站 2022-03-12 19:36:38
...
public class EcbDesUtil {
	static Logger log = Logger.getLogger(EcbDesUtil.class);

	public static void main(String[] args) {
/*		String key1 = "0000000000000000";
		String data = "3207FEBFC350BA8ACFC96F2867D32E1CC0122D1274BC996BAAC9485EC41917E861C
    61CA8601630A38586B7733740FB1F7824CAF97396791ED7A1EF6C48782E3B12DFFFECDF71C3181
FA17D37AA6AAA4B41BB1CC9C1A923FC602AADCDF0F5E0A5AF77C5A847476673E66F724C59A539AF3D88074D
219B3612F09D009713BD3EBA8CD45FEBBFA225FB534D9EC067199399B772732E03AD83908C671D8BB751175D
2122AD9CC5B32140AC5423D651CBD00D5315A4ACA49898A2B6DE2BD86BC4A869B54CA454C8AC886213E0
A56358A1B6A2B54CA454C8AC886213E0A56358A1B6A28351520A185DD48F46D898D9CA3004686BAF
3FAAB7CBE70ED6B973442A8752DD195E0FF16777FDBA7CAD750758F6655722462CB89C6E5080E2CBD
FC09BB5C52E924322438D247C2B2FCDED9FA0CD923A82115C5B517625A12E3744EE5
8EEE67CD29A22F232F31F04F0D9A1F809CD496869F52D981014B5FB1F1A1BEA413DF1
EC20571F101401A9D60EC21803EA074696F09F60A8DDA86F44B8A8044C57081F4034FE195E43B3B6EC7C8A11C95049
29230CB486C972B8FE5B3D6F5866B53B7C0945B9DEF3B52253F0AF1FCC4B6FEFB2A3";
		String eninfo = encodeDEA(key1, data);
		System.out.println("key=" + key1);
		System.out.println("data=" + data);
		System.out.println("des加密后:" + eninfo);

		String decodeStr = decodeDEA(key1, eninfo);
		System.out.println("des解密后:" + decodeStr);*/

		String srcStr="<execStatus><statusCode>000000</statusCode><statusDescription>更新订单成功</statusDescription></execStatus>";
		//将字节数组转换为十六进制字符串
		String data=HexUtil.encodeHexStr(srcStr.getBytes());
		System.out.println("data=" + data);
		
		String key2 = "EC35E9100872BD3FCC9663D86397C2A5";
		String eninfo = encode3DEA(key2, data);
		System.out.println("3des加密后:" + eninfo);

		
		
		String data2 = decode3DEA(key2, eninfo);
		//将十六进制字符数组转换为字节数组,再转换成字符串
		String decodeStr = new String(HexUtil.decodeHex(data2));
		System.out.println("data2=" + data2);
		
		System.out.println("3des解密后:" + decodeStr);

	}

	/**
	 * 补位填充最后数据块
	 * @param hexData
	 * @return
	 */
	private static String fillLastBlock(String hexData) {
		// 先检查最后一个数据块长度是否为8字节,进行补齐处理
		int n = hexData.length() % 16;
		if (n != 0) { // 最后的数据块为1-7字节长即为2-14位

			// 先其后加入‘80’刚好达到8字节,则继续,否则继续在后面补0直到8字节
			hexData += "80";
			n = hexData.length() % 16;
			if (n != 0) {
				for (int i = 0; i < (16 - n) / 2; i++) {
					hexData += "00";
				}
			}
		}
		return hexData;
	}

	/**
	 * 单倍长**DEA加密算法
	 * 
	 * @param hexKey
	 *            16进制**(单倍长**8字节)
	 * @param hexData
	 *            16进制的明文数据
	 */
	public static String encodeDEA(String hexKey, String hexData) {
		//log.info("单倍长des**算法,**="+hexKey+",数据="+hexData);
		// log.debug("key size="+hexKey.length());
		// log.debug("data size="+hexData.length());
		if (hexKey.length() != 16) {
			throw new RuntimeException("单倍长**DEA加密算法**必须为16位十六进制数,此**长度为:"+hexKey.length());
		}
		byte[] key = HexUtil.decodeHex(hexKey.toCharArray());
		byte[] buffer;
		StringBuilder sb = new StringBuilder();
		try {

			/**
			 * 数据加密的方法: 1,用LD(1字节)表示明文数据的长度,在明文数据前加上LD产生新的数据块。
			 * 2,将此数据块分成8字节为单位的数据块,表示为block1、block2、block3、block4等,最后的数据块有可能是1-
			 * 8字节。
			 * 3,如果最后(或唯一)的数据块长度是8字节的话,转到第4步;如果不足8字节,则在其后加入十六进制数‘80’,如果达到8字节长度,则
			 * 转到第4步;否则在其后加入十六进制数‘00’直到长度达到8字节。 4,按照图所述的算法使用指定**对每一个数据块进行加密。
			 * 5,计算结束后,所有加密后的数据块按照顺序连接在一起。
			 */
			// 严格来说应该在数据块前面先加上1字节表示数据的长度
			// hexData=NumberUtil.format2Hex(hexData.length(),1)+hexData;
			
			hexData=fillLastBlock(hexData);
			//log.info("des数据补齐后="+hexData);

			for (int i = 0; i < hexData.length(); i = i + 16) {
				buffer = HexUtil.decodeHex(hexData.substring(i, i + 16).toCharArray());
				buffer = DESUtil.encrypt(buffer, key);
				sb.append(HexUtil.encodeHexStr(buffer));
			}

		} catch (Exception e) {
			log.error("单倍长**DEA加密算法出错了,key=" + hexKey + ",data=" + hexData, e);
			return null;
		}
		//log.info("单倍长des算法加密结果="+sb.toString());
		return sb.toString();
	}

	/**
	 * 单倍长**DEA解密算法
	 * 
	 * @param hexKey
	 *            十六进制**(16字节)
	 * @param hexData
	 *            十六进制密文(长度为8字节倍数)
	 */
	public static String decodeDEA(String hexKey, String hexData) {
		// log.debug("key size="+hexKey.length());
		// log.debug("data size="+hexData.length());
		if (hexKey.length() != 16) {
			throw new RuntimeException("单倍长**DEA解密算法**必须为16位十六进制数,此**长度为:"+hexKey.length());
		}

		byte[] key = HexUtil.decodeHex(hexKey.toCharArray());
		byte[] buffer;
		StringBuilder sb = new StringBuilder();
		try {

			for (int i = 0; i < hexData.length(); i = i + 16) {
				buffer = HexUtil.decodeHex(hexData.substring(i, i + 16).toCharArray());
				buffer = DESUtil.decrypt(buffer, key);
				sb.append(HexUtil.encodeHexStr(buffer));
			}

		} catch (Exception e) {
			log.error("单倍长**DEA解密算法出错了,key=" + hexKey + ",data=" + hexData, e);
			return null;
		}
		return sb.toString();
	}
	

	/**
	 * 双倍长**(16字节长)3DEA加密算法
	 * 
	 * @param hexKey
	 *            16进制**(16字节32位长)
	 * @param hexData
	 *            16进制的明文数据
	 */
	public static String encode3DEA(String hexKey, String hexData) {
		 
		if (hexKey.length() != 32) {
			throw new RuntimeException("双倍长**(16字节长)3DEA加密算法**必须为32位十六进制数,当前**长度为:"+hexKey.length());
		}
		byte[] lkey = HexUtil.decodeHex(hexKey.substring(0, 16).toCharArray());
		byte[] rkey = HexUtil.decodeHex(hexKey.substring(16, 32).toCharArray());
		byte[] buffer;
		StringBuilder sb = new StringBuilder();
		try {

			/**
			 * 数据加密的方法: 1,用LD(1字节)表示明文数据的长度,在明文数据前加上LD产生新的数据块。
			 * 2,将此数据块分成8字节为单位的数据块,表示为block1、block2、block3、block4等,最后的数据块有可能是1-
			 * 8字节。
			 * 3,如果最后(或唯一)的数据块长度是8字节的话,转到第4步;如果不足8字节,则在其后加入十六进制数‘80’,如果达到8字节长度,则
			 * 转到第4步;否则在其后加入十六进制数‘00’直到长度达到8字节。 4,按照图所述的算法使用指定**对每一个数据块进行加密。
			 * 5,计算结束后,所有加密后的数据块按照顺序连接在一起。
			 */
			// 严格来说应该在数据块前面先加上1字节表示数据的长度
			// hexData=NumberUtil.format2Hex(hexData.length(),1)+hexData;

			hexData=fillLastBlock(hexData);

			for (int i = 0; i < hexData.length(); i = i + 16) {
				buffer = HexUtil.decodeHex(hexData.substring(i, i + 16).toCharArray());
				buffer = DESUtil.encrypt(buffer, lkey);
				buffer = DESUtil.decrypt(buffer, rkey);
				buffer = DESUtil.encrypt(buffer, lkey);
				sb.append(HexUtil.encodeHexStr(buffer));
			}

		} catch (Exception e) {
			log.error("双倍长**(16字节长)3DEA加密算法出错了,key=" + hexKey + ",data=" + hexData, e);
			return null;
		}
		String enc=sb.toString();
		//log.info("3des key="+hexKey+",hexData="+hexData+",encValue="+enc);
		return enc;
	}

	/**
	 * 双倍长**(16字节长)3DEA解密算法
	 * 
	 * @param hexKey
	 *            十六进制**(32位16字节)
	 * @param hexData
	 *            十六进制密文(长度为8字节倍数)
	 */
	public static String decode3DEA(String hexKey, String hexData) {
		// log.debug("key size="+hexKey.length());
		// log.debug("data size="+hexData.length());
		if (hexKey.length() != 32) {
			throw new RuntimeException("双倍长**(16字节长)3DEA解密算法**必须为32位十六进制数");
		}

		byte[] lkey = HexUtil.decodeHex(hexKey.substring(0, 16).toCharArray());
		byte[] rkey = HexUtil.decodeHex(hexKey.substring(16, 32).toCharArray());
		byte[] buffer;
		StringBuilder sb = new StringBuilder();
		try {

			for (int i = 0; i < hexData.length(); i = i + 16) {
				buffer = HexUtil.decodeHex(hexData.substring(i, i + 16).toCharArray());
				buffer = DESUtil.decrypt(buffer, lkey);
				buffer = DESUtil.encrypt(buffer, rkey);
				buffer = DESUtil.decrypt(buffer, lkey);
				sb.append(HexUtil.encodeHexStr(buffer));
			}

		} catch (Exception e) {
			log.error("双倍长**(16字节长)3DEA解密算法出错了,key=" + hexKey + ",data=" + hexData, e);
			return null;
		}
		return sb.toString();
	}
}

相关标签: des