Sha1 的块计算函数

 以下是计算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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值