以下是计算SHA1的64字节块的计算函数。测试方式非常简单,
准备一个 int src[16] 的数组,赋值测试数据块。测试数据
为"abc " 字串,位长度为 0x18。
如果以字节方式来看待64字节缓冲区的话,下面是Big Endian 字序机上的映像:
61 62 63 80 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 18
如果以字节方式来看待64字节缓冲区的话,下面是Little Endian 字序机上的映像:
80 63 62 61 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 18 00 00 00
可以看出来重新组织过的数据在两种机器内存中是不一样的,不过不必担心,语言层
上根本不必为此担心。
无论是 Big endian / little endian 机器,在C 语言中,以以下方式赋给16双字
缓冲区数组,那么,结果就是一样的:
src[0] = 0x61626380 <--80是追加的标志符号
src[1] to src[13] = 0
src[14] = 0 <--64位的位长度,这里存放高位的32位为0
src[15] = 0x00000018
再准备一个 int reg[6] 的数组接收计算结果。Reg[6]的初始化值为下:
reg[0] = 0x67452301;
reg[1] = 0xefcdab89;
reg[2] = 0x98badcfe;
reg[3] = 0x10325476;
reg[4] = 0xC3D2E1F0;
之后调用 Sha1Calc_CalcBlock( src, reg )
最后将 reg 数组的每个双字打印出来即可,如 reg[0] 包括 4 个字节,将这4个字节按
big endian 字序打印出来。
"abc"的 Sha1 的标准结果是:a9 99 3e 36 47 6 81 6a ba 3e 25 71 78 50 c2 6c 9c d0 d8 9d
至于超过64字节的数据源块怎么办,请参考“Md5 与 Sha 如何将大于64字节的数据分成多块”
/**
dp -- DataPtr rp -- RegisterArrayPointer
dp 是一个指向64 字节的数据块指针,也就是16 双字数组的指针。
rp 是一个指向 int Reg[6] 数组的指针
RET_OK 是一个宏 #define REG_OK 0
*/
int Sha1Calc_calcBlock( int* dp, int* rp ){
int a,b,c,d,e;
int f,k;
int x;
a = rp[0]; b = rp[1]; c = rp[2]; d = rp[3]; e = rp[4];
/** main loop */
for( x = 0; x < 16; x ++ ){
k = (( a << 5 ) | (( a >> 27 ) & 0x1f )) + ( d ^ ( b & ( c ^ d ) )) + e + 0x5a827999 + dp[ x ];
e = d; d = c; c = (( b << 30 ) | (( b >> 2 ) & 0x3fffffff )); b = a; a = k;
}
for( x = 16; x < 20; x ++ ){
k = dp[( x + 13 ) & 0xf ] ^ dp[( x + 8 ) & 0xf ] ^ dp[( x + 2 ) & 0xf ] ^ dp[ x & 0xf ];
dp[ x & 0xf ] = k = (( k << 1 ) | (( k >> 31 ) & 1 ));
k = (( a << 5 ) | (( a >> 27 ) & 0x1f )) + ( d ^ ( b & ( c ^ d ) )) + e + 0x5a827999 + k;
e = d; d = c; c = (( b << 30 ) | (( b >> 2 ) & 0x3fffffff )); b = a; a = k;
}
for( x = 20; x < 40; x ++ ){
k = dp[( x + 13 ) & 0xf ] ^ dp[( x + 8 ) & 0xf ] ^ dp[( x + 2 ) & 0xf ] ^ dp[ x & 0xf ];
dp[ x & 0xf ] = k = (( k << 1 ) | (( k >> 31 ) & 1 ));
k = (( a << 5 ) | (( a >> 27 ) & 0x1f )) + ( b ^ c ^ d ) + e + 0x6ed9eba1 + k;
e = d; d = c; c = ( b << 30 ) | (( b >> 2 ) & 0x3fffffff ); b = a; a = k;
}
for( x = 40; x < 60; x ++ ){
k = dp[( x + 13 ) & 0xf ] ^ dp[( x + 8 ) & 0xf ] ^ dp[( x + 2 ) & 0xf ] ^ dp[ x & 0xf ];
dp[ x & 0xf ] = k = (( k << 1 ) | (( k >> 31 ) & 1 ));
k = (( a << 5 ) | (( a >> 27 ) & 0x1f )) + (( b & c ) | ( d & ( b | c ))) + e + 0x8f1bbcdc + k;
e = d; d = c; c = ( b << 30 ) | (( b >> 2 ) & 0x3fffffff ); b = a; a = k;
}
for( x = 60; x < 80; x ++ ){
k = dp[( x + 13 ) & 0xf ] ^ dp[( x + 8 ) & 0xf ] ^ dp[( x + 2 ) & 0xf ] ^ dp[ x & 0xf ];
dp[ x & 0xf ] = k = (( k << 1 ) | (( k >> 31 ) & 1 ));
k = (( a << 5 ) | (( a >> 27 ) & 0x1f )) + ( b ^ c ^ d ) + e + 0xca62c1d6 + k;
e = d; d = c; c = ( b << 30 ) | (( b >> 2 ) & 0x3fffffff ); b = a; a = k;
}
rp[0] += a; rp[1] += b; rp[2] += c; rp[3] += d; rp[4] += e;
return RET_OK;
}