可遇不可求的事:故乡的云,上古的玉,随手的诗,十九岁的你。
DES
DES是 Data Encryption Standard(数据加密标准)的缩写。DES是一个分组加密算法,他以64位为分组对数据加密。同时DES也是一个 对称算法:加密和解密用的是同一个算法。它的密匙长度是56位(因为每个第8位都用作奇偶校验),密匙可以是任意的56位的数,而且可以任意时候改变。其中有极少量的数被认为是弱密匙,但是很容易避开他们。所以保密性依赖于密钥。
DES对64(bit)位的明文分组M进行操作,M经过一个初始置换IP置换成m0,将m0明文分成左半部分和右半部分m0=(L0,R0),各32位长。然后进行16轮完全相同的运算,这些运算被称为函数f,在运算过程中数据与密匙结合。经过16轮后,左,右半部分合在一起经过一个末置换,这样就完成了。在每一轮中,密匙位移位,然后再从密匙的56位中选出48位。通过一个扩展置换将数据的右半部分扩展成48位,并通过一个异或操作替代成新的32位数据,在将其置换换一次。这四步运算构成了函数f。然后,通过另一个异或运算,函数f的输出与左半部分结合,其结果成为新的右半部分,原来的右半部分成为新的左半部分。将该操作重复16次,就实现了。
👨🦱🧥🗝😍🤛
解密过程:在经过所有的代替、置换、异或盒循环之后,你也许认为解密算法与加密算法完全不同。恰恰相反,经过精心选择的各种操作,获得了一个非常有用的性质:加密和解密使用相同的算法。 DES加密和解密唯一的不同是密匙的次序相反。 如果各轮加密密匙分别是K1,K2,K3….K16那么解密密匙就是K16,K15,K14…K1。
MD5
MD5的全称是Message-Digest Algorithm5,Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了" 字节串"而不是" 字符串"这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。MD5将任意长度的"字节串"变换成一个128bit的大整数, 并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。
👩🥼🪣👄
MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被"篡改"。举个例子,你将一段话写在一个叫wuai.txt 文件中,并对这个 wuai.txt 产生一个MD5的值并记录在案,然后你可以传这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的"抵赖", 这就是所谓的数字签名应用。
MD5还广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的,用户Login的时候,系统是把用户输入的密码计算成MD5值,然后再去和系统中保存的MD5值进行比较,而系统并不"知道"用户的密码是什么。
一些黑客破获这种密码的方法是一种被称为"跑字典"的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。 🧒🛏😶✋
即使假设密码的最大长度为8,同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是P(62,1)+P(62,2)....+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要TB级的磁盘组, 而且这种方法还有一个前提,就是能获得目标账户的密码MD5值的情况下才可以。
C++实现:
🧑🎤🦺📐💀🦴
全屏查看- #include<string>
- using namespace std;
- #define shift(x, n) (((x) << (n)) | ((x) >> (32-(n))))//右移的时候,高位一定要补零,而不是补充符号位
- #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
- #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))👩✈️💎🪣🤪✊
- #define H(x, y, z) ((x) ^ (y) ^ (z))
- #define I(x, y, z) ((y) ^ ((x) | (~z)))
- #define A 0x67452301
- #define B 0xefcdab89
- #define C 0x98badcfe🥼🖥🙌
- #define D 0x10325476
- //strBaye的长度
- unsigned int strlength;
- //A,B,C,D的临时变量
- unsigned int atemp;
🙌🌡🫖♑🪰 - unsigned int btemp;
- unsigned int ctemp;
- unsigned int dtemp;
- //常量ti unsigned int(abs(sin(i+1))*(2pow32))
- const unsigned int k[]={
👂⛄🥣❌🐴 - 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
- 0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
- 0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
- 0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
- 0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,👳🎒🩺🤑🙌
- 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
- 0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
- 0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
- 0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
- 0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,👠⌨😷🦴
- 0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
- 0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
- 0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};
- //向左位移数
- const unsigned int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
✍🌦🫑♀🦉 - 12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
- 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
- 15,21,6,10,15,21,6,10,15,21,6,10,15,21};
- const char str16[]="0123456789abcdef";
- void mainLoop(unsigned int M[])👩✈️👔📬☠🤌
- {
- unsigned int f,g;
- unsigned int a=atemp;
- unsigned int b=btemp;
- unsigned int c=ctemp;🧒🕶⚔😭🖕
- unsigned int d=dtemp;
- for (unsigned int i = 0; i < 64; i++)
- {
- if(i<16){
- f=F(b,c,d);
💪🚘🍍❌🐟 - g=i;
- }else if (i<32)
- {
- f=G(b,c,d);
- g=(5*i+1)%16;
🤟⛴🍚♂🐅 - }else if(i<48){
- f=H(b,c,d);
- g=(3*i+5)%16;
- }else{
- f=I(b,c,d);🥷🎒⚔🤔🤝
- g=(7*i)%16;
- }
- unsigned int tmp=d;
- d=c;
- c=b;👖✏💩💪
- b=b+shift((a+f+k<i>+M[g]),s<i>);
- a=tmp;
- }
- atemp=a+atemp;
- btemp=b+btemp;
🧑🚀👒⚔💀👂
- ctemp=c+ctemp;
- dtemp=d+dtemp;
- }
- /*
- *填充函数
👴🎒💾😭✋
- *处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
- *填充方式为先加一个1,其它位补零
- *最后加上64位的原来长度
- */
- unsigned int* add(string str)
🦷🏦🥩🉑🐠 - {
- unsigned int num=((str.length()+8)/64)+1;//以512位,64个字节为一组
- unsigned int *strByte=new unsigned int[num*16]; //64/4=16,所以有16个整数
- strlength=num*16;
- for (unsigned int i = 0; i < num*16; i++)
👮♂️🥼🩸🤔
- strByte<i>=0;
- for (unsigned int i=0; i <str.length(); i++)
- {
- strByte[i>>2]|=(str<i>)<<((i%4)*8);//一个整数存储四个字节,i>>2表示i/4 一个unsigned int对应4个字节,保存4个字符信息
- }
🤳🚈🍽🈚🦦 - strByte[str.length()>>2]|=0x80<<(((str.length()%4))*8);//尾部添加1 一个unsigned int保存4个字符信息,所以用128左移
- /*
- *添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
- */
- strByte[num*16-2]=str.length()*8;
👍🚗🥣🦬 - return strByte;
- }
- string changeHex(int a)
- {
- int b;
🤛🚗🍖🅱🦦 - string str1;
- string str="";
- for(int i=0;i<4;i++)
- {
- str1="";
🧠🌧🍍➡🐯 - b=((a>>i*8)%(1<<8))&0xff; //逆序处理每个字节
- for (int j = 0; j < 2; j++)
- {
- str1.insert(0,1,str16[b%16]);
- b=b/16;
🤛🌦🍽🅿🐅 - }
- str+=str1;
- }
- return str;
- }
👨🦱🧢📡😡💪
- string getMD5(string source)
- {
- atemp=A; //初始化
- btemp=B;
- ctemp=C;
🧠🧳🍍🆚🐂 - dtemp=D;
- unsigned int *strByte=add(source);
- for(unsigned int i=0;i<strlength/16;i+=16)
- {
- unsigned int num[16];🥼🏮🥰🖕
- for(unsigned int j=0;j<16;j++)
- num[j]=strByte[i*16+j];
- mainLoop(num);
- }
- return changeHex(atemp).append(changeHex(btemp)).append(changeHex(ctemp)).append(changeHex(dtemp));
👍🍓♏🐤 - }
- unsigned int main()
- {
- string ss;
- // cin>>ss;👨🚒👑📷🤮👂
- string s=getMD5("abc");
- cout<<s;
- return 0;
- }</i></i></i></i>
复制代码
🤞⛵🍌🈸🦉
|