程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> c語言實現SHA-1算法

c語言實現SHA-1算法

編輯:關於C語言

安全哈希算法(Secure Hash Algorithm)主要適用於數字簽名標准 (Digital Signature Standard DSS)裡面定義的數字簽名算法(Digital Signature Algorithm DSA)。對於長度小於2^64位的消息,SHA1會產生一個160位的消息摘要。當接收到消息的時候,這個消息摘要可以用來驗證數據的完整性。在傳輸的過程中,數據很可能會發生變化,那麼這時候就會產生不同的消息摘要。 SHA1有如下特性:不可以從消息摘要中復原信息;兩個不同的消息不會產生同樣的消息摘要。

算法實現的版本比較多,以下代碼來自:http://download.csdn.net/detail/zhangrulzu/2936159,代碼行數很少,但確實實現了想要的效果。

下載的SHA-1算法:

#include<stdio.h>  
void creat_w(unsigned char input[64],unsigned long w[80])  
{  
   int i,j;unsigned long temp,temp1;  
   for(i=0;i<16;i++)  
          {  
             j=4*i;  
             w[i]=((long)input[j])<<24 |((long)input[1+j])<<16|((long)input[2+j])<<8|((long)input[3+j])<<0;  
       
          }  
   for(i=16;i<80;i++)  
         {  
             w[i]=w[i-16]^w[i-14]^w[i-8]^w[i-3];  
             temp=w[i]<<1;  
             temp1=w[i]>>31;  
             w[i]=temp|temp1;  
       
         }  
}  
char ms_len(long a,char intput[64])  
{  
    unsigned long temp3,p1;  int i,j;  
    temp3=0;  
    p1=~(~temp3<<8);  
    for(i=0;i<4;i++)  
       {  
          j=8*i;  
          intput[63-i]=(char)((a&(p1<<j))>>j);  
       
       }  
       
}  
main()  
{  
   unsigned long H0=0x67452301,H1=0xefcdab89,H2=0x98badcfe,H3=0x10325476,H4=0xc3d2e1f0;  
   unsigned long A,B,C,D,E,temp,temp1,temp2,temp3,k,f;int i,flag;unsigned long w[80];  
   unsigned char input[64]; long x;int n;  
   printf("input message:\n");  
   scanf("%s",input);  
   n=strlen(input);  
   if(n<57)  
          {  
                 x=n*8;  
                 ms_len(x,input);  
                 if(n==56)  
                     for(i=n;i<60;i++)  
                     input[i]=0;  
                 else
                    {  
                     input[n]=128;  
                     for(i=n+1;i<60;i++)  
                     input[i]=0;  
                    }  
       
          }  
       
   creat_w(input,w);  
   /*for(i=0;i<80;i++) 
   printf("%lx,",w[i]);*/
   printf("\n");  
   A=H0;B=H1;C=H2;D=H3;E=H4;  
   for(i=0;i<80;i++)  
         {  
               flag=i/20;  
               switch(flag)  
                  {  
                   case 0: k=0x5a827999;f=(B&C)|(~B&D);break;  
                   case 1: k=0x6ed9eba1;f=B^C^D;break;  
                   case 2: k=0x8f1bbcdc;f=(B&C)|(B&D)|(C&D);break;  
                   case 3: k=0xca62c1d6;f=B^C^D;break;  
                  }  
               /*printf("%lx,%lx\n",k,f); */
               temp1=A<<5;  
               temp2=A>>27;  
               temp3=temp1|temp2;  
               temp=temp3+f+E+w[i]+k;  
               E=D;  
               D=C;  
       
               temp1=B<<30;  
               temp2=B>>2;  
               C=temp1|temp2;  
               B=A;  
               A=temp;  
       
               printf("%lx,%lx,%lx,%lx,%lx\n",A,B,C,D,E);  
         }  
   H0=H0+A;  
   H1=H1+B;  
   H2=H2+C;  
   H3=H3+D;  
   H4=H4+E;  
   printf("\noutput hash value:\n");  
   printf("%lx,%lx,%lx,%lx,%lx",H0,H1,H2,H3,H4);  
   getch();  
}

這裡對算法驗證過程做一個記錄說明:

Visual Studio 2005,文件》新建》項目》Visual c++》Win32控制台應用程序,輸入項目名稱“SHA1”,完成;

把下載的代碼貼到SHA1.cpp文件末尾,復制“int _tmain(int argc, _TCHAR* argv[])”,刪除_tmain函數,替換“main()”;

編譯代碼,提示以下錯誤:

錯誤2error C3861: “strlen”: 找不到標識符e:\devlop\sha1\sha1\sha1.cpp 43

錯誤3error C2664: “ms_len”: 不能將參數 2 從“unsigned char [64]”轉換為“char []”e:\devlop\sha1\sha1\sha1.cpp 47

錯誤4error C3861: “getch”: 找不到標識符e:\devlop\sha1\sha1\sha1.cpp 98

第一條是警告,可以不處理

警告1warning C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.e:\devlop\sha1\sha1\sha1.cpp 42

雙擊錯誤2,定位到錯誤位置,在“strlen"上單擊鼠標右鍵》Refactor》Add Include,如下圖:

如果沒有這一項,那應該是沒有安裝VC助手的原因;

雙擊錯誤3,定位到錯誤位置,在變量input前加(char*)強制轉換;

雙擊錯誤4,定位到錯誤位置,在“getch"上單擊鼠標右鍵》Refactor》Add Include;

