几个标准Hash算法的说明及实现(一)
时间:2007-12-27 来源:061107
标 题: 【原创】几个标准Hash算法的说明及实现(一)
作 者: lotusroots
时 间: 2005-11-01,13:45
链 接: http://bbs.pediy.com/showthread.php?t=18092
作者:冲出宇宙
说明:作者水平所限,恐怕错误比较多,请兄弟们多多包涵。并提出指正。
昨天刚在这里发了一个帖子,今天就发现被转移到其他地方去了。思考之后,决定把自己写的几个标准的Hash函数代码和说明发布到这里来。这下不会把我的东西转移了吧?
首先看看美国的FIPS下的Hash算法标准:
1,ripemd
2,sha
3,tiger
4,whirlpool
md5以前好像也是这个里面的标准。不知道是不是真的是。反正现在已经不是了。md5的代码网络上铺天盖地都是的,我们将不讨论和md5有关的话题。需要代码的请看:
http://lotusroots.bokee.com ,那里也包含了hash算法的更详细的讨论。
1, ripemd
顾名思义ripemd就是成熟md算法,是Hans Dobbertin等3人在md4,md5的基础上,于1996年提出来的。算法共有4个标准128、160、256和320,其对应输出长度分别为16字节、20字节、32字节和40字节。不过,让人难以致信的是ripemd的设计者们根本就没有真正设计256和320位这2种标准,他们只是在128位和160位的基础上,修改了初始参数和s-box来达到输出为256和320位的目的。所以,256位的强度和128相当,而320位的强度和160位相当。ripemd建立在md的基础之上,所以,其添加数据的方式和md5完全一样。
这里只列出ripemd128的代码。需要其他代码的兄弟可以下载附件。
其参考代码如下:
ripemd.h文件:
#ifndef Goodzzp_RipeMd_05_10_20_12
#define Goodzzp_RipeMd_05_10_20_12
//ripemd128,160,256,320
//program be Goodzzp
//05,10,20
//128 and 160 are referred:
//http://homes.esat.md_kuleuven.be/~bosselae/ripemd160.html
//256 and 320 are not guarranteed to be safe than 128 or 160
//referred: Crypto++5.21
#include "define.h"
//128-320需要的5论变换
#define md_F(x, y, z) (x ^ y ^ z)
#define md_G(x, y, z) (z ^ (x & (y^z)))
#define md_H(x, y, z) (z ^ (x | ~y))
#define md_I(x, y, z) (y ^ (z & (x^y)))
#define md_J(x, y, z) (x ^ (y | ~z))
//常量
#define md_k0 0
#define md_k1 0x5a827999UL
#define md_k2 0x6ed9eba1UL
#define md_k3 0x8f1bbcdcUL
#define md_k4 0xa953fd4eUL
#define md_k5 0x50a28be6UL
#define md_k6 0x5c4dd124UL
#define md_k7 0x6d703ef3UL
#define md_k8 0x7a6d76e9UL
#define md_k9 0
// for 128 and 256
#define md1_Subround(f, a, b, c, d, x, s, md_k) \
a += f(b, c, d) + x + md_k;\
a = rotlFixed((UI32)a, s);
//...begin ripemd128
//RipeMd128散列类
class RipeMD128
{
public:
//输出结果的长度(字节)
static UI32 OutDataLength()
{
return 128/8;
}
//RipeMD128变换函数
//out:输出,长度为16,要求事先已经分配了内存
//in:输入
//length:输入值的长度
void Hash(UI8 *out,const UI8 *in,UI32 length)
{
UI32 i = length>>6,j=(length&0x3f),md_k;
//对数据64 64个字节的计算
for(md_k=0;md_k>=8;
buffer[57]=(UI8)(len&0xff);
len>>=8;
buffer[58]=(UI8)(len&0xff);
len>>=8;
buffer[59]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
else if(dataBlockLen>=56)
{
//添加1和0
buffer[dataBlockLen]=0x80;
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
//添加长度
memset(buffer,0,64);
buffer[56]=(UI8)(len&0xff);
len>>=8;
buffer[57]=(UI8)(len&0xff);
len>>=8;
buffer[58]=(UI8)(len&0xff);
len>>=8;
buffer[59]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
}
else if(dataBlockLen == 64)
{
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
}
//把64字节的原始数据data进行初步转化到m_data中去
void FirstTransform(UI32 *data)
{
memcpy(X,data,64);
}
//核心变换
void CoreTransform()
{
UI32 a1, b1, c1, d1, a2, b2, c2, d2;
a1 = a2 = MDbuf[0];
b1 = b2 = MDbuf[1];
c1 = c2 = MDbuf[2];
d1 = d2 = MDbuf[3];
md1_Subround(md_F, a1, b1, c1, d1, X[ 0], 11, md_k0);
md1_Subround(md_F, d1, a1, b1, c1, X[ 1], 14, md_k0);
md1_Subround(md_F, c1, d1, a1, b1, X[ 2], 15, md_k0);
md1_Subround(md_F, b1, c1, d1, a1, X[ 3], 12, md_k0);
md1_Subround(md_F, a1, b1, c1, d1, X[ 4], 5, md_k0);
md1_Subround(md_F, d1, a1, b1, c1, X[ 5], 8, md_k0);
md1_Subround(md_F, c1, d1, a1, b1, X[ 6], 7, md_k0);
md1_Subround(md_F, b1, c1, d1, a1, X[ 7], 9, md_k0);
md1_Subround(md_F, a1, b1, c1, d1, X[ 8], 11, md_k0);
md1_Subround(md_F, d1, a1, b1, c1, X[ 9], 13, md_k0);
md1_Subround(md_F, c1, d1, a1, b1, X[10], 14, md_k0);
md1_Subround(md_F, b1, c1, d1, a1, X[11], 15, md_k0);
md1_Subround(md_F, a1, b1, c1, d1, X[12], 6, md_k0);
md1_Subround(md_F, d1, a1, b1, c1, X[13], 7, md_k0);
md1_Subround(md_F, c1, d1, a1, b1, X[14], 9, md_k0);
md1_Subround(md_F, b1, c1, d1, a1, X[15], 8, md_k0);
md1_Subround(md_G, a1, b1, c1, d1, X[ 7], 7, md_k1);
md1_Subround(md_G, d1, a1, b1, c1, X[ 4], 6, md_k1);
md1_Subround(md_G, c1, d1, a1, b1, X[13], 8, md_k1);
md1_Subround(md_G, b1, c1, d1, a1, X[ 1], 13, md_k1);
md1_Subround(md_G, a1, b1, c1, d1, X[10], 11, md_k1);
md1_Subround(md_G, d1, a1, b1, c1, X[ 6], 9, md_k1);
md1_Subround(md_G, c1, d1, a1, b1, X[15], 7, md_k1);
md1_Subround(md_G, b1, c1, d1, a1, X[ 3], 15, md_k1);
md1_Subround(md_G, a1, b1, c1, d1, X[12], 7, md_k1);
md1_Subround(md_G, d1, a1, b1, c1, X[ 0], 12, md_k1);
md1_Subround(md_G, c1, d1, a1, b1, X[ 9], 15, md_k1);
md1_Subround(md_G, b1, c1, d1, a1, X[ 5], 9, md_k1);
md1_Subround(md_G, a1, b1, c1, d1, X[ 2], 11, md_k1);
md1_Subround(md_G, d1, a1, b1, c1, X[14], 7, md_k1);
md1_Subround(md_G, c1, d1, a1, b1, X[11], 13, md_k1);
md1_Subround(md_G, b1, c1, d1, a1, X[ 8], 12, md_k1);
md1_Subround(md_H, a1, b1, c1, d1, X[ 3], 11, md_k2);
md1_Subround(md_H, d1, a1, b1, c1, X[10], 13, md_k2);
md1_Subround(md_H, c1, d1, a1, b1, X[14], 6, md_k2);
md1_Subround(md_H, b1, c1, d1, a1, X[ 4], 7, md_k2);
md1_Subround(md_H, a1, b1, c1, d1, X[ 9], 14, md_k2);
md1_Subround(md_H, d1, a1, b1, c1, X[15], 9, md_k2);
md1_Subround(md_H, c1, d1, a1, b1, X[ 8], 13, md_k2);
md1_Subround(md_H, b1, c1, d1, a1, X[ 1], 15, md_k2);
md1_Subround(md_H, a1, b1, c1, d1, X[ 2], 14, md_k2);
md1_Subround(md_H, d1, a1, b1, c1, X[ 7], 8, md_k2);
md1_Subround(md_H, c1, d1, a1, b1, X[ 0], 13, md_k2);
md1_Subround(md_H, b1, c1, d1, a1, X[ 6], 6, md_k2);
md1_Subround(md_H, a1, b1, c1, d1, X[13], 5, md_k2);
md1_Subround(md_H, d1, a1, b1, c1, X[11], 12, md_k2);
md1_Subround(md_H, c1, d1, a1, b1, X[ 5], 7, md_k2);
md1_Subround(md_H, b1, c1, d1, a1, X[12], 5, md_k2);
md1_Subround(md_I, a1, b1, c1, d1, X[ 1], 11, md_k3);
md1_Subround(md_I, d1, a1, b1, c1, X[ 9], 12, md_k3);
md1_Subround(md_I, c1, d1, a1, b1, X[11], 14, md_k3);
md1_Subround(md_I, b1, c1, d1, a1, X[10], 15, md_k3);
md1_Subround(md_I, a1, b1, c1, d1, X[ 0], 14, md_k3);
md1_Subround(md_I, d1, a1, b1, c1, X[ 8], 15, md_k3);
md1_Subround(md_I, c1, d1, a1, b1, X[12], 9, md_k3);
md1_Subround(md_I, b1, c1, d1, a1, X[ 4], 8, md_k3);
md1_Subround(md_I, a1, b1, c1, d1, X[13], 9, md_k3);
md1_Subround(md_I, d1, a1, b1, c1, X[ 3], 14, md_k3);
md1_Subround(md_I, c1, d1, a1, b1, X[ 7], 5, md_k3);
md1_Subround(md_I, b1, c1, d1, a1, X[15], 6, md_k3);
md1_Subround(md_I, a1, b1, c1, d1, X[14], 8, md_k3);
md1_Subround(md_I, d1, a1, b1, c1, X[ 5], 6, md_k3);
md1_Subround(md_I, c1, d1, a1, b1, X[ 6], 5, md_k3);
md1_Subround(md_I, b1, c1, d1, a1, X[ 2], 12, md_k3);
md1_Subround(md_I, a2, b2, c2, d2, X[ 5], 8, md_k5);
md1_Subround(md_I, d2, a2, b2, c2, X[14], 9, md_k5);
md1_Subround(md_I, c2, d2, a2, b2, X[ 7], 9, md_k5);
md1_Subround(md_I, b2, c2, d2, a2, X[ 0], 11, md_k5);
md1_Subround(md_I, a2, b2, c2, d2, X[ 9], 13, md_k5);
md1_Subround(md_I, d2, a2, b2, c2, X[ 2], 15, md_k5);
md1_Subround(md_I, c2, d2, a2, b2, X[11], 15, md_k5);
md1_Subround(md_I, b2, c2, d2, a2, X[ 4], 5, md_k5);
md1_Subround(md_I, a2, b2, c2, d2, X[13], 7, md_k5);
md1_Subround(md_I, d2, a2, b2, c2, X[ 6], 7, md_k5);
md1_Subround(md_I, c2, d2, a2, b2, X[15], 8, md_k5);
md1_Subround(md_I, b2, c2, d2, a2, X[ 8], 11, md_k5);
md1_Subround(md_I, a2, b2, c2, d2, X[ 1], 14, md_k5);
md1_Subround(md_I, d2, a2, b2, c2, X[10], 14, md_k5);
md1_Subround(md_I, c2, d2, a2, b2, X[ 3], 12, md_k5);
md1_Subround(md_I, b2, c2, d2, a2, X[12], 6, md_k5);
md1_Subround(md_H, a2, b2, c2, d2, X[ 6], 9, md_k6);
md1_Subround(md_H, d2, a2, b2, c2, X[11], 13, md_k6);
md1_Subround(md_H, c2, d2, a2, b2, X[ 3], 15, md_k6);
md1_Subround(md_H, b2, c2, d2, a2, X[ 7], 7, md_k6);
md1_Subround(md_H, a2, b2, c2, d2, X[ 0], 12, md_k6);
md1_Subround(md_H, d2, a2, b2, c2, X[13], 8, md_k6);
md1_Subround(md_H, c2, d2, a2, b2, X[ 5], 9, md_k6);
md1_Subround(md_H, b2, c2, d2, a2, X[10], 11, md_k6);
md1_Subround(md_H, a2, b2, c2, d2, X[14], 7, md_k6);
md1_Subround(md_H, d2, a2, b2, c2, X[15], 7, md_k6);
md1_Subround(md_H, c2, d2, a2, b2, X[ 8], 12, md_k6);
md1_Subround(md_H, b2, c2, d2, a2, X[12], 7, md_k6);
md1_Subround(md_H, a2, b2, c2, d2, X[ 4], 6, md_k6);
md1_Subround(md_H, d2, a2, b2, c2, X[ 9], 15, md_k6);
md1_Subround(md_H, c2, d2, a2, b2, X[ 1], 13, md_k6);
md1_Subround(md_H, b2, c2, d2, a2, X[ 2], 11, md_k6);
md1_Subround(md_G, a2, b2, c2, d2, X[15], 9, md_k7);
md1_Subround(md_G, d2, a2, b2, c2, X[ 5], 7, md_k7);
md1_Subround(md_G, c2, d2, a2, b2, X[ 1], 15, md_k7);
md1_Subround(md_G, b2, c2, d2, a2, X[ 3], 11, md_k7);
md1_Subround(md_G, a2, b2, c2, d2, X[ 7], 8, md_k7);
md1_Subround(md_G, d2, a2, b2, c2, X[14], 6, md_k7);
md1_Subround(md_G, c2, d2, a2, b2, X[ 6], 6, md_k7);
md1_Subround(md_G, b2, c2, d2, a2, X[ 9], 14, md_k7);
md1_Subround(md_G, a2, b2, c2, d2, X[11], 12, md_k7);
md1_Subround(md_G, d2, a2, b2, c2, X[ 8], 13, md_k7);
md1_Subround(md_G, c2, d2, a2, b2, X[12], 5, md_k7);
md1_Subround(md_G, b2, c2, d2, a2, X[ 2], 14, md_k7);
md1_Subround(md_G, a2, b2, c2, d2, X[10], 13, md_k7);
md1_Subround(md_G, d2, a2, b2, c2, X[ 0], 13, md_k7);
md1_Subround(md_G, c2, d2, a2, b2, X[ 4], 7, md_k7);
md1_Subround(md_G, b2, c2, d2, a2, X[13], 5, md_k7);
md1_Subround(md_F, a2, b2, c2, d2, X[ 8], 15, md_k9);
md1_Subround(md_F, d2, a2, b2, c2, X[ 6], 5, md_k9);
md1_Subround(md_F, c2, d2, a2, b2, X[ 4], 8, md_k9);
md1_Subround(md_F, b2, c2, d2, a2, X[ 1], 11, md_k9);
md1_Subround(md_F, a2, b2, c2, d2, X[ 3], 14, md_k9);
md1_Subround(md_F, d2, a2, b2, c2, X[11], 14, md_k9);
md1_Subround(md_F, c2, d2, a2, b2, X[15], 6, md_k9);
md1_Subround(md_F, b2, c2, d2, a2, X[ 0], 14, md_k9);
md1_Subround(md_F, a2, b2, c2, d2, X[ 5], 6, md_k9);
md1_Subround(md_F, d2, a2, b2, c2, X[12], 9, md_k9);
md1_Subround(md_F, c2, d2, a2, b2, X[ 2], 12, md_k9);
md1_Subround(md_F, b2, c2, d2, a2, X[13], 9, md_k9);
md1_Subround(md_F, a2, b2, c2, d2, X[ 9], 12, md_k9);
md1_Subround(md_F, d2, a2, b2, c2, X[ 7], 5, md_k9);
md1_Subround(md_F, c2, d2, a2, b2, X[10], 15, md_k9);
md1_Subround(md_F, b2, c2, d2, a2, X[14], 8, md_k9);
c1 = MDbuf[1] + c1 + d2;
MDbuf[1] = MDbuf[2] + d1 + a2;
MDbuf[2] = MDbuf[3] + a1 + b2;
MDbuf[3] = MDbuf[0] + b1 + c2;
MDbuf[0] = c1;
}
private:
UI32 MDbuf[4]; //保存有ripemd输出值
UI32 X[16]; //保存有每步变换时对输入的初始化转化值
};
//...end ripemd128
这里是附件:
附件包含有2个文件:
define.h 定义了数据结构和操作
ripemd.h 定义了所有ripemd类
SHA系列Hash算法是由美国国家安全局(US National Security Agency)设计的。完整的说,SHA共有6个标准。分别是:SHA-0(1992年)、SHA-1(1995年)、SHA224(2002年)、SHA256(2000年)、SHA-384(2000年)和SHA-512(2000年)。关于SHA算法最权威的文档当属FIPS P180系列,最新的是2002年修订的FIPS P180-2。参考地址为:http://csrc.nist.gov/publications/.
SHA的具体描述大家自己去下载文档来看就行了。SHA与普通Hash算法最大的不同在于它不是专门为Intel cpu设计的,所以,其整数的表示方式和Intel cpu目前的低字节在前的方法不一样。以下只列出了SHA-1算法的代码。
#ifndef Goodzzp_SHA_05_10_12_16
#define Goodzzp_SHA_05_10_12_16
//sha-1,224,256,384,512
//program by Goodzzp
//2005.10.13
//Notice:
// this sha.h file referred crypto++5.21 and SHA standard(Federal Information
// Processing Standards Publication 180-2 with SHA224 notice) 2002 Auguest 1
#include "define.h"
//....beigin sha-1
#define sha_blk0(i) (W = m_data)
#define sha_blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
#define sha_f1(x,y,z) (z^(x&(y^z)))
#define sha_f2(x,y,z) (x^y^z)
#define sha_f3(x,y,z) ((x&y)|(z&(x|y)))
#define sha_f4(x,y,z) (x^y^z)
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define sha_R0(v,w,x,y,z,i) z+=sha_f1(w,x,y)+sha_blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R1(v,w,x,y,z,i) z+=sha_f1(w,x,y)+sha_blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R2(v,w,x,y,z,i) z+=sha_f2(w,x,y)+sha_blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R3(v,w,x,y,z,i) z+=sha_f3(w,x,y)+sha_blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R4(v,w,x,y,z,i) z+=sha_f4(w,x,y)+sha_blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30);
//sha1 algorithm
class SHA1
{
public:
//输出结果的长度(字节)
static UI32 OutDataLength()
{
return 4*5;
}
//SHA-1变换函数
//out:输出,长度为20,要求事先已经分配了内存
//in:输入
//length:输入值的长度
void Hash(UI8 *out,const UI8 *in,UI32 length)
{
UI32 i = length>>6,j=(length&0x3f),k;
//对数据64 64个字节的计算
for(k=0;k> 8) | ((m_state&0xff000000)>>24);
}
memcpy(out,m_state,4*5);
//恢复m_state值
m_state[0] = 0x67452301L;
m_state[1] = 0xEFCDAB89L;
m_state[2] = 0x98BADCFEL;
m_state[3] = 0x10325476L;
m_state[4] = 0xC3D2E1F0L;
}
SHA1() //initialize data
{
m_state[0] = 0x67452301L;
m_state[1] = 0xEFCDAB89L;
m_state[2] = 0x98BADCFEL;
m_state[3] = 0x10325476L;
m_state[4] = 0xC3D2E1F0L;
}
private:
//每步的变换函数
//输入:
// data: 要处理的数据块(不大于64字节)
// dataBlockLen: 数据块的长度
// dataTotalLen: 要处理的所有数据块的总长度
//输出结果保存在m_state里面
void StepTransform(UI8 *data,UI32 dataBlockLen, UI32 dataTotalLen)
{
UI8 buffer[64];
UI32 len=dataTotalLen*8;
memset(buffer,0,64);//清空数据为0
memcpy(buffer,data,dataBlockLen);//拷贝数据到缓冲
if(dataBlockLen >=8;
buffer[62]=(UI8)(len&0xff);
len>>=8;
buffer[61]=(UI8)(len&0xff);
len>>=8;
buffer[60]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
else if(dataBlockLen>=56)
{
//添加1和0
buffer[dataBlockLen]=0x80;
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
//添加长度
memset(buffer,0,64);
buffer[63]=(UI8)(len&0xff);
len>>=8;
buffer[62]=(UI8)(len&0xff);
len>>=8;
buffer[61]=(UI8)(len&0xff);
len>>=8;
buffer[60]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
}
else if(dataBlockLen == 64)
{
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
}
//把64字节的原始数据data进行初步转化到m_data中去
void FirstTransform(UI32 *data)
{
//拷贝
memcpy(m_data,data,64);
//反转,因为sha-1是低位在后面的存储方法,所以,需要把abcd efgh变成dcba hgfe。
for(UI32 i=0;i> 8) | ((m_data&0xff000000)>>24);
}
//根据这16个生成其它64个UI32
for(UI32 j=16;j
作 者: lotusroots
时 间: 2005-11-01,13:45
链 接: http://bbs.pediy.com/showthread.php?t=18092
作者:冲出宇宙
说明:作者水平所限,恐怕错误比较多,请兄弟们多多包涵。并提出指正。
昨天刚在这里发了一个帖子,今天就发现被转移到其他地方去了。思考之后,决定把自己写的几个标准的Hash函数代码和说明发布到这里来。这下不会把我的东西转移了吧?
首先看看美国的FIPS下的Hash算法标准:
1,ripemd
2,sha
3,tiger
4,whirlpool
md5以前好像也是这个里面的标准。不知道是不是真的是。反正现在已经不是了。md5的代码网络上铺天盖地都是的,我们将不讨论和md5有关的话题。需要代码的请看:
http://lotusroots.bokee.com ,那里也包含了hash算法的更详细的讨论。
1, ripemd
顾名思义ripemd就是成熟md算法,是Hans Dobbertin等3人在md4,md5的基础上,于1996年提出来的。算法共有4个标准128、160、256和320,其对应输出长度分别为16字节、20字节、32字节和40字节。不过,让人难以致信的是ripemd的设计者们根本就没有真正设计256和320位这2种标准,他们只是在128位和160位的基础上,修改了初始参数和s-box来达到输出为256和320位的目的。所以,256位的强度和128相当,而320位的强度和160位相当。ripemd建立在md的基础之上,所以,其添加数据的方式和md5完全一样。
这里只列出ripemd128的代码。需要其他代码的兄弟可以下载附件。
其参考代码如下:
ripemd.h文件:
#ifndef Goodzzp_RipeMd_05_10_20_12
#define Goodzzp_RipeMd_05_10_20_12
//ripemd128,160,256,320
//program be Goodzzp
//05,10,20
//128 and 160 are referred:
//http://homes.esat.md_kuleuven.be/~bosselae/ripemd160.html
//256 and 320 are not guarranteed to be safe than 128 or 160
//referred: Crypto++5.21
#include "define.h"
//128-320需要的5论变换
#define md_F(x, y, z) (x ^ y ^ z)
#define md_G(x, y, z) (z ^ (x & (y^z)))
#define md_H(x, y, z) (z ^ (x | ~y))
#define md_I(x, y, z) (y ^ (z & (x^y)))
#define md_J(x, y, z) (x ^ (y | ~z))
//常量
#define md_k0 0
#define md_k1 0x5a827999UL
#define md_k2 0x6ed9eba1UL
#define md_k3 0x8f1bbcdcUL
#define md_k4 0xa953fd4eUL
#define md_k5 0x50a28be6UL
#define md_k6 0x5c4dd124UL
#define md_k7 0x6d703ef3UL
#define md_k8 0x7a6d76e9UL
#define md_k9 0
// for 128 and 256
#define md1_Subround(f, a, b, c, d, x, s, md_k) \
a += f(b, c, d) + x + md_k;\
a = rotlFixed((UI32)a, s);
//...begin ripemd128
//RipeMd128散列类
class RipeMD128
{
public:
//输出结果的长度(字节)
static UI32 OutDataLength()
{
return 128/8;
}
//RipeMD128变换函数
//out:输出,长度为16,要求事先已经分配了内存
//in:输入
//length:输入值的长度
void Hash(UI8 *out,const UI8 *in,UI32 length)
{
UI32 i = length>>6,j=(length&0x3f),md_k;
//对数据64 64个字节的计算
for(md_k=0;md_k>=8;
buffer[57]=(UI8)(len&0xff);
len>>=8;
buffer[58]=(UI8)(len&0xff);
len>>=8;
buffer[59]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
else if(dataBlockLen>=56)
{
//添加1和0
buffer[dataBlockLen]=0x80;
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
//添加长度
memset(buffer,0,64);
buffer[56]=(UI8)(len&0xff);
len>>=8;
buffer[57]=(UI8)(len&0xff);
len>>=8;
buffer[58]=(UI8)(len&0xff);
len>>=8;
buffer[59]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
}
else if(dataBlockLen == 64)
{
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
}
//把64字节的原始数据data进行初步转化到m_data中去
void FirstTransform(UI32 *data)
{
memcpy(X,data,64);
}
//核心变换
void CoreTransform()
{
UI32 a1, b1, c1, d1, a2, b2, c2, d2;
a1 = a2 = MDbuf[0];
b1 = b2 = MDbuf[1];
c1 = c2 = MDbuf[2];
d1 = d2 = MDbuf[3];
md1_Subround(md_F, a1, b1, c1, d1, X[ 0], 11, md_k0);
md1_Subround(md_F, d1, a1, b1, c1, X[ 1], 14, md_k0);
md1_Subround(md_F, c1, d1, a1, b1, X[ 2], 15, md_k0);
md1_Subround(md_F, b1, c1, d1, a1, X[ 3], 12, md_k0);
md1_Subround(md_F, a1, b1, c1, d1, X[ 4], 5, md_k0);
md1_Subround(md_F, d1, a1, b1, c1, X[ 5], 8, md_k0);
md1_Subround(md_F, c1, d1, a1, b1, X[ 6], 7, md_k0);
md1_Subround(md_F, b1, c1, d1, a1, X[ 7], 9, md_k0);
md1_Subround(md_F, a1, b1, c1, d1, X[ 8], 11, md_k0);
md1_Subround(md_F, d1, a1, b1, c1, X[ 9], 13, md_k0);
md1_Subround(md_F, c1, d1, a1, b1, X[10], 14, md_k0);
md1_Subround(md_F, b1, c1, d1, a1, X[11], 15, md_k0);
md1_Subround(md_F, a1, b1, c1, d1, X[12], 6, md_k0);
md1_Subround(md_F, d1, a1, b1, c1, X[13], 7, md_k0);
md1_Subround(md_F, c1, d1, a1, b1, X[14], 9, md_k0);
md1_Subround(md_F, b1, c1, d1, a1, X[15], 8, md_k0);
md1_Subround(md_G, a1, b1, c1, d1, X[ 7], 7, md_k1);
md1_Subround(md_G, d1, a1, b1, c1, X[ 4], 6, md_k1);
md1_Subround(md_G, c1, d1, a1, b1, X[13], 8, md_k1);
md1_Subround(md_G, b1, c1, d1, a1, X[ 1], 13, md_k1);
md1_Subround(md_G, a1, b1, c1, d1, X[10], 11, md_k1);
md1_Subround(md_G, d1, a1, b1, c1, X[ 6], 9, md_k1);
md1_Subround(md_G, c1, d1, a1, b1, X[15], 7, md_k1);
md1_Subround(md_G, b1, c1, d1, a1, X[ 3], 15, md_k1);
md1_Subround(md_G, a1, b1, c1, d1, X[12], 7, md_k1);
md1_Subround(md_G, d1, a1, b1, c1, X[ 0], 12, md_k1);
md1_Subround(md_G, c1, d1, a1, b1, X[ 9], 15, md_k1);
md1_Subround(md_G, b1, c1, d1, a1, X[ 5], 9, md_k1);
md1_Subround(md_G, a1, b1, c1, d1, X[ 2], 11, md_k1);
md1_Subround(md_G, d1, a1, b1, c1, X[14], 7, md_k1);
md1_Subround(md_G, c1, d1, a1, b1, X[11], 13, md_k1);
md1_Subround(md_G, b1, c1, d1, a1, X[ 8], 12, md_k1);
md1_Subround(md_H, a1, b1, c1, d1, X[ 3], 11, md_k2);
md1_Subround(md_H, d1, a1, b1, c1, X[10], 13, md_k2);
md1_Subround(md_H, c1, d1, a1, b1, X[14], 6, md_k2);
md1_Subround(md_H, b1, c1, d1, a1, X[ 4], 7, md_k2);
md1_Subround(md_H, a1, b1, c1, d1, X[ 9], 14, md_k2);
md1_Subround(md_H, d1, a1, b1, c1, X[15], 9, md_k2);
md1_Subround(md_H, c1, d1, a1, b1, X[ 8], 13, md_k2);
md1_Subround(md_H, b1, c1, d1, a1, X[ 1], 15, md_k2);
md1_Subround(md_H, a1, b1, c1, d1, X[ 2], 14, md_k2);
md1_Subround(md_H, d1, a1, b1, c1, X[ 7], 8, md_k2);
md1_Subround(md_H, c1, d1, a1, b1, X[ 0], 13, md_k2);
md1_Subround(md_H, b1, c1, d1, a1, X[ 6], 6, md_k2);
md1_Subround(md_H, a1, b1, c1, d1, X[13], 5, md_k2);
md1_Subround(md_H, d1, a1, b1, c1, X[11], 12, md_k2);
md1_Subround(md_H, c1, d1, a1, b1, X[ 5], 7, md_k2);
md1_Subround(md_H, b1, c1, d1, a1, X[12], 5, md_k2);
md1_Subround(md_I, a1, b1, c1, d1, X[ 1], 11, md_k3);
md1_Subround(md_I, d1, a1, b1, c1, X[ 9], 12, md_k3);
md1_Subround(md_I, c1, d1, a1, b1, X[11], 14, md_k3);
md1_Subround(md_I, b1, c1, d1, a1, X[10], 15, md_k3);
md1_Subround(md_I, a1, b1, c1, d1, X[ 0], 14, md_k3);
md1_Subround(md_I, d1, a1, b1, c1, X[ 8], 15, md_k3);
md1_Subround(md_I, c1, d1, a1, b1, X[12], 9, md_k3);
md1_Subround(md_I, b1, c1, d1, a1, X[ 4], 8, md_k3);
md1_Subround(md_I, a1, b1, c1, d1, X[13], 9, md_k3);
md1_Subround(md_I, d1, a1, b1, c1, X[ 3], 14, md_k3);
md1_Subround(md_I, c1, d1, a1, b1, X[ 7], 5, md_k3);
md1_Subround(md_I, b1, c1, d1, a1, X[15], 6, md_k3);
md1_Subround(md_I, a1, b1, c1, d1, X[14], 8, md_k3);
md1_Subround(md_I, d1, a1, b1, c1, X[ 5], 6, md_k3);
md1_Subround(md_I, c1, d1, a1, b1, X[ 6], 5, md_k3);
md1_Subround(md_I, b1, c1, d1, a1, X[ 2], 12, md_k3);
md1_Subround(md_I, a2, b2, c2, d2, X[ 5], 8, md_k5);
md1_Subround(md_I, d2, a2, b2, c2, X[14], 9, md_k5);
md1_Subround(md_I, c2, d2, a2, b2, X[ 7], 9, md_k5);
md1_Subround(md_I, b2, c2, d2, a2, X[ 0], 11, md_k5);
md1_Subround(md_I, a2, b2, c2, d2, X[ 9], 13, md_k5);
md1_Subround(md_I, d2, a2, b2, c2, X[ 2], 15, md_k5);
md1_Subround(md_I, c2, d2, a2, b2, X[11], 15, md_k5);
md1_Subround(md_I, b2, c2, d2, a2, X[ 4], 5, md_k5);
md1_Subround(md_I, a2, b2, c2, d2, X[13], 7, md_k5);
md1_Subround(md_I, d2, a2, b2, c2, X[ 6], 7, md_k5);
md1_Subround(md_I, c2, d2, a2, b2, X[15], 8, md_k5);
md1_Subround(md_I, b2, c2, d2, a2, X[ 8], 11, md_k5);
md1_Subround(md_I, a2, b2, c2, d2, X[ 1], 14, md_k5);
md1_Subround(md_I, d2, a2, b2, c2, X[10], 14, md_k5);
md1_Subround(md_I, c2, d2, a2, b2, X[ 3], 12, md_k5);
md1_Subround(md_I, b2, c2, d2, a2, X[12], 6, md_k5);
md1_Subround(md_H, a2, b2, c2, d2, X[ 6], 9, md_k6);
md1_Subround(md_H, d2, a2, b2, c2, X[11], 13, md_k6);
md1_Subround(md_H, c2, d2, a2, b2, X[ 3], 15, md_k6);
md1_Subround(md_H, b2, c2, d2, a2, X[ 7], 7, md_k6);
md1_Subround(md_H, a2, b2, c2, d2, X[ 0], 12, md_k6);
md1_Subround(md_H, d2, a2, b2, c2, X[13], 8, md_k6);
md1_Subround(md_H, c2, d2, a2, b2, X[ 5], 9, md_k6);
md1_Subround(md_H, b2, c2, d2, a2, X[10], 11, md_k6);
md1_Subround(md_H, a2, b2, c2, d2, X[14], 7, md_k6);
md1_Subround(md_H, d2, a2, b2, c2, X[15], 7, md_k6);
md1_Subround(md_H, c2, d2, a2, b2, X[ 8], 12, md_k6);
md1_Subround(md_H, b2, c2, d2, a2, X[12], 7, md_k6);
md1_Subround(md_H, a2, b2, c2, d2, X[ 4], 6, md_k6);
md1_Subround(md_H, d2, a2, b2, c2, X[ 9], 15, md_k6);
md1_Subround(md_H, c2, d2, a2, b2, X[ 1], 13, md_k6);
md1_Subround(md_H, b2, c2, d2, a2, X[ 2], 11, md_k6);
md1_Subround(md_G, a2, b2, c2, d2, X[15], 9, md_k7);
md1_Subround(md_G, d2, a2, b2, c2, X[ 5], 7, md_k7);
md1_Subround(md_G, c2, d2, a2, b2, X[ 1], 15, md_k7);
md1_Subround(md_G, b2, c2, d2, a2, X[ 3], 11, md_k7);
md1_Subround(md_G, a2, b2, c2, d2, X[ 7], 8, md_k7);
md1_Subround(md_G, d2, a2, b2, c2, X[14], 6, md_k7);
md1_Subround(md_G, c2, d2, a2, b2, X[ 6], 6, md_k7);
md1_Subround(md_G, b2, c2, d2, a2, X[ 9], 14, md_k7);
md1_Subround(md_G, a2, b2, c2, d2, X[11], 12, md_k7);
md1_Subround(md_G, d2, a2, b2, c2, X[ 8], 13, md_k7);
md1_Subround(md_G, c2, d2, a2, b2, X[12], 5, md_k7);
md1_Subround(md_G, b2, c2, d2, a2, X[ 2], 14, md_k7);
md1_Subround(md_G, a2, b2, c2, d2, X[10], 13, md_k7);
md1_Subround(md_G, d2, a2, b2, c2, X[ 0], 13, md_k7);
md1_Subround(md_G, c2, d2, a2, b2, X[ 4], 7, md_k7);
md1_Subround(md_G, b2, c2, d2, a2, X[13], 5, md_k7);
md1_Subround(md_F, a2, b2, c2, d2, X[ 8], 15, md_k9);
md1_Subround(md_F, d2, a2, b2, c2, X[ 6], 5, md_k9);
md1_Subround(md_F, c2, d2, a2, b2, X[ 4], 8, md_k9);
md1_Subround(md_F, b2, c2, d2, a2, X[ 1], 11, md_k9);
md1_Subround(md_F, a2, b2, c2, d2, X[ 3], 14, md_k9);
md1_Subround(md_F, d2, a2, b2, c2, X[11], 14, md_k9);
md1_Subround(md_F, c2, d2, a2, b2, X[15], 6, md_k9);
md1_Subround(md_F, b2, c2, d2, a2, X[ 0], 14, md_k9);
md1_Subround(md_F, a2, b2, c2, d2, X[ 5], 6, md_k9);
md1_Subround(md_F, d2, a2, b2, c2, X[12], 9, md_k9);
md1_Subround(md_F, c2, d2, a2, b2, X[ 2], 12, md_k9);
md1_Subround(md_F, b2, c2, d2, a2, X[13], 9, md_k9);
md1_Subround(md_F, a2, b2, c2, d2, X[ 9], 12, md_k9);
md1_Subround(md_F, d2, a2, b2, c2, X[ 7], 5, md_k9);
md1_Subround(md_F, c2, d2, a2, b2, X[10], 15, md_k9);
md1_Subround(md_F, b2, c2, d2, a2, X[14], 8, md_k9);
c1 = MDbuf[1] + c1 + d2;
MDbuf[1] = MDbuf[2] + d1 + a2;
MDbuf[2] = MDbuf[3] + a1 + b2;
MDbuf[3] = MDbuf[0] + b1 + c2;
MDbuf[0] = c1;
}
private:
UI32 MDbuf[4]; //保存有ripemd输出值
UI32 X[16]; //保存有每步变换时对输入的初始化转化值
};
//...end ripemd128
这里是附件:
附件包含有2个文件:
define.h 定义了数据结构和操作
ripemd.h 定义了所有ripemd类
SHA系列Hash算法是由美国国家安全局(US National Security Agency)设计的。完整的说,SHA共有6个标准。分别是:SHA-0(1992年)、SHA-1(1995年)、SHA224(2002年)、SHA256(2000年)、SHA-384(2000年)和SHA-512(2000年)。关于SHA算法最权威的文档当属FIPS P180系列,最新的是2002年修订的FIPS P180-2。参考地址为:http://csrc.nist.gov/publications/.
SHA的具体描述大家自己去下载文档来看就行了。SHA与普通Hash算法最大的不同在于它不是专门为Intel cpu设计的,所以,其整数的表示方式和Intel cpu目前的低字节在前的方法不一样。以下只列出了SHA-1算法的代码。
#ifndef Goodzzp_SHA_05_10_12_16
#define Goodzzp_SHA_05_10_12_16
//sha-1,224,256,384,512
//program by Goodzzp
//2005.10.13
//Notice:
// this sha.h file referred crypto++5.21 and SHA standard(Federal Information
// Processing Standards Publication 180-2 with SHA224 notice) 2002 Auguest 1
#include "define.h"
//....beigin sha-1
#define sha_blk0(i) (W = m_data)
#define sha_blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
#define sha_f1(x,y,z) (z^(x&(y^z)))
#define sha_f2(x,y,z) (x^y^z)
#define sha_f3(x,y,z) ((x&y)|(z&(x|y)))
#define sha_f4(x,y,z) (x^y^z)
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define sha_R0(v,w,x,y,z,i) z+=sha_f1(w,x,y)+sha_blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R1(v,w,x,y,z,i) z+=sha_f1(w,x,y)+sha_blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R2(v,w,x,y,z,i) z+=sha_f2(w,x,y)+sha_blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R3(v,w,x,y,z,i) z+=sha_f3(w,x,y)+sha_blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30);
#define sha_R4(v,w,x,y,z,i) z+=sha_f4(w,x,y)+sha_blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30);
//sha1 algorithm
class SHA1
{
public:
//输出结果的长度(字节)
static UI32 OutDataLength()
{
return 4*5;
}
//SHA-1变换函数
//out:输出,长度为20,要求事先已经分配了内存
//in:输入
//length:输入值的长度
void Hash(UI8 *out,const UI8 *in,UI32 length)
{
UI32 i = length>>6,j=(length&0x3f),k;
//对数据64 64个字节的计算
for(k=0;k> 8) | ((m_state&0xff000000)>>24);
}
memcpy(out,m_state,4*5);
//恢复m_state值
m_state[0] = 0x67452301L;
m_state[1] = 0xEFCDAB89L;
m_state[2] = 0x98BADCFEL;
m_state[3] = 0x10325476L;
m_state[4] = 0xC3D2E1F0L;
}
SHA1() //initialize data
{
m_state[0] = 0x67452301L;
m_state[1] = 0xEFCDAB89L;
m_state[2] = 0x98BADCFEL;
m_state[3] = 0x10325476L;
m_state[4] = 0xC3D2E1F0L;
}
private:
//每步的变换函数
//输入:
// data: 要处理的数据块(不大于64字节)
// dataBlockLen: 数据块的长度
// dataTotalLen: 要处理的所有数据块的总长度
//输出结果保存在m_state里面
void StepTransform(UI8 *data,UI32 dataBlockLen, UI32 dataTotalLen)
{
UI8 buffer[64];
UI32 len=dataTotalLen*8;
memset(buffer,0,64);//清空数据为0
memcpy(buffer,data,dataBlockLen);//拷贝数据到缓冲
if(dataBlockLen >=8;
buffer[62]=(UI8)(len&0xff);
len>>=8;
buffer[61]=(UI8)(len&0xff);
len>>=8;
buffer[60]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
else if(dataBlockLen>=56)
{
//添加1和0
buffer[dataBlockLen]=0x80;
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
//添加长度
memset(buffer,0,64);
buffer[63]=(UI8)(len&0xff);
len>>=8;
buffer[62]=(UI8)(len&0xff);
len>>=8;
buffer[61]=(UI8)(len&0xff);
len>>=8;
buffer[60]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
}
else if(dataBlockLen == 64)
{
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
}
//把64字节的原始数据data进行初步转化到m_data中去
void FirstTransform(UI32 *data)
{
//拷贝
memcpy(m_data,data,64);
//反转,因为sha-1是低位在后面的存储方法,所以,需要把abcd efgh变成dcba hgfe。
for(UI32 i=0;i> 8) | ((m_data&0xff000000)>>24);
}
//根据这16个生成其它64个UI32
for(UI32 j=16;j
相关阅读 更多 +