关键词: whirlpool
Whirlpool算法被列入了ISO标准。主要原因是因为其强大的安全度。第一点,Whirlpool使用了和AES加密标准相同的转化技术,只不过,AES使用的模函数为:f(x) = x^8 + x^4 + x^3 + x + 1, 即0x11B;而Whirlpool使用的是:f(x) = x^8 + x^4 + x^3 + x^2 + 1, 即0x11D。第二点,Whirlpool的输出是512位的。为了加快计算速度,Whirlpool使用的所有表格都已经时间计算好了。Whirlpool在历史上共有3个版本,根据最新的2003年版本,我们把目前的Whirlpool算法叫做Whirlpool 3.0。
以下是其具体代码实现。
#ifndef Goodzzp_WhirlPool_05_10_22_13
#define Goodzzp_WhirlPool_05_10_22_13
//whirlPool 3.0(2003,3)
//program by Goodzzp
//05,10,22
//referred:
//http://planeta.terra.com.br/informatica/paulobarreto/whirlpool.zip
//this document revised at 2003,5
#include "define.h"
//...begin whirlpool 3.0
#define R 10
#define LL(v) (v##i64)
class WhirlPool
{
public:
//输出结果的长度(字节)
static UI32 OutDataLength()
{
return 512/8;
}
//WhirlPool变换函数
//out:输出,长度为64,要求事先已经分配了内存
//in:输入
//length:输入值的长度
//说明:Whirlpool使用256位来表示数据长度。
void Hash(UI8 *out,const UI8 *in,UI32 length)
{
UI32 i = length>>6,j=(length&0x3f),k;
//对数据64 64个字节的计算
for(k=0;k {
StepTransform((UI8 *)(in + k * 64),64,length);
}
//最后计算尾数
StepTransform((UI8 *)(in + 64 * i),j,length);
//拷贝输出
for(i=0;i<8;i++) //反转
{
m_state[i] = ((m_state[i]&0xff) << 56) | ((m_state[i]&0xff00) << 40) |
((m_state[i]&0xff0000) << 24) | ((m_state[i]&0xff000000) << 8) |
((m_state[i]&0xff00000000) >> 8) | ((m_state[i]&0xff0000000000) >> 24) |
((m_state[i]&0xff000000000000) >> 40) | ((m_state[i]&0xff00000000000000) >> 56);;
}
memcpy(out,m_state,64);
//恢复初始值
m_state[0] = 0;
m_state[1] = 0;
m_state[2] = 0;
m_state[3] = 0;
m_state[4] = 0;
m_state[5] = 0;
m_state[6] = 0;
m_state[7] = 0;
}
WhirlPool() //initialize data
{
m_state[0] = 0;
m_state[1] = 0;
m_state[2] = 0;
m_state[3] = 0;
m_state[4] = 0;
m_state[5] = 0;
m_state[6] = 0;
m_state[7] = 0;
}
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 <64) //需要增加数据
{
if(dataBlockLen<32)//当前数据是最后若干个,而且不需要增加一次变换
{
//添加1和0
buffer[dataBlockLen]=0x80;
//添加长度
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);
len>>=8;
buffer[59]=(UI8)(len&0xff);
//变换
FirstTransform((UI32*)buffer);
CoreTransform();
}
else if(dataBlockLen>=32)
{
//添加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);
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(m_data,data,64);
}
//核心变换
void CoreTransform()
{
UI32 i, r;
UI64 K[8]; /* the round key */
UI64 block[8]; /* mu(buffer) */
UI64 state[8]; /* the cipher state */
UI64 L[8];
UI8 *buffer = m_data;
/*
* map the buffer to a block:
*/
for (i = 0; i < 8; i++, buffer += 8) {
block[i] =
(((UI64)buffer[0] ) << 56) ^
(((UI64)buffer[1] & 0xffL) << 48) ^
(((UI64)buffer[2] & 0xffL) << 40) ^
(((UI64)buffer[3] & 0xffL) << 32) ^
(((UI64)buffer[4] & 0xffL) << 24) ^
(((UI64)buffer[5] & 0xffL) << 16) ^
(((UI64)buffer[6] & 0xffL) << 8) ^
(((UI64)buffer[7] & 0xffL) );
}
/*
* compute and apply K^0 to the cipher state:
*/
state[0] = block[0] ^ (K[0] = m_state[0]);
state[1] = block[1] ^ (K[1] = m_state[1]);
state[2] = block[2] ^ (K[2] = m_state[2]);
state[3] = block[3] ^ (K[3] = m_state[3]);
state[4] = block[4] ^ (K[4] = m_state[4]);
state[5] = block[5] ^ (K[5] = m_state[5]);
state[6] = block[6] ^ (K[6] = m_state[6]);
state[7] = block[7] ^ (K[7] = m_state[7]);
/*
* iterate over all rounds:
*/
for (r = 1; r <= R; r++) {
/*
* compute K^r from K^{r-1}:
*/
L[0] =
C0[(UI32)(K[0] >> 56) ] ^
C1[(UI32)(K[7] >> 48) & 0xff] ^
C2[(UI32)(K[6] >> 40) & 0xff] ^
C3[(UI32)(K[5] >> 32) & 0xff] ^
C4[(UI32)(K[4] >> 24) & 0xff] ^
C5[(UI32)(K[3] >> 16) & 0xff] ^
C6[(UI32)(K[2] >> 8) & 0xff] ^
C7[(UI32)(K[1] ) & 0xff] ^
rc[r];
L[1] =
C0[(UI32)(K[1] >> 56) ] ^
C1[(UI32)(K[0] >> 48) & 0xff] ^
C2[(UI32)(K[7] >> 40) & 0xff] ^
C3[(UI32)(K[6] >> 32) & 0xff] ^
C4[(UI32)(K[5] >> 24) & 0xff] ^
C5[(UI32)(K[4] >> 16) & 0xff] ^
C6[(UI32)(K[3] >> 8) & 0xff] ^
C7[(UI32)(K[2] ) & 0xff];
L[2] =
C0[(UI32)(K[2] >> 56) ] ^
C1[(UI32)(K[1] >> 48) & 0xff] ^
C2[(UI32)(K[0] >> 40) & 0xff] ^
C3[(UI32)(K[7] >> 32) & 0xff] ^
C4[(UI32)(K[6] >> 24) & 0xff] ^
C5[(UI32)(K[5] >> 16) & 0xff] ^
C6[(UI32)(K[4] >> 8) & 0xff] ^
C7[(UI32)(K[3] ) & 0xff];
L[3] =
C0[(UI32)(K[3] >> 56) ] ^
C1[(UI32)(K[2] >> 48) & 0xff] ^
C2[(UI32)(K[1] >> 40) & 0xff] ^
C3[(UI32)(K[0] >> 32) & 0xff] ^
C4[(UI32)(K[7] >> 24) & 0xff] ^
C5[(UI32)(K[6] >> 16) & 0xff] ^
C6[(UI32)(K[5] >> 8) & 0xff] ^
C7[(UI32)(K[4] ) & 0xff];
L[4] =
C0[(UI32)(K[4] >> 56) ] ^
C1[(UI32)(K[3] >> 48) & 0xff] ^
C2[(UI32)(K[2] >> 40) & 0xff] ^
C3[(UI32)(K[1] >> 32) & 0xff] ^
C4[(UI32)(K[0] >> 24) & 0xff] ^
C5[(UI32)(K[7] >> 16) & 0xff] ^
C6[(UI32)(K[6] >> 8) & 0xff] ^
C7[(UI32)(K[5] ) & 0xff];
L[5] =
C0[(UI32)(K[5] >> 56) ] ^
C1[(UI32)(K[4] >> 48) & 0xff] ^
C2[(UI32)(K[3] >> 40) & 0xff] ^
C3[(UI32)(K[2] >> 32) & 0xff] ^
C4[(UI32)(K[1] >> 24) & 0xff] ^
C5[(UI32)(K[0] >> 16) & 0xff] ^
C6[(UI32)(K[7] >> 8) & 0xff] ^
C7[(UI32)(K[6] ) & 0xff];
L[6] =
C0[(UI32)(K[6] >> 56) ] ^
C1[(UI32)(K[5] >> 48) & 0xff] ^
C2[(UI32)(K[4] >> 40) & 0xff] ^
C3[(UI32)(K[3] >> 32) & 0xff] ^
C4[(UI32)(K[2] >> 24) & 0xff] ^
C5[(UI32)(K[1] >> 16) & 0xff] ^
C6[(UI32)(K[0] >> 8) & 0xff] ^
C7[(UI32)(K[7] ) & 0xff];
L[7] =
C0[(UI32)(K[7] >> 56) ] ^
C1[(UI32)(K[6] >> 48) & 0xff] ^
C2[(UI32)(K[5] >> 40) & 0xff] ^
C3[(UI32)(K[4] >> 32) & 0xff] ^
C4[(UI32)(K[3] >> 24) & 0xff] ^
C5[(UI32)(K[2] >> 16) & 0xff] ^
C6[(UI32)(K[1] >> 8) & 0xff] ^
C7[(UI32)(K[0] ) & 0xff];
K[0] = L[0];
K[1] = L[1];
K[2] = L[2];
K[3] = L[3];
K[4] = L[4];
K[5] = L[5];
K[6] = L[6];
K[7] = L[7];
/*
* apply the r-th round transformation:
*/
L[0] =
C0[(UI32)(state[0] >> 56) ] ^
C1[(UI32)(state[7] >> 48) & 0xff] ^
C2[(UI32)(state[6] >> 40) & 0xff] ^
C3[(UI32)(state[5] >> 32) & 0xff] ^
C4[(UI32)(state[4] >> 24) & 0xff] ^
C5[(UI32)(state[3] >> 16) & 0xff] ^
C6[(UI32)(state[2] >> 8) & 0xff] ^
C7[(UI32)(state[1] ) & 0xff] ^
K[0];
L[1] =
C0[(UI32)(state[1] >> 56) ] ^
C1[(UI32)(state[0] >> 48) & 0xff] ^
C2[(UI32)(state[7] >> 40) & 0xff] ^
C3[(UI32)(state[6] >> 32) & 0xff] ^
C4[(UI32)(state[5] >> 24) & 0xff] ^
C5[(UI32)(state[4] >> 16) & 0xff] ^
C6[(UI32)(state[3] >> 8) & 0xff] ^
C7[(UI32)(state[2] ) & 0xff] ^
K[1];
L[2] =
C0[(UI32)(state[2] >> 56) ] ^
C1[(UI32)(state[1] >> 48) & 0xff] ^
C2[(UI32)(state[0] >> 40) & 0xff] ^
C3[(UI32)(state[7] >> 32) & 0xff] ^
C4[(UI32)(state[6] >> 24) & 0xff] ^
C5[(UI32)(state[5] >> 16) & 0xff] ^
C6[(UI32)(state[4] >> 8) & 0xff] ^
C7[(UI32)(state[3] ) & 0xff] ^
K[2];
L[3] =
C0[(UI32)(state[3] >> 56) ] ^
C1[(UI32)(state[2] >> 48) & 0xff] ^
C2[(UI32)(state[1] >> 40) & 0xff] ^
C3[(UI32)(state[0] >> 32) & 0xff] ^
C4[(UI32)(state[7] >> 24) & 0xff] ^
C5[(UI32)(state[6] >> 16) & 0xff] ^
C6[(UI32)(state[5] >> 8) & 0xff] ^
C7[(UI32)(state[4] ) & 0xff] ^
K[3];
L[4] =
C0[(UI32)(state[4] >> 56) ] ^
C1[(UI32)(state[3] >> 48) & 0xff] ^
C2[(UI32)(state[2] >> 40) & 0xff] ^
C3[(UI32)(state[1] >> 32) & 0xff] ^
C4[(UI32)(state[0] >> 24) & 0xff] ^
C5[(UI32)(state[7] >> 16) & 0xff] ^
C6[(UI32)(state[6] >> 8) & 0xff] ^
C7[(UI32)(state[5] ) & 0xff] ^
K[4];
L[5] =
C0[(UI32)(state[5] >> 56) ] ^
C1[(UI32)(state[4] >> 48) & 0xff] ^
C2[(UI32)(state[3] >> 40) & 0xff] ^
C3[(UI32)(state[2] >> 32) & 0xff] ^
C4[(UI32)(state[1] >> 24) & 0xff] ^
C5[(UI32)(state[0] >> 16) & 0xff] ^
C6[(UI32)(state[7] >> 8) & 0xff] ^
C7[(UI32)(state[6] ) & 0xff] ^
K[5];
L[6] =
C0[(UI32)(state[6] >> 56) ] ^
C1[(UI32)(state[5] >> 48) & 0xff] ^
C2[(UI32)(state[4] >> 40) & 0xff] ^
C3[(UI32)(state[3] >> 32) & 0xff] ^
C4[(UI32)(state[2] >> 24) & 0xff] ^
C5[(UI32)(state[1] >> 16) & 0xff] ^
C6[(UI32)(state[0] >> 8) & 0xff] ^
C7[(UI32)(state[7] ) & 0xff] ^
K[6];
L[7] =
C0[(UI32)(state[7] >> 56) ] ^
C1[(UI32)(state[6] >> 48) & 0xff] ^
C2[(UI32)(state[5] >> 40) & 0xff] ^
C3[(UI32)(state[4] >> 32) & 0xff] ^
C4[(UI32)(state[3] >> 24) & 0xff] ^
C5[(UI32)(state[2] >> 16) & 0xff] ^
C6[(UI32)(state[1] >> 8) & 0xff] ^
C7[(UI32)(state[0] ) & 0xff] ^<