按F6鍵編譯項目,發現還有錯誤:

錯誤2error C2664: “strlen”: 不能將參數 1 從“unsigned char [64]”轉換為“const char *”e:\devlop\sha1\sha1\sha1.cpp 45

雙擊錯誤2,定位到錯誤位置,在input前加(LPSTR)強制轉換,編譯,還有錯誤:

錯誤2error C2065: “LPSTR”: 未聲明的標識符e:\devlop\sha1\sha1\sha1.cpp 45

錯誤3error C2146: 語法錯誤 : 缺少“)”(在標識符“input”的前面)e:\devlop\sha1\sha1\sha1.cpp 45

錯誤4error C2059: 語法錯誤 : “)”e:\devlop\sha1\sha1\sha1.cpp 45

還是找不到標識符,方法一樣:在“LPSTR"上單擊鼠標右鍵》Refactor》Add Include;

再編譯,又報錯:

錯誤4error C4716: “ms_len”: 必須返回一個值e:\devlop\sha1\sha1\sha1.cpp 38

定位到錯誤位置,仔細看了一下,這個函數的返回值應該沒什麼用,隨便返回一個:return '0';

再編譯,OK,終於生成成功了!

F5調試,輸入:abcd,回車,哦,輸出了好多東東,查看代碼的輸出調用,

找到92行應該沒用,注釋://printf("%lx,%lx,%lx,%lx,%lx\n",A,B,C,D,E);//輸出編碼過程,

最後得到的SHA1哈希值中還有逗號,找到100行,將printf("%lx,%lx,%lx,%lx,%lx",H0,H1,H2,H3,H4);格式化字符串中的逗號去掉;

再編譯,F5調試,輸入:abcd,回車,結果如下圖:

得到的結果對不對呢,找到一個在線SHA1加密工具,輸入abcd,結果如下:

對比一下,OK,結果一至。

修改後的SHA-1算法:

// SHA1.cpp : 定義控制台應用程序的入口點。  
//  
#include "stdafx.h"  
#include<stdio.h>  
#include <string.h>  
#include <conio.h>  
#include <wtypes.h>  
void creat_w(unsigned char input[64],unsigned long w[80])  
{  
   int i,j;unsigned long temp,temp1;  
   for(i=0;i<16;i++)  
          {  
             j=4*i;  
             w[i]=((long)input[j])<<24 |((long)input[1+j])<<16|((long)input[2+j])<<8|((long)input[3+j])<<0;  
    
          }  
   for(i=16;i<80;i++)  
         {  
             w[i]=w[i-16]^w[i-14]^w[i-8]^w[i-3];  
             temp=w[i]<<1;  
             temp1=w[i]>>31;  
             w[i]=temp|temp1;  
    
         }  
}  
char ms_len(long a,char intput[64])  
{  
    unsigned long temp3,p1;  int i,j;  
    temp3=0;  
    p1=~(~temp3<<8);  
    for(i=0;i<4;i++)  
       {  
          j=8*i;  
          intput[63-i]=(char)((a&(p1<<j))>>j);  
    
       }  
    return '0';  
}  
int _tmain(int argc, _TCHAR* argv[])  
{  
   unsigned long H0=0x67452301,H1=0xefcdab89,H2=0x98badcfe,H3=0x10325476,H4=0xc3d2e1f0;  
   unsigned long A,B,C,D,E,temp,temp1,temp2,temp3,k,f;int i,flag;unsigned long w[80];  
   unsigned char input[64]; long x;int n;  
   printf("input message:\n");  
   scanf("%s",input);  
   n=strlen((LPSTR)input);  
   if(n<57)  
          {  
                 x=n*8;  
                 ms_len(x,(char*)input);  
                 if(n==56)  
                     for(i=n;i<60;i++)  
                     input[i]=0;  
                 else
                    {  
                     input[n]=128;  
                     for(i=n+1;i<60;i++)  
                     input[i]=0;  
                    }  
    

          }  
    
   creat_w(input,w);  
   /*for(i=0;i<80;i++) 
   printf("%lx,",w[i]);*/
   printf("\n");  
   A=H0;B=H1;C=H2;D=H3;E=H4;  
   for(i=0;i<80;i++)  
         {  
               flag=i/20;  
               switch(flag)  
                  {  
                   case 0: k=0x5a827999;f=(B&C)|(~B&D);break;  
                   case 1: k=0x6ed9eba1;f=B^C^D;break;  
                   case 2: k=0x8f1bbcdc;f=(B&C)|(B&D)|(C&D);break;  
                   case 3: k=0xca62c1d6;f=B^C^D;break;  
                  }  
               /*printf("%lx,%lx\n",k,f); */
               temp1=A<<5;  
               temp2=A>>27;  
               temp3=temp1|temp2;  
               temp=temp3+f+E+w[i]+k;  
               E=D;  
               D=C;  
    
               temp1=B<<30;  
               temp2=B>>2;  
               C=temp1|temp2;  
               B=A;  
               A=temp;  
    
               //printf("%lx,%lx,%lx,%lx,%lx\n",A,B,C,D,E);//輸出編碼過程  
         }  
   H0=H0+A;  
   H1=H1+B;  
   H2=H2+C;  
   H3=H3+D;  
   H4=H4+E;  
   printf("\noutput hash value:\n");  
   printf("%lx%lx%lx%lx%lx",H0,H1,H2,H3,H4);  
   getch();  
}

修改後項目源碼下載:http://download.csdn.net/detail/testcs_dn/7344003

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved