SHA1消息摘要算法
前言:SHA消息摘要算法的学习笔记
什么是SHA-1消息摘要算法
Sha系列算法,又叫做安全散列算法,其包括 sha-1,sha-256,sha-384,sha-512总共这四种,分别产生160/256/384/512位的散列值,该算法与MD4算法设计原理相同,但安全性更高一些。
以sha-1为例,其会产生160位消息摘要,在对消息处理之前,初始散列值H用5个32位双子进行初始化,可以通过识别这些双字压缩常数来确定是否是该算法。
h0=> 67452301h h1=>efcdab89h h2=>98badcfeh h3=>10325476h h4=>c3d2e1f0h
SHA-1消息摘要算法的实现过程
SHA-1消息摘要算法代码实现
/*------------------------------------------------------- /* 《加密与解密》第三版 第7章 加密算法 /* MD5计算器源码 /* (c) www.PEDIY.com /* code by cnbragon 2007.9 -------------------------------------------------------*/ //////////////////////////////////////////////////////////////////// #include <stdio.h> #include <windows.h> typedef struct { unsigned int length[2]; unsigned int h[8]; unsigned int w[80]; } sha; #define H0 0x67452301L #define H1 0xefcdab89L #define H2 0x98badcfeL #define H3 0x10325476L #define H4 0xc3d2e1f0L #define K0 0x5a827999L #define K1 0x6ed9eba1L #define K2 0x8f1bbcdcL #define K3 0xca62c1d6L #define PAD 0x80 #define ZERO 0 /* functions */ #define S(n,x) (((x)<<n) | ((x)>>(32-n))) #define F0(x,y,z) ((x&y)|((~x)&z)) #define F1(x,y,z) (x^y^z) #define F2(x,y,z) ((x&y) | (x&z)|(y&z)) #define F3(x,y,z) (x^y^z) static void sha1_transform(sha *sh) { /* basic transformation step */ unsigned int a,b,c,d,e,temp; int t; for (t=16;t<80;t++) sh->w[t]=S(1,sh->w[t-3]^sh->w[t-8]^sh->w[t-14]^sh->w[t-16]); a=sh->h[0]; b=sh->h[1]; c=sh->h[2]; d=sh->h[3]; e=sh->h[4]; for (t=0;t<20;t++) { /* 20 times - mush it up */ temp=K0+F0(b,c,d)+S(5,a)+e+sh->w[t]; e=d; d=c; c=S(30,b); b=a; a=temp; } for (t=20;t<40;t++) { /* 20 more times - mush it up */ temp=K1+F1(b,c,d)+S(5,a)+e+sh->w[t]; e=d; d=c; c=S(30,b); b=a; a=temp; } for (t=40;t<60;t++) { /* 20 more times - mush it up */ temp=K2+F2(b,c,d)+S(5,a)+e+sh->w[t]; e=d; d=c; c=S(30,b); b=a; a=temp; } for (t=60;t<80;t++) { /* 20 more times - mush it up */ temp=K3+F3(b,c,d)+S(5,a)+e+sh->w[t]; e=d; d=c; c=S(30,b); b=a; a=temp; } sh->h[0]+=a; sh->h[1]+=b; sh->h[2]+=c; sh->h[3]+=d; sh->h[4]+=e; } void sha1_init(sha *sh) { /* re-initialise */ int i; for (i=0;i<80;i++) sh->w[i]=0L; sh->length[0]=sh->length[1]=0L; sh->h[0]=H0; sh->h[1]=H1; sh->h[2]=H2; sh->h[3]=H3; sh->h[4]=H4; } void sha1_process(sha * sh,int byte) { /* process the next message byte */ int cnt; cnt=(int)((sh->length[0]/32)%16); sh->w[cnt]<<=8; sh->w[cnt]|=(unsigned int)(byte&0xFF); sh->length[0]+=8; if (sh->length[0]==0L) { sh->length[1]++; sh->length[0]=0L; } if ((sh->length[0]%512)==0) sha1_transform(sh); } void sha1_hash(sha *sh, char hash[20]) { /* pad message and finish - supply digest */ int i; unsigned int len0,len1; len0=sh->length[0]; len1=sh->length[1]; sha1_process(sh,PAD); while ((sh->length[0]%512)!=448) sha1_process(sh,ZERO); sh->w[14]=len1; sh->w[15]=len0; sha1_transform(sh); for (i=0;i<20;i++) { /* convert to bytes */ hash[i]=((sh->h[i/4]>>(8*(3-i%4))) & 0xffL); } sha1_init(sh); } int main() { return 0; }
在逆向中识别SHA1系列算法的特征
第一个特征就是SHA1的初始化的五个常数,跟MD5_INIT一样,SHA1_INIT也是对要变换的常数进行初始化操作
IDA中的识别特征如下图所示
动态调试的特征如下图所示
同样的跟MD5_INIT一样,在transform的过程中也会对初始化的五个常数进行变换操作
IDA中的特征如下图所示
动态调试的特征如下图所示
其他SHA1系列算法的特征
SHA1题目
注册机代码如下
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <windows.h> #define MAXINPUTLEN 200 typedef struct { unsigned int length[2]; unsigned int h[8]; unsigned int w[80]; } sha; #define H0 0x67452301L #define H1 0xefcdab89L #define H2 0x98badcfeL #define H3 0x10325476L #define H4 0xc3d2e1f0L #define K0 0x5a827999L #define K1 0x6ed9eba1L #define K2 0x8f1bbcdcL #define K3 0xca62c1d6L #define PAD 0x80 #define ZERO 0 /* functions */ #define S(n,x) (((x)<<n) | ((x)>>(32-n))) #define F0(x,y,z) ((x&y)|((~x)&z)) #define F1(x,y,z) (x^y^z) #define F2(x,y,z) ((x&y) | (x&z)|(y&z)) #define F3(x,y,z) (x^y^z) static void sha1_transform(sha* sh) { /* basic transformation step */ // 在sha1加密中迭代的次数为80次 unsigned int a,b,c,d,e,temp; int t; for (t = 16; t < 80; t++) sh->w[t] = S(1, sh->w[t - 3] ^ sh->w[t - 8] ^ sh->w[t - 14] ^ sh->w[t - 16]); // 重新覆盖 sha1中默认初始化的常数 a = sh->h[0]; b = sh->h[1]; c = sh->h[2]; d = sh->h[3]; e = sh->h[4]; for (t=0;t<20;t++) { /* 20 times - mush it up */ temp=K0+F0(b,c,d)+S(5,a)+e+sh->w[t]; e=d; d=c; c=S(30,b); b=a; a=temp; } for (t=20;t<40;t++) { /* 20 more times - mush it up */ temp=K1+F1(b,c,d)+S(5,a)+e+sh->w[t]; e=d; d=c; c=S(30,b); b=a; a=temp; } for (t=40;t<60;t++) { /* 20 more times - mush it up */ temp=K2+F2(b,c,d)+S(5,a)+e+sh->w[t]; e=d; d=c; c=S(30,b); b=a; a=temp; } for (t=60;t<80;t++) { /* 20 more times - mush it up */ temp=K3+F3(b,c,d)+S(5,a)+e+sh->w[t]; e=d; d=c; c=S(30,b); b=a; a=temp; } // 重新覆盖 sha1中默认初始化的常数 sh->h[0]+=a; sh->h[1]+=b; sh->h[2]+=c; sh->h[3]+=d; sh->h[4]+=e; } void sha1_init(sha *sh) { /* re-initialise */ // 初始化5个常数 int i; for (i=0;i<80;i++) sh->w[i]=0L; sh->length[0] = sh->length[1] = 0L; // the same as md5 sh->h[0] = 0x67452301L; sh->h[1] = 0xefcdab89L; sh->h[2] = 0x98badcfeL; sh->h[3] = 0x10325476L; sh->h[4] = 0xc3d2e1f0L; } void sha1_process(sha* sh, int byte) { // 对每个字节都进行对应的操作如下的操作 int cnt; cnt = (int)((sh->length[0] / 32) % 16); sh->w[cnt] <<= 8; sh->w[cnt] |= (unsigned int)(byte & 0xFF); sh->length[0] += 8; if (sh->length[0] == 0L) { sh->length[1]++; sh->length[0] = 0L; } if ((sh->length[0] % 512) == 0) sha1_transform(sh); } void sha1_hash(sha* sh, char hash[20]) { /* pad message and finish - supply digest */ int i; unsigned int len0, len1; len0 = sh->length[0]; len1 = sh->length[1]; // 填充一次PAD,默认的PAD -> 0x80 sha1_process(sh, PAD); // 然后再把剩下的全部填充,填充数为0 while ((sh->length[0] % 512) != 448) sha1_process(sh, ZERO); sh->w[14] = len1; sh->w[15] = len0; // len0为 当前加密的长度*8 // 对默认初始化的五个常数进行变换 sha1_transform(sh); // 生成20个字节的SHA1 for (i=0;i<20;i++) { /* convert to bytes */ hash[i] = ((sh->h[i / 4] >> (8 * (3 - i % 4))) & 0xffL); } // 结束玩重新初始化常数 sha1_init(sh); } int main() { sha sh; DWORD i, k, q; TCHAR szName[MAXINPUTLEN] = "test"; TCHAR szHash[MAXINPUTLEN] = { 0 }; TCHAR szSNtemp[MAXINPUTLEN] = { 0 }; TCHAR szFinaEncodeData[41] = { 0 }; TCHAR szPediyForumBuffer[41] = { 0 }; TCHAR szPediyComForumBuffer[41] = { 0 }; sha1_init(&sh); // d033e22ae348aeb5660fc2140aec35850c4da997 for (i = 0; i<strlen(szName); i++) sha1_process(&sh, szName[i]); sha1_hash(&sh, szHash); strcpy(szPediyForumBuffer, "PEDIY Forum"); strcpy(szPediyComForumBuffer, "pediy.com"); // 前面填充17个字节 q = 12; for (i = 0;i<17;i++) { k = szPediyForumBuffer[i] ^ szHash[i]; szPediyForumBuffer[q++] = k; } // 最后填充三个字节 szPediyForumBuffer[q++] = szHash[17] ^ 0x70; szPediyForumBuffer[q++] = szHash[18] ^ 0x65; szPediyForumBuffer[q++] = szHash[19] ^ 0x64; k = strlen(szPediyForumBuffer) + 1; for (i = 0; i < 10;i++) szPediyForumBuffer[k + i] = szPediyForumBuffer[k + i] ^ szPediyForumBuffer[k + i + 10]; for (i = 0; i < 10; i++) { wsprintf((szSNtemp + i * 2), "%02X", (unsigned char)szPediyForumBuffer[k]); k++; } printf("final encode data -> %s\n", szSNtemp); return 0; }
标签:
数据结构和算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
2020-09-19 关于ZjDroid的脱壳