SHA1计算过程

参考资料,按字节的角度(加密的数据是字节数组,不是位数组),理解大致过程是:

1. 原字节数组补字节,使得字节数为64的倍数,且补的部分第一个字节是0x80,最后的8个字节存储原字节数组的总位数。

2. 补后的字节数组,每64字节为一块,循环计算。

3. 每64字节的一块再分16份,每份4字节,这16份会扩展计算,和自身的16分,组成80份,再循环计算。

4. 这80份的每份,按公式计算得到结果。

5. 之前各处计算的结果不断累计,即为结果。


import org.apache.commons.codec.digest.DigestUtils;

public class MySHA1Test {

	public static void main(String[] args) {
		String str = "hello";
//		System.out.println(DigestUtils.md5Hex("hello"));
		System.out.println(DigestUtils.shaHex(str));
		byte[] data = str.getBytes();
//		data = new byte[448];
		System.out.println(hexToString(sha(data)));
	}

	public static String sha(String data) {
		return hexToString(sha(data.getBytes()));
	}

	public static byte[] sha(byte[] bytes_data) {
		byte[] bytes_all = appendBytes(bytes_data);
		return computeBytes(bytes_all);
	}

	public static byte[] appendBytes(byte[] bytes_src) {
		// 原始数据补字节,补后整体是64字节(512位)的整数倍。
		// 补的部分,第一bit是1,后面至少有8个字节(64位)用来存放原始数据长度,这样至少补9字节
		int length_src = bytes_src.length;
		int length_append = 64 - length_src % 64;
		if (length_append < 9) {
			length_append = 64 + length_append;
		}

		// 补的数据
		byte[] bytes_append = new byte[length_append];
		// 第一位是1,其他位是0
		bytes_append[0] = (byte) 0x80;
		// 后面8字节(64位)存储的是按bit算的长度
		long length_src1 = length_src * 8;
		bytes_append[length_append - 8] = (byte)(length_src1 >>> 56);
		bytes_append[length_append - 7] = (byte)(length_src1 >>> 48);
		bytes_append[length_append - 6] = (byte)(length_src1 >>> 40);
		bytes_append[length_append - 5] = (byte)(length_src1 >>> 32);
		bytes_append[length_append - 4] = (byte)(length_src1 >>> 24);
		bytes_append[length_append - 3] = (byte)(length_src1 >>> 16);
		bytes_append[length_append - 2] = (byte)(length_src1 >>>  8);
		bytes_append[length_append - 1] = (byte)(length_src1 >>>  0);

		// 组装完整数据
		byte[] bytes_all = new byte[length_src + length_append];
		System.arraycopy(bytes_src, 0, bytes_all, 0, length_src);
		System.arraycopy(bytes_append, 0, bytes_all, length_src, length_append);

//		System.out.println("原始:" + hexToString(bytes_data));
//		System.out.println("扩充:" + hexToString(bytes_append));
//		System.out.println("结果:" + hexToString(bytes_all));

		return bytes_all;
	}

