#include <string.h>
#include <stdlib.h>
#include <stdio.h>
typedef unsigned __int64 UINT64;
#define NULL 0
// The standard SHA1 needs the input string to fit into a block
// This function align the input string to meet the requirement
void AlignSHA1(const char *pIn,UINT64 *pBlks, UINT64 &nBlksLen)
{
if (pIn == NULL)
{
return;
}
UINT64 nInLen = strlen(pIn);
UINT64 nBlk = ((nInLen+8)>> 6)+1;
if (pBlks == NULL)
{
nBlksLen = nBlk*16;
return;
}
for (int j=0; j <nBlksLen; j++)
{
pBlks[j] = 0;
}
for(UINT64 i=0; i <nInLen; i++)
{
pBlks[i>> 2] |= pIn[i] <<(24-(i&3)*8);
}
pBlks[i>> 2] |= 0x80 <<(24-(i&3)*8);
pBlks[nBlksLen-1]=(int)(nInLen*8);
return ;
}
// The int32 add function which doesn 't generate overflow
// exception. This is required by the algorithm
UINT64 add(UINT64 x, UINT64 y)
{
UINT64 lsw = (x&0xffff)+(y&0xffff);
UINT64 msw = (x>> 16) + (y>> 16) +(lsw>> 16);
return (msw <<16) | (lsw&0xffff);
}
UINT64 UnsigedRightMove(UINT64 num, UINT64 bit)
{
num &=0xffffffff;
num >>= bit ;
return num;
}
// The int32 _asm rol :)
UINT64 rol(UINT64 num,UINT64 cnt)
{
return(num <<cnt)|UnsigedRightMove(num, (32-cnt));
}
// Perform the appropriate triplet combination function for the current round
UINT64 ft(UINT64 t, UINT64 b, UINT64 c, UINT64 d)
{
if(t <20)return(b&c)|((~b)&d);
if(t <40)return b^c^d;
if(t <60)return(b&c)|(b&d)|(c&d);
return b^c^d;
}
// Determine the appropriate additive constant for the current iteration
UINT64 kt(UINT64 t)
{
return(t <20)?1518500249:(t <40)?1859775393:
(t <60)?-1894007588:-899497514;
}
char* Uint64ToHexStr(UINT64 num, char *buf, int nLen)
{
if (buf == NULL || nLen <8)
{
return buf;
}
char szTemp[9]={0};
ultoa((unsigned long)num, szTemp, 16);
static char *s_pZero[]=
{
"0 ",
"00 ",
"000 "
"0000 ",
"00000 ",
"000000 ",
"0000000 ",
"00000000 ",
"000000000 ",
};
int nRealLen = strlen(szTemp);
int nSpareBit = 7-nRealLen;
if (nSpareBit >=0 && nSpareBit <=7)
{
memcpy(buf, s_pZero[nSpareBit], nSpareBit+1);
memcpy(buf+ nSpareBit+1, szTemp, nRealLen);
}
else
{
memcpy(buf, szTemp, 8);
}
return buf;
}
char* SHA1(const unsigned char *pIn, char *pOut, int nOutLen)
{
if (pIn == NULL)
{
return pOut;
}
UINT64 nBlksLen = 0;
AlignSHA1((const char*)pIn, NULL, nBlksLen);
UINT64 *pBlks = new UINT64[(int)nBlksLen];
if (pBlks == NULL)
{
return pOut;
}
AlignSHA1((const char*)pIn, pBlks, nBlksLen);
UINT64 w[80] ={0};
UINT64 a=1732584193;
UINT64 b=-271733879;
UINT64 c=-1732584194;
UINT64 d=271733878;
UINT64 e=-1009589776;
for (UINT64 i=0; i <nBlksLen; i+=16)
{
UINT64 olda=a;
UINT64 oldb=b;
UINT64 oldc=c;
UINT64 oldd=d;
UINT64 olde=e;
for (UINT64 j=0; j <80; j++)
{
if (j <16)
{
w[j]=pBlks[i+j];
}
else
{
w[j]=rol(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);
}
UINT64 t=add(add(rol(a,5),ft(j,b,c,d)),add(add(e,w[j]),kt(j)));
e=d;
d=c;
c=rol(b,30);
b=a;
a=t;
}
a=add(a,olda);
b=add(b,oldb);
c=add(c,oldc);
d=add(d,oldd);
e=add(e,olde);
}
Uint64ToHexStr(a, pOut, nOutLen);
Uint64ToHexStr(b, pOut+8, nOutLen-8);
Uint64ToHexStr(c, pOut+16, nOutLen-16);
Uint64ToHexStr(d, pOut+24, nOutLen-24);
Uint64ToHexStr(e, pOut+32, nOutLen-32);
if (pBlks != NULL)
{
delete[] pBlks;
pBlks = NULL;
}
return pOut;
}
int main()
{
unsigned char input[]="abc";
char output[111];
memset(output,0,sizeof(output));
SHA1(input,output,111);
printf("%s\n%d\n",output,strlen(output));
return 0;
}
sha1加密算法
最新推荐文章于 2024-06-21 10:11:43 发布