#include "stdio.h"
void getHex(long len,unsigned char* tmplen); //取长度填充64bit
void encode(FILE *fp_read,unsigned char *pad,unsigned char *final,int padlen);
//sha1读取文件并进行摘要,结果放在final里
void encode1(int l,unsigned char* len,unsigned char* final,int padlen,unsigned char*str);//sha1字符串的摘要,结果放在final里
void encode2(int l,unsigned char* len,unsigned char* final,int padlen,unsigned char* str);//sha256的字符串hash
void encode3(FILE *fp_read,unsigned char* len,unsigned char* final,int padlen);//sha256的文件hash
void wordXOR(unsigned char* result,unsigned char* paraA,unsigned char* paraB); //字异或
void wordADD(unsigned char* result,unsigned char* paraA,unsigned char* paraB); //字模32位加
void wordAND(unsigned char* result,unsigned char* paraA,unsigned char* paraB); //字与
void wordOR(unsigned char* result,unsigned char* paraA,unsigned char* paraB); //字或
void wordROTL(unsigned char* result,unsigned char* paraA,int s); //循环左移
void wordROTR(unsigned char* result,unsigned char* paraA,int s); //循环右移
void wordSHR(unsigned char* result,unsigned char* w,int s);//字右移s位
void wordFILL(unsigned char* result,unsigned char* paraA); //字取反
void wordCOPY(unsigned char* source,unsigned char* dest); //字复制
void ft(unsigned char* paraB,unsigned char* paraC,unsigned char* paraD,int t,unsigned char* tmpT); //ft函数
void Maj(unsigned char* tmpT,unsigned char* paraE,unsigned char* paraF,unsigned char* paraG);//256中的Maj函数
void CH(unsigned char* tmpT,unsigned char* paraE,unsigned char* paraF,unsigned char* paraG);//256中的CH函数
void sigma(unsigned char* result,unsigned char* w,int i);//256中的sigma函数
void s(unsigned char* result,unsigned char* w,int i);//256中的s函数
void T1(unsigned char* tmpT,unsigned char* E,unsigned char* F,unsigned char *G,unsigned char* K,unsigned char* W,unsigned char* H);//T1函数
void T2(unsigned char* tmpT,unsigned char *A,unsigned char *B,unsigned char *C);//T2函数
void BINARYTOCHAR(unsigned char* final,unsigned char* result); //输出显示
void main()
{
int t,q;
printf(" SHA-1 and SHA-256 Message Digest ");
printf(" 2007122005彭尼敏 \n");
printf("1.SHA-1\n");
printf("2.SHA-256\n");
printf("请选择:\n");
scanf("%d",&t);
printf("1.字符串输入\n");
printf("2.文件输入\n");
printf("请选择:\n");
scanf("%d",&q);
if (t==1&&q==1)//sha1的字符串hash
{
char str[64],len[64],final[160],tmpWord[2];
char result[500],ch;
long lFileLen; //文件长度
int padlen,i,l; //填充长度
printf("输入字符串:");
scanf("%s",str);
l=strlen(str);
lFileLen=8*l; //是总共的位数
printf("输入内容长度:%ld bit\n",lFileLen);
padlen=(448-lFileLen)%512; //取得padding0的长度
if(padlen<0) //padlen>512
padlen+=512;
getHex(lFileLen,len); //取填充长度64bit
encode1(l,len,final,padlen,str);
BINARYTOCHAR(final,result); //转换摘要为ASCII字符并显示输出
printf("%s\n",result); //打印
}
else if(t==2&&q==1)//sha256的字符串hash
{
char str[64],len[64],final[160],tmpWord[2];
char result[500],ch;
long lFileLen; //文件长度
int padlen,i,l; //填充长度
printf("输入字符串:");
scanf("%s",str);
l=strlen(str);
lFileLen=8*l; //是总共的位数
printf("输入内容长度:%ld bit\n",lFileLen);
padlen=(448-lFileLen)%512; //取得padding0的长度
if(padlen<0) //padlen>512
padlen+=512;
getHex(lFileLen,len); //取填充长度64bit
encode2(l,len,final,padlen,str);
BINARYTOCHAR(final,result); //转换摘要为ASCII字符并显示输出
printf("%s\n",result); //打印
}
else if(t==2&&q==2) //sha256的文件hash
{
FILE *fp_read; //定义两个文件指针
char strRead[100],len[64],final[160],tmpWord[2]; //输入文件的名字,final的长度
char result[500],ch;
long lFileLen; //文件长度
int padlen,i,l; //填充长度
printf("Please enter the path of Text:");
scanf("%s",strRead);
fp_read=fopen(strRead,"rb"); //为读写打开一个二进制文件
if(fp_read==NULL) //"r+方式该文件应该已经存在,以便能输入数据"
{
printf("Open file %s Error!\n",strRead);
return;
}
ch=fgetc(fp_read);
l=0;
while(ch!=EOF)
{
l++;
ch=fgetc(fp_read);
}
lFileLen=8*l; //是总共的位数
printf("输入内容长度:%ld bit\n",lFileLen);
padlen=(448-lFileLen)%512; //取得padding0的长度
if(padlen<0) //padlen>512
padlen+=512;
getHex(lFileLen,len); //取填充长度64bit
fseek(fp_read,0L,SEEK_SET); //指向文件开始位置
encode3(fp_read,len,final,padlen); //摘要函数
BINARYTOCHAR(final,result); //转换摘要为ASCII字符并显示输出
printf("%s\n",result); //打印
fclose(fp_read);
}
else //sha1的文件hash
{
FILE *fp_read; //定义两个文件指针
char strRead[100],len[64],final[160],tmpWord[2]; //输入文件的名字,final的长度
char result[500],ch;
long lFileLen; //文件长度
int padlen,i,l; //填充长度
printf("Please enter the path of Text:");
scanf("%s",strRead);
fp_read=fopen(strRead,"rb"); //为读写打开一个二进制文件
if(fp_read==NULL) //"r+方式该文件应该已经存在,以便能输入数据"
{
printf("Open file %s Error!\n",strRead);
return;
}
ch=fgetc(fp_read);
l=0;
while(ch!=EOF)
{
l++;
ch=fgetc(fp_read);
}
lFileLen=8*l; //是总共的位数
printf("输入内容长度:%ld bit\n",lFileLen);
padlen=(448-lFileLen)%512; //取得padding0的长度
if(padlen<0) //padlen>512
padlen+=512;
getHex(lFileLen,len); //取填充长度64bit
fseek(fp_read,0L,SEEK_SET); //指向文件开始位置
encode(fp_read,len,final,padlen); //摘要函数
BINARYTOCHAR(final,result); //转换摘要为ASCII字符并显示输出
printf("%s\n",result); //打印
fclose(fp_read);
}
}
wordADD(tmpT,tmpH[0],tmpA);
wordCOPY(tmpT,tmpH[0]);
wordADD(tmpT,tmpH[1],tmpB);
wordCOPY(tmpT,tmpH[1]);
wordADD(tmpT,tmpH[2],tmpC);
wordCOPY(tmpT,tmpH[2]);
wordADD(tmpT,tmpH[3],tmpD);
wordCOPY(tmpT,tmpH[3]);
wordADD(tmpT,tmpH[4],tmpE);
wordCOPY(tmpT,tmpH[4]);
}
for(i=0;i<20;i++) //就是H0到H4的新值
final[i]=tmpH[i/4][i%4];
}
void getHex(long len,unsigned char* tmplen) //取填充长度64bit
{
int cur,i;
for(i=0;i<8;i++)
tmplen[i]=0x00; //初始化
cur=7;
while(len!=0)
{
if(len%256<0)
{
tmplen[cur--]=256+len%256;
}
else{
tmplen[cur--]=len%256;
}
len=len/256;
}
}
void wordROTL(unsigned char* result,unsigned char* paraA,int s) //循环左移s
{
int i;
unsigned char tmpResult[4];
if(s<8)
{
for(i=0;i<4;i++)
result[i]=paraA[i]<<s|paraA[(i+1)%4]>>(8-s); //左移s位
}
else{
wordROTL(tmpResult,paraA,7);
wordROTL(result,tmpResult,s-7);
}
}
void wordAND(char* result,char* paraA,char* paraB) //与运算right
{
int i;
for(i=0;i<4;i++)
result[i]=paraA[i]¶B[i];
}
void wordOR(char* result,char* paraA,char* paraB) //或运算right
{
int i;
for(i=0;i<4;i++)
result[i]=paraA[i]|paraB[i];
}
void wordXOR(char* result,char* paraA,char* paraB) //异或运算right
{
int i;
for(i=0;i<4;i++)
result[i]=paraA[i]^paraB[i];
}
void wordFILL(char* result,char* paraA) //取反 right
{
int i;
for(i=0;i<4;i++)
result[i]=~paraA[i];
}
void wordADD(unsigned char* result,unsigned char* paraA,unsigned char* paraB) //32位的操作系统模2加
{
unsigned char fix=0x00 ; //定义一个字符是16进制
int i;
for(i=3;i>=0;i--)
{
result[i]=paraA[i]+paraB[i]+fix;
if(paraA[i]+paraB[i]+fix>=256)
fix=0x01;
else
fix=0x00;
}
}
void wordCOPY(unsigned char* source,unsigned char* dest) //字复制将前面的内容复制到后面32位right
{
int i;
for(i=0;i<4;i++)
dest[i]=source[i];
}
void ft(unsigned char* paraB,unsigned char* paraC,unsigned char* paraD,int t,unsigned char* tmpT) //f的四个函数
{
unsigned char tmpI[4],tmpJ[4];
int i;
if(t<=19)
{
wordFILL(tmpT,paraB); //字取反将B的非装入tmpT 1
wordCOPY(tmpT,tmpI); //字复制 tmpT的东西复制到了tmpI 1
wordAND(tmpT,tmpI,paraD); //字与 B非和D相与得到的结果装入tmpT
wordCOPY(tmpT,tmpI); //字复制 tmpI=tmpT
wordAND(tmpJ,paraB,paraC); //字与B和C相与得到的结果装入tmpJ
wordOR(tmpT,tmpI,tmpJ); //字或tmpT=f1
}
else if(t<=39)
{
wordXOR(tmpI,paraB,paraC); //B和C异或
wordXOR(tmpT,tmpI,paraD); //B,C,D异或tmpT=f2
}
else if(t<=59)
{
wordAND(tmpI,paraB,paraC); //B和C相与
wordAND(tmpJ,paraB,paraD); //B和D相与
wordOR(tmpT,tmpI,tmpJ); //以上两个或
wordAND(tmpI,paraC,paraD); //C和D相与
wordOR(tmpJ,tmpI,tmpT); //以上的再或
wordCOPY(tmpJ,tmpT); //tmpT=tmpJ=f3
}
else if(t<=79)
{
wordXOR(tmpI,paraB,paraC); //同f2
wordXOR(tmpT,tmpI,paraD);
}
}
void BINARYTOCHAR(unsigned char* final,unsigned char* result) //将final文件的内容输入到result中显示出来
{
int iLow,iHigh,i,j; //定义了四个变量
for(i=0,j=0;i<20;i++)
{
iHigh=(final[i]&0xF0)>>4; //先与F0做与运算,然后再右移四位得到高位
iLow=final[i]&0x0F; //然后再与0F做与运算 得到低位
if(iHigh>9)
result[j++]=iHigh-9+0x40;
else
result[j++]=iHigh+0x30;
if(iLow>9)
result[j++]=iLow-9+0x40;
else
result[j++]=iLow+0x30;
}
result[j]='\0';
}