	public static byte[] computeBytes(byte[] bytes_all) {

		int k0 = 0x5A827999; // (0 <= t <= 19)
		int k1 = 0x6ED9EBA1; // (20 <= t <= 39)
		int k2 = 0x8F1BBCDC; // (40 <= t <= 59)
		int k3 = 0xCA62C1D6; // (60 <= t <= 79).

		int H0 = 0x67452301;
		int H1 = 0xEFCDAB89;
		int H2 = 0x98BADCFE;
		int H3 = 0x10325476;
		int H4 = 0xC3D2E1F0;

		int A = 0;
		int B = 0;
		int C = 0;
		int D = 0;
		int E = 0;
		int A1 = 0;

		// 整体数据,按每块64字节512位切分,循环处理每个分块
		int block_size = 64;
		int block_count = bytes_all.length / block_size;
		byte[] block_data = new byte[block_size];
		int[] W = new int[80];
		for (int block_index = 0;  block_index < block_count; block_index++) {
			// 取得分块数据
			System.arraycopy(bytes_all, block_index * block_size, block_data, 0, block_size);

			// 分块数据转为80个子分块
			for (int t = 0; t < 80; t++) {
				if (t < 16) {
					// 前16个子分块,切分16分直接转换得到
					int tmp = t * 4;
					W[t] = (
							((block_data[0 + tmp] << 24) & 0xff000000)
							+ ((block_data[1 + tmp] << 16) & 0xff0000)
							+ ((block_data[2 + tmp] << 8) & 0xff00)
							+ ((block_data[3 + tmp] << 0) & 0xff)
							);
				} else {
					// 后面的子分块,计算得到
					// W[t] = S1(W[t-3] XOR W[t-8] XOR W[t-14] XOR W[t-16]).
					W[t] = leftShiftLoop((W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]), 1);
				}
			}

			// 80个子分块计算ABCDE,并累加
			A = H0;
			B = H1;
			C = H2;
			D = H3;
			E = H4;
			for (int t = 0; t < 80; t++) {
				// 计算ABCDE:A, B, C, D, E ← [(A<<<5)+ ft(B,C,D)+E+Wt+Kt], A, (B<<<30), C, D
				if (t < 20) {
					A1 = leftShiftLoop(A, 5)
							+ ((B & C) | ((~B) & D)) // (B AND C) or ((NOT B) AND D)
							+ E + W[t] + k0;
				} else if (t < 40) {
					A1 = leftShiftLoop(A, 5)
							+ (B ^ C ^ D) // B XOR C XOR D
							+ E + W[t] + k1;
				} else if (t < 60) {
					A1 = leftShiftLoop(A, 5)
							+ ((B & C) | (B & D) | (C & D)) // (B AND C) or (B AND D) or (C AND D)
							+ E + W[t] + k2;
				} else {
					A1 = leftShiftLoop(A, 5)
							+ (B ^ C ^ D) // B XOR C XOR D
							+ E + W[t] + k3;
				}
				E = D;
				D = C;
				C = leftShiftLoop(B, 30);
				B = A;
				A = A1;
			}
			H0 = H0 + A;
			H1 = H1 + B;
			H2 = H2 + C;
			H3 = H3 + D;
			H4 = H4 + E;
		}

		// ABCDE转为结果
		byte[] bytes_ret = new byte[20];
		int index_ret = 0;
		A1 = H0;
		bytes_ret[index_ret++] = (byte) ((A1 >>> 24) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>> 16) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  8) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  0) & 0xFF);
		A1 = H1;
		bytes_ret[index_ret++] = (byte) ((A1 >>> 24) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>> 16) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  8) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  0) & 0xFF);
		A1 = H2;
		bytes_ret[index_ret++] = (byte) ((A1 >>> 24) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>> 16) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  8) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  0) & 0xFF);
		A1 = H3;
		bytes_ret[index_ret++] = (byte) ((A1 >>> 24) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>> 16) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  8) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  0) & 0xFF);
		A1 = H4;
		bytes_ret[index_ret++] = (byte) ((A1 >>> 24) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>> 16) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  8) & 0xFF);
		bytes_ret[index_ret++] = (byte) ((A1 >>>  0) & 0xFF);
		//
		return bytes_ret;
	}

	public static int leftShiftLoop(int d, int n) {
		return (d << n) | (d >>> (32 - n));
	}

	//
	private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7',
			'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
	public static String hexToString(byte[] data) {
		int l = data.length;

		char[] out = new char[l << 1];

		int i = 0;
		for (int j = 0; i < l; ++i) {
			out[(j++)] = digits[((0xF0 & data[i]) >>> 4)];
			out[(j++)] = digits[(0xF & data[i])];
		}
		return new String(out);
	}

}

猜你喜欢

转载自blog.csdn.net/superzlc/article/details/82532548