java版 MAC ANSI x 9.9 算法

网上通过查找DES算法,无意间发现了这个算法,因为对算法不是很了解,暂时未对注释中的乱码进行修改

package fuck.this.world;

import java.io.UnsupportedEncodingException;

/**
 * 
 * @author someone
 * 
 * desType 1:单倍长 2:3DES(双倍长)3:3DES(三倍长)
 * 
 */

public class MAC_ANSI_x9_9 {

	/** ***************************压缩替换S-Box�?************************************************* */

	private static final int[][] s1 = {
			{ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },

			{ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },

			{ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },

			{ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } };

	private static final int[][] s2 = {
			{ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },

			{ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },

			{ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },

			{ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } };

	private static final int[][] s3 = {
			{ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },

			{ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },

			{ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },

			{ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } };

	private static final int[][] s4 = {
			{ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },

			{ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },// erorr

			{ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },

			{ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } };

	private static final int[][] s5 = {
			{ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },

			{ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 },

			{ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },

			{ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } };

	private static final int[][] s6 = {
			{ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },

			{ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },

			{ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },

			{ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } };

	private static final int[][] s7 = {
			{ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },

			{ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },

			{ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },

			{ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } };

	private static final int[][] s8 = {
			{ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },

			{ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },

			{ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },

			{ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } };

	private static final int[] ip = { 58, 50, 42, 34, 26, 18, 10, 2,

	60, 52, 44, 36, 28, 20, 12, 4,

	62, 54, 46, 38, 30, 22, 14, 6,

	64, 56, 48, 40, 32, 24, 16, 8,

	57, 49, 41, 33, 25, 17, 9, 1,

	59, 51, 43, 35, 27, 19, 11, 3,

	61, 53, 45, 37, 29, 21, 13, 5,

	63, 55, 47, 39, 31, 23, 15, 7 };

	private static final int[] _ip = { 40, 8, 48, 16, 56, 24, 64, 32,

	39, 7, 47, 15, 55, 23, 63, 31,

	38, 6, 46, 14, 54, 22, 62, 30,

	37, 5, 45, 13, 53, 21, 61, 29,

	36, 4, 44, 12, 52, 20, 60, 28,

	35, 3, 43, 11, 51, 19, 59, 27,

	34, 2, 42, 10, 50, 18, 58, 26,

	33, 1, 41, 9, 49, 17, 57, 25 };

	// 每次密钥循环左移位数

	private static final int[] LS = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,
			2, 1 };

	private static int[][] subKey = new int[16][48];

	private static int HEX = 0;

	private static int ASC = 1;

	/**
	 * 
	 * 将十六进制A--F转换成对应数�?
	 * 
	 * @param ch
	 * 
	 * @return
	 * 
	 * @throws Exception
	 * 
	 */

	public static int getIntByChar(char ch) throws Exception {

		char t = Character.toUpperCase(ch);

		int i = 0;

		switch (t) {

		case '0':

		case '1':

		case '2':

		case '3':

		case '4':

		case '5':

		case '6':

		case '7':

		case '8':

		case '9':

			i = Integer.parseInt(Character.toString(t));

			break;

		case 'A':

			i = 10;

			break;

		case 'B':

			i = 11;

			break;

		case 'C':

			i = 12;

			break;

		case 'D':

			i = 13;

			break;

		case 'E':

			i = 14;

			break;

		case 'F':

			i = 15;

			break;

		default:

			throw new Exception("getIntByChar was wrong");

		}

		return i;

	}

	/**
	 * 
	 * 将字符串转换成二进制数组
	 * 
	 * @param source :
	 *            16字节
	 * 
	 * @return
	 * 
	 */

	public static int[] string2Binary(String source) {

		int len = source.length();

		int[] dest = new int[len * 4];

		char[] arr = source.toCharArray();

		for (int i = 0; i < len; i++) {

			int t = 0;

			try {

				t = getIntByChar(arr[i]);

				// System.out.println(arr[i]);

			} catch (Exception e) {

				e.printStackTrace();

			}

			String[] str = Integer.toBinaryString(t).split("");

			int k = i * 4 + 3;

			for (int j = str.length - 1; j > 0; j--) {

				dest[k] = Integer.parseInt(str[j]);

				k--;

			}

		}

		return dest;

	}

	/**
	 * 
	 * 返回x的y次方
	 * 
	 * @param x
	 * 
	 * @param y
	 * 
	 * @return
	 * 
	 */

	public static int getXY(int x, int y) {

		int temp = x;

		if (y == 0)
			x = 1;

		for (int i = 2; i <= y; i++) {

			x *= temp;

		}

		return x;

	}

	/**
	 * 
	 * s�?位长度的二进制字符串
	 * 
	 * @param s
	 * 
	 * @return
	 * 
	 */

	public static String binary2Hex(String s) {

		int len = s.length();

		int result = 0;

		int k = 0;

		if (len > 4)
			return null;

		for (int i = len; i > 0; i--) {

			result += Integer.parseInt(s.substring(i - 1, i)) * getXY(2, k);

			k++;

		}

		switch (result) {

		case 0:

		case 1:

		case 2:

		case 3:

		case 4:

		case 5:

		case 6:

		case 7:

		case 8:

		case 9:

			return "" + result;

		case 10:

			return "A";

		case 11:

			return "B";

		case 12:

			return "C";

		case 13:

			return "D";

		case 14:

			return "E";

		case 15:

			return "F";

		default:

			return null;

		}

	}

	/**
	 * 
	 * 将int转换成Hex
	 * 
	 * @param i
	 * 
	 * @return
	 * 
	 * @throws Exception
	 * 
	 */

	public static String int2Hex(int i) {

		switch (i) {

		case 0:

		case 1:

		case 2:

		case 3:

		case 4:

		case 5:

		case 6:

		case 7:

		case 8:

		case 9:

			return "" + i;

		case 10:

			return "A";

		case 11:

			return "B";

		case 12:

			return "C";

		case 13:

			return "D";

		case 14:

			return "E";

		case 15:

			return "F";

		default:

			return null;

		}

	}

	/**
	 * 
	 * 将二进制字符串转换成十六进制字符�?
	 * 
	 * @param s
	 * 
	 * @return
	 * 
	 */

	public static String binary2ASC(String s) {

		String str = "";

		int ii = 0;

		int len = s.length();

		// 不够4bit左补0

		if (len % 4 != 0) {

			while (ii < 4 - len % 4) {

				s = "0" + s;

			}

		}

		for (int i = 0; i < len / 4; i++) {

			str += binary2Hex(s.substring(i * 4, i * 4 + 4));

		}

		return str;

	}

	/**
	 * 
	 * IP初始置换
	 * 
	 * @param source
	 * 
	 * @return
	 * 
	 */

	public static int[] changeIP(int[] source) {

		int[] dest = new int[64];

		for (int i = 0; i < 64; i++) {

			dest[i] = source[ip[i] - 1];

		}

		return dest;

	}

	/**
	 * 
	 * IP-1逆置�?
	 * 
	 * @param source
	 * 
	 * @return
	 * 
	 */

	public static int[] changeInverseIP(int[] source) {

		int[] dest = new int[64];

		for (int i = 0; i < 64; i++) {

			dest[i] = source[_ip[i] - 1];

		}

		return dest;

	}

	/**
	 * 
	 * �?2bit扩展�?8bit
	 * 
	 * @param source
	 * 
	 * @return
	 * 
	 */

	public static int[] expend(int[] source) {

		int[] ret = new int[48];

		int[] temp = { 32, 1, 2, 3, 4, 5,

		4, 5, 6, 7, 8, 9,

		8, 9, 10, 11, 12, 13,

		12, 13, 14, 15, 16, 17,

		16, 17, 18, 19, 20, 21,

		20, 21, 22, 23, 24, 25,

		24, 25, 26, 27, 28, 29,

		28, 29, 30, 31, 32, 1 };

		for (int i = 0; i < 48; i++) {

			ret[i] = source[temp[i] - 1];

		}

		return ret;

	}

	/**
	 * 
	 * �?8bit压缩�?2bit
	 * 
	 * @param source(48bit)
	 * 
	 * @return R(32bit)
	 * 
	 * B=E(R)⊕K,将48 位的B 分成8 个分组,B=B1B2B3B4B5B6B7B8
	 * 
	 */

	public static int[] press(int[] source) {

		int[] ret = new int[32];

		int[][] temp = new int[8][6];

		int[][][] s = { s1, s2, s3, s4, s5, s6, s7, s8 };

		StringBuffer str = new StringBuffer();

		for (int i = 0; i < 8; i++) {

			for (int j = 0; j < 6; j++) {

				temp[i][j] = source[i * 6 + j];

			}

		}

		for (int i = 0; i < 8; i++) {

			// (16)

			int x = temp[i][0] * 2 + temp[i][5];

			// (2345)

			int y = temp[i][1] * 8 + temp[i][2] * 4 + temp[i][3] * 2
					+ temp[i][4];

			int val = s[i][x][y];

			String ch = int2Hex(val);

			// System.out.println("x=" + x + ",y=" + y + "-->" + ch);

			// String ch = Integer.toBinaryString(val);

			str.append(ch);

		}

		// System.out.println(str.toString());

		ret = string2Binary(str.toString());

		// printArr(ret);

		// 置换P

		ret = dataP(ret);

		return ret;

	}

	/**
	 * 
	 * 置换P(32bit)
	 * 
	 * @param source
	 * 
	 * @return
	 * 
	 */

	public static int[] dataP(int[] source) {

		int[] dest = new int[32];

		int[] temp = { 16, 7, 20, 21,

		29, 12, 28, 17,

		1, 15, 23, 26,

		5, 18, 31, 10,

		2, 8, 24, 14,

		32, 27, 3, 9,

		19, 13, 30, 6,

		22, 11, 4, 25 };

		int len = source.length;

		for (int i = 0; i < len; i++) {

			dest[i] = source[temp[i] - 1];

		}

		return dest;

	}

	/**
	 * 
	 * @param R(�?2bit)
	 * 
	 * @param K(48bit的轮子密�?
	 * 
	 * @return 32bit
	 * 
	 */

	public static int[] f(int[] R, int[] K) {

		int[] dest = new int[32];

		int[] temp = new int[48];

		// 先将输入32bit扩展�?8bit

		int[] expendR = expend(R);// 48bit

		// 与轮子密钥进行异或运�?

		temp = diffOr(expendR, K);

		// 压缩�?2bit

		dest = press(temp);

		// System.out.println("need press data----->");

		// printArr(temp);

		return dest;

	}

	/**
	 * 
	 * 两个等长的数组做异或
	 * 
	 * @param source1
	 * 
	 * @param source2
	 * 
	 * @return
	 * 
	 */

	public static int[] diffOr(int[] source1, int[] source2) {

		int len = source1.length;

		int[] dest = new int[len];

		for (int i = 0; i < len; i++) {

			dest[i] = source1[i] ^ source2[i];

		}

		return dest;

	}

	/**
	 * 
	 * DES加密--->对称密钥
	 * 
	 * D = Ln(32bit)+Rn(32bit)
	 * 
	 * 经过16轮置�?
	 * 
	 * @param D(16byte)明文
	 * 
	 * @param K(16byte)轮子密钥
	 * 
	 * @return (16byte)密文
	 * 
	 */

	public static String encryption(String D, String K) {

		String str = "";

		int[] temp = new int[64];

		int[] data = string2Binary(D);

		// printArr(data);

		// 第一步初始置�?

		data = changeIP(data);

		// printArr(data);

		int[][] left = new int[17][32];

		int[][] right = new int[17][32];

		for (int j = 0; j < 32; j++) {

			left[0][j] = data[j];

			right[0][j] = data[j + 32];

		}

		// printArr(left[0]);

		// printArr(right[0]);

		setKey(K);// sub key ok

		for (int i = 1; i < 17; i++) {

			// 获取(48bit)的轮子密�?

			int[] key = subKey[i - 1];

			// L1 = R0

			left[i] = right[i - 1];

			// R1 = L0 ^ f(R0,K1)

			int[] fTemp = f(right[i - 1], key);// 32bit

			right[i] = diffOr(left[i - 1], fTemp);

		}

		// �?��组合的时候,左右调换**************************************************

		for (int i = 0; i < 32; i++) {

			temp[i] = right[16][i];

			temp[32 + i] = left[16][i];

		}

		temp = changeInverseIP(temp);

		str = binary2ASC(intArr2Str(temp));

		return str;

	}

	/**
	 * 
	 * DES解密--->对称密钥
	 * 
	 * 解密算法与加密算法基本相同,不同之处仅在于轮子密钥的使用顺序逆序,即解密的第1
	 * 
	 * 轮子密钥为加密的�?6 轮子密钥,解密的�? 轮子密钥为加密的�?5 轮子密钥,�?…,
	 * 
	 * 解密的第16 轮子密钥为加密的�? 轮子密钥�?
	 * 
	 * @param source密文
	 * 
	 * @param key密钥
	 * 
	 * @return
	 * 
	 */

	public static String discryption(String source, String key) {

		String str = "";

		int[] data = string2Binary(source);// 64bit

		// 第一步初始置�?

		data = changeIP(data);

		int[] left = new int[32];

		int[] right = new int[32];

		int[] tmp = new int[32];

		for (int j = 0; j < 32; j++) {

			left[j] = data[j];

			right[j] = data[j + 32];

		}

		setKey(key);// sub key ok

		for (int i = 16; i > 0; i--) {

			// 获取(48bit)的轮子密�?

			/** *******不同之处********* */

			int[] sKey = subKey[i - 1];

			tmp = left;

			// R1 = L0

			left = right;

			// L1 = R0 ^ f(L0,K1)

			int[] fTemp = f(right, sKey);// 32bit

			right = diffOr(tmp, fTemp);

		}

		// �?��组合的时候,左右调换**************************************************

		for (int i = 0; i < 32; i++) {

			data[i] = right[i];

			data[32 + i] = left[i];

		}

		data = changeInverseIP(data);

		for (int i = 0; i < data.length; i++) {

			str += data[i];

		}

		str = binary2ASC(str);

		return str;

	}

	/**
	 * 
	 * 单�?长密钥DES(16byte)
	 * 
	 * @param source
	 * 
	 * @param key
	 * 
	 * @param type
	 *            0:encrypt 1:discrypt
	 * 
	 * @return
	 * 
	 */

	public static String DES_1(String source, String key, int type) {

		if (source.length() != 16 || key.length() != 16)
			return null;

		if (type == 0) {

			return encryption(source, key);

		}

		if (type == 1) {

			return discryption(source, key);

		}

		return null;

	}

	/**
	 * 
	 * 
	 * 
	 * @param source
	 * 
	 * @param key
	 * 
	 * @param type
	 *            0:encrypt 1:discrypt
	 * 
	 * @return
	 * 
	 */

	public static String DES_2(String source, String key, int type) {

		return null;

	}

	/**
	 * 
	 * 三重DES算法(双�?长密�?32byte))
	 * 
	 * 密钥K1和K2
	 * 
	 * 1、先用K1加密明文
	 * 
	 * 2、接�?��K2对上�?��的结果进行解�?
	 * 
	 * 3、然后用K1对上�?��的结果进行加�?
	 * 
	 * @param source
	 * 
	 * @param key
	 * 
	 * @param type
	 *            0:encrypt 1:discrypt
	 * 
	 * @return
	 * 
	 */

	public static String DES_3(String source, String key, int type) {

		if (key.length() != 32 || source.length() != 16)
			return null;

		String temp = null;

		String K1 = key.substring(0, key.length() / 2);

		String K2 = key.substring(key.length() / 2);

		System.out.println("K1--->" + K1);

		System.out.println("K2--->" + K2);

		if (type == 0) {

			temp = encryption(source, K1);

			System.out.println("step1--->" + temp);

			temp = discryption(temp, K2);

			System.out.println("step2--->" + temp);

			return encryption(temp, K1);

		}

		if (type == 1) {

			temp = discryption(source, K1);

			temp = encryption(temp, K2);

			return discryption(temp, K1);

		}

		return null;

	}

	/** **********************************48bit的轮子密钥的生成********************************************************* */

	/**
	 * 
	 * �?4bit的密钥转换成56bit
	 * 
	 * @param source
	 * 
	 * @return
	 * 
	 */

	public static int[] keyPC_1(int[] source) {

		int[] dest = new int[56];

		int[] temp = { 57, 49, 41, 33, 25, 17, 9,

		1, 58, 50, 42, 34, 26, 18,

		10, 2, 59, 51, 43, 35, 27,

		19, 11, 3, 60, 52, 44, 36,

		63, 55, 47, 39, 31, 23, 15,

		7, 62, 54, 46, 38, 30, 22,

		14, 6, 61, 53, 45, 37, 29,

		21, 13, 5, 28, 20, 12, 4 };

		for (int i = 0; i < 56; i++) {

			dest[i] = source[temp[i] - 1];

		}

		return dest;

	}

	/**
	 * 
	 * 将密钥循环左移i�?
	 * 
	 * @param source
	 *            二进制密钥数�?
	 * 
	 * @param i
	 *            循环左移位数
	 * 
	 * @return
	 * 
	 */

	public static int[] keyLeftMove(int[] source, int i) {

		int temp = 0;

		int len = source.length;

		int ls = LS[i];

		// System.out.println("len" + len + ",LS[" + i + "]=" + ls);

		for (int k = 0; k < ls; k++) {

			temp = source[0];

			for (int j = 0; j < len - 1; j++) {

				source[j] = source[j + 1];

			}

			source[len - 1] = temp;

		}

		return source;

	}

	/**
	 * 
	 * �?6bit的密钥转换成48bit
	 * 
	 * @param source
	 * 
	 * @return
	 * 
	 */

	public static int[] keyPC_2(int[] source) {

		int[] dest = new int[48];

		int[] temp = { 14, 17, 11, 24, 1, 5,

		3, 28, 15, 6, 21, 10,

		23, 19, 12, 4, 26, 8,

		16, 7, 27, 20, 13, 2,

		41, 52, 31, 37, 47, 55,

		30, 40, 51, 45, 33, 48,

		44, 49, 39, 56, 34, 53,

		46, 42, 50, 36, 29, 32 };

		for (int i = 0; i < 48; i++) {

			dest[i] = source[temp[i] - 1];

		}

		return dest;

	}

	/**
	 * 
	 * 获取轮子密钥(48bit)
	 * 
	 * @param source
	 * 
	 * @return
	 * 
	 */

	public static void setKey(String source) {

		if (subKey.length > 0)
			subKey = new int[16][48];

		// 装换�?4bit

		int[] temp = string2Binary(source);

		// �?6bit均分成两部分

		int[] left = new int[28];

		int[] right = new int[28];

		// 经过PC-1�?4bit转换�?6bit

		int[] temp1 = new int[56];

		temp1 = keyPC_1(temp);

		// printArr(temp1);

		// 将经过转换的temp1均分成两部分

		for (int i = 0; i < 28; i++) {

			left[i] = temp1[i];

			right[i] = temp1[i + 28];

		}

		// 经过16次循环左移,然后PC-2置换

		for (int i = 0; i < 16; i++) {

			left = keyLeftMove(left, LS[i]);

			right = keyLeftMove(right, LS[i]);

			for (int j = 0; j < 28; j++) {

				temp1[j] = left[j];

				temp1[j + 28] = right[j];

			}

			// printArr(temp1);

			subKey[i] = keyPC_2(temp1);

		}

	}

	public static void printArr(int[] source) {

		int len = source.length;

		for (int i = 0; i < len; i++) {

			System.out.print(source[i]);

		}

		System.out.println();

	}

	/**
	 * 
	 * 将ASC字符串转�?6进制字符�?
	 * 
	 * @param asc
	 * 
	 * @return
	 * 
	 */

	public static String ASC_2_HEX(String asc) {

		StringBuffer hex = new StringBuffer();

		try {

			byte[] bs = asc.toUpperCase().getBytes("UTF-8");

			for (byte b : bs) {

				hex.append(Integer.toHexString(new Byte(b).intValue()));

			}

		} catch (UnsupportedEncodingException e) {

			e.printStackTrace();

		}

		return hex.toString();

	}

	/**
	 * 
	 * �?6进制的字符串转换成ASC的字符串
	 * 
	 * �?6进制的字符串压缩成BCD�?30313233343536373839414243444546)-->(0123456789ABCDEF)
	 * 
	 * @param hex
	 * 
	 * @return
	 * 
	 */

	public static String HEX_2_ASC(String hex) {

		String asc = null;

		int len = hex.length();

		byte[] bs = new byte[len / 2];

		for (int i = 0; i < len / 2; i++) {

			bs[i] = Byte.parseByte(hex.substring(i * 2, i * 2 + 2), 16);

		}

		try {

			asc = new String(bs, "UTF-8");

		} catch (UnsupportedEncodingException e) {

			e.printStackTrace();

		}

		return asc;

	}

	/**
	 * 
	 * 计算MAC(hex)
	 * 
	 * ANSI-X9.9-MAC(16的整数�?不补)
	 * 
	 * PBOC-DES-MAC(16的整数�?�?000000000000000)
	 * 
	 * 使用单�?长密钥DES算法
	 * 
	 * @param key密钥(16byte)
	 * 
	 * @param vector初始向量0000000000000000
	 * 
	 * @param data数据
	 * 
	 * @return mac
	 * 
	 */

	public static String MAC(String key, String vector, String data, int type, int desType) {

		if (type == ASC) {

			data = ASC_2_HEX(data);

		}

		int len = data.length();

		int arrLen = len / 16 + 1;

		String[] D = new String[arrLen];

		if (vector == null)
			vector = "0000000000000000";

		if (len % 16 == 0) {

			data += "8000000000000000";

		} else {

			data += "80";

			for (int i = 0; i < 15 - len % 16; i++) {

				data += "00";

			}

		}

		for (int i = 0; i < arrLen; i++) {

			D[i] = data.substring(i * 16, i * 16 + 16);

			System.out.println("D[" + i + "]=" + D[i]);

		}

		// D0 Xor Vector

		String I = xOr(D[0], vector);

		String O = null;

		for (int i = 1; i < arrLen; i++) {

			// System.out.println(i + "**************");

			// System.out.println("I=" + I);
			switch (desType) {
			case 1:
				O = DES_1(I, key, 0);
				break;
			case 2:
				O = DES_2(I, key, 0);
				break;
			case 3:
				O = DES_3(I, key, 0);
				break;
			default:
				break;
			}

			// System.out.println("O=" + O);

			I = xOr(D[i], O);

			// System.out.println("I=" + I);

		}

		switch (desType) {
		case 1:
			O = DES_1(I, key, 0);
			break;
		case 2:
			O = DES_2(I, key, 0);
			break;
		case 3:
			O = DES_3(I, key, 0);
			break;
		default:
			break;
		}

		return I;

	}

	/**
	 * 
	 * 将s1和s2做异或,然后返回
	 * 
	 * @param s1
	 * 
	 * @param s2
	 * 
	 * @return
	 * 
	 */

	public static String xOr(String s1, String s2) {

		int[] iArr = diffOr(string2Binary(s1), string2Binary(s2));

		return binary2ASC(intArr2Str(iArr));

	}

	/**
	 * 
	 * 将int类型数组拼接成字符串
	 * 
	 * @param arr
	 * 
	 * @return
	 * 
	 */

	public static String intArr2Str(int[] arr) {

		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < arr.length; i++) {

			sb.append(arr[i]);

		}

		return sb.toString();

	}

	/**
	 * 
	 * 将data分散
	 * 
	 * @param data
	 * 
	 * @param key
	 * 
	 * @param type
	 * 
	 * @return
	 * 
	 */

	public static String divData(String data, String key, int type) {

		String left = null;

		String right = null;

		if (type == HEX) {

			left = key.substring(0, 16);

			right = key.substring(16, 32);

		}

		if (type == ASC) {

			left = ASC_2_HEX(key.substring(0, 8));

			right = ASC_2_HEX(key.substring(8, 16));

		}

		// 加密

		data = DES_1(data, left, 0);

		// 解密

		data = DES_1(data, right, 1);

		// 加密

		data = DES_1(data, left, 0);

		return data;

	}

	/**
	 * 
	 * 取反(10001)--->(01110)
	 * 
	 * @param source
	 * 
	 * @return
	 * 
	 */

	public static String reverse(String source) {

		int[] data = string2Binary(source);

		int j = 0;

		for (int i : data) {

			data[j++] = 1 - i;

		}

		return binary2ASC(intArr2Str(data));

	}

	/**
	 * 
	 * 主密钥需要经过两次分散获得IC卡中的子密钥
	 * 
	 * @param issuerFlag发卡方标识符
	 * 
	 * @param appNo应用序列号即卡号
	 * 
	 * @param mpk主密钥
	 * 
	 * @return
	 * 
	 */

	public static String getDPK(String issuerFlag, String appNo, String mpk) {

		// 第一次分散

		StringBuffer issuerMPK = new StringBuffer();

		// 获取Issuer MPK左半边

		issuerMPK.append(divData(issuerFlag, mpk, 0));

		// 获取Issuer MPK右半边

		issuerMPK.append(divData(reverse(issuerFlag), mpk, 0));

		// 第二次分散

		StringBuffer dpk = new StringBuffer();

		// 获取DPK左半边

		dpk.append(divData(appNo, issuerMPK.toString(), 0));

		// 获取DPK右半边

		dpk.append(divData(reverse(appNo), issuerMPK.toString(), 0));

		return dpk.toString();

	}

	public String getMac(String key, String data, int desType) {
		String macCode = "";
		macCode = MAC(key, "0000000000000000", data, HEX, desType);
		return macCode == null ? "" : macCode;
	}

	public static void main(String[] args) throws Exception {

		System.out.println("/*************Tripe-MAC*************/");
		String masterKey = "1111111111111111";
		String data = "1212122343243543554645756666666666633333333333333333332111aa";

		String macCode = MAC(masterKey, "0000000000000000", data, HEX, 1);
		System.out.println(macCode);

	}

}

点赞