sha1釋義:安全哈希算法(Secure Hash Algorithm)主要適用於數字簽名標準 (Digital Signature Standard DSS)裏面定義的數字簽名算法(Digital Signature Algorithm DSA)。對於長度小於2^64位的消息,SHA1會產生一個160位的消息摘要。當接收到消息的時候,這個消息摘要可以用來驗證數據的完整性。在傳輸的過程中,數據很可能會發生變化,那麼這時候就會產生不同的消息摘要。
sha1特點:不可以從消息摘要中復原信息;兩個不同的消息不會產生同樣的消息摘要,所以可以用摘要來校驗信息是否正確
代碼如下所示:
/*
SHA1 算法產出的是160位的摘要 即 32 * 5長度
有五個字(這裏爲32位)
*/
#include <stdio.h>
#include <string.h>
#define EACH_HADLE_LEN 64//每次處理64字節
#define DWORD unsigned int
char cipher[40] = "\0";//32 * 5 32位表示 8個十六進制
typedef struct sha1_context
{
DWORD length;
DWORD hashRes[5];
unsigned char block[64];//64字節的塊
}sha1_context;
DWORD RoLeft(DWORD value,int index)
{
return (value << index) ^ (value >> (32 - index));
}
void SHA1Init(sha1_context *sha1)
{
if(!sha1){
printf("%s %d the pointer is null\n",__func__,__LINE__);
}
sha1->length = 0;
sha1->hashRes[0] = 0x67452301;//初始化H[0] H[1] H[2] H[3] H[4]
sha1->hashRes[1] = 0xefcdab89;
sha1->hashRes[2] = 0x98badcfe;
sha1->hashRes[3] = 0x10325476;
sha1->hashRes[4] = 0xc3d2e1f0;
}
void ProcessEachBlock(sha1_context *sha1)
{
DWORD a, b, c, d, e;//五個緩衝區
DWORD W[80];
DWORD temp;
int i, j;
if(!sha1){
printf("%s %d the pointer is null\n",__func__,__LINE__);
}
for (i = 0, j =0; j < 16; i += 4, j++) {//初始化W[0] ~ W[15]
W[j] = (sha1->block[i] << 24) | (sha1->block[i + 1] << 16) |
(sha1->block[i + 2] << 8) | (sha1->block[i + 3]);
//產生一個32位的字
}
for (i = 16; i < 80; i++) {//產生W[16] ~ W[79]
temp = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
W[i] = RoLeft(temp, 1);
}
//初始化a b c d e
a = sha1->hashRes[0];
b = sha1->hashRes[1];
c = sha1->hashRes[2];
d = sha1->hashRes[3];
e = sha1->hashRes[4];
for ( i = 0; i < 20; i++){//前20
temp = RoLeft(a, 5) + (((c ^ d) & b) ^ d) + e + W[i] + 0x5A827999;//產生新值
//循環賦值
e = d;
d = c;
c = RoLeft(b, 30);
b = a;
a = temp;
}
for (i = 20; i < 40; i++){
temp = RoLeft(a, 5) + (b ^ c ^ d) + e + W[i] + 0x6ED9EBA1;//產生新值
//循環賦值
e = d;
d = c;
c = RoLeft(b, 30);
b = a;
a = temp;
}
for (i = 40; i < 60; i++){
temp = RoLeft(a, 5) + ((b & c) | (b & d) | (c & d)) + e + W[i] + 0x8F1BBCDC;//產生新值
//循環賦值
e = d;
d = c;
c = RoLeft(b, 30);
b = a;
a = temp;
}
for (i = 60; i < 80; i++){
temp = RoLeft(a, 5) + (b ^ c ^ d) + e + W[i] + 0xCA62C1D6;//產生新值
//循環賦值
e = d;
d = c;
c = RoLeft(b, 30);
b = a;
a = temp;
}
//獲得新的hash值
sha1->hashRes[0] += a;
sha1->hashRes[1] += b;
sha1->hashRes[2] += c;
sha1->hashRes[3] += d;
sha1->hashRes[4] += e;
}
//每次處理512bit 即是處理64字節
void SHA1Update(sha1_context *sha1,char *data)
{
int i = 0;
if(!sha1 || !data){
printf("%s %d the pointer is null\n",__func__,__LINE__);
}
sha1->length += strlen(data);
while (sha1->length >= EACH_HADLE_LEN ){
memcpy(sha1->block, data, EACH_HADLE_LEN);//獲得M[i]
ProcessEachBlock(sha1);
data += EACH_HADLE_LEN;//移動到下一個塊
sha1->length -= EACH_HADLE_LEN;//減去相應的長度
}
//對最後進行一輪進行一些補位操作 這裏先清空 這樣就可以不需要填0操作
memset(sha1->block, 0, sizeof(char) * EACH_HADLE_LEN);
memcpy(sha1->block, data, sha1->length);//剩餘的數據進行填充
sha1->block[sha1->length] = 0x80;//最高位填充1
unsigned long long bitLen = sha1->length << 3;//獲得bit長度 從而填充最後64bit位
memcpy(&(sha1->block[56]), &bitLen, sizeof(unsigned long long));
//直接copy內存的話 因爲內存是小端序的所以非常方便 學到了!
for (i = 0; i < 4; i++) {//這裏注意要顛倒
DWORD temp = sha1->block[56+i];
sha1->block[56+i] = sha1->block[63 - i];
sha1->block[63 - i] = temp;
}
ProcessEachBlock(sha1);//最後一次運算
}
void PrintSHA1(sha1_context *sha1)
{
int i;
char hashValue[9];
if(!sha1){
printf("%s %d the pointer is null\n",__func__,__LINE__);
}
printf("\nresult of the SHA - 1 is : ");
for (i = 0; i < 5; i++) {
memset(hashValue, 0, 9 * sizeof(char));
sprintf(hashValue, "%08x", sha1->hashRes[i]);//得到8個十六進制
printf("%s", hashValue);
}
}
void SHA1Encrypt(char *data)//傳入要加密的數據
{
sha1_context sha1 = {0};
SHA1Init(&sha1);//初始化長度
SHA1Update(&sha1, data);//產生40字節的hash值
PrintSHA1(&sha1);
}
int main()
{
char data[] = "message digest";
SHA1Encrypt(data);
}