常见的几种数据加密算法
提示:以下是正文内容,文章例子仅供参考
文章目录
数据加密概念
数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码为“密文”,使其只能在输入相应的密钥之后才能显示出原容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。 该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。
简单来说,就是把某一段数据(明文),按照“某种规则”转换成另外一段不可读的数(密文)。这里选定的“规则”,就是加密算法。理所当然,当别人拿到“密文”,解析出“明文”的难度取决于加密算法的破解难度。
一、加密算法的分类
常见的加密算法可以分成三类,对称加密算法,非对称加密算法和Hash算法。
1.对称加密
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。
亦指加密和解密使用相同密钥的加密算法。对称加密算法的优点在于加解密的高速度和使用长密钥时的难破解性。假设两个用户需要使用对称加密方法加密然后交换数据,则用户最少需要2个密钥并交换使用,如果企业内用户有n个,则整个企业共需要n×(n-1) 个密钥,密钥的生成和分发将成为企业信息部门的恶梦。对称加密算法的安全性取决于加密密钥的保存情况,但要求企业中每一个持有密钥的人都保守秘密是不可能的,他们通常会有意无意的把密钥泄漏出去——如果一个用户使用的密钥被入侵者所获得,入侵者便可以读取该用户密钥加密的所有文档,如果整个企业共用一个加密密钥,那整个企业文档的保密性便无从谈起。
常见的对称加密算法:DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES
2.非对称加密
指加密和解密使用不同密钥的加密算法,也称为公私钥加密。假设两个用户要加密交换数据,双方交换公钥,使用时一方用对方的公钥加密,另一方即可用自己的私钥解密。如果企业中有n个用户,企业需要生成n对密钥,并分发n个公钥。由于公钥是可以公开的,用户只要保管好自己的私钥即可,因此加密密钥的分发将变得十分简单。同时,由于每个用户的私钥是唯一的,其他用户除了可以可以通过信息发送者的公钥来验证信息的来源是否真实,还可以确保发送者无法否认曾发送过该信息。非对称加密的缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比非对称加密慢上1000倍。
常见的非对称加密算法:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)
3.Hash算法
Hash算法特别的地方在于它是一种单向算法,用户可以通过Hash算法对目标信息生成一段特定长度的唯一的Hash值,却不能通过这个Hash值重新获得目标信息。因此Hash算法常用在不可还原的密码存储、信息完整性校验等。
常见的Hash算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1
二、常见数据加密算法
1.对称加密算法之DES加密原理
加密的三个原则
混淆(confusion):使密文与密钥的关系尽可能复杂化,使得对手即使获取了许多明文和对应的密文,以及关于密文的一些统计特性,也无法推测密钥。
扩散(diffusion):让明文中的每一位影响密文中的许多位,或者说让密文中的每一位受明文中的许多位的影响。这样可以隐蔽明文的统计特性。当然,理想的情况是让明文中的每一位影响密文中的所有位,或者说让密文中的每一位受明文中所有位的影响。
分组(block cipher):可以看成经典的电报密码本加密技术的现代传承,其中由密钥来决定电报密码本的选择。一次加密一组数据,密钥长度为一组数据的长度。
加密的原理
DES(Data Encryption Standard)采用分组加密。使用64位的分组长度和56位的密钥长度,将64位的输入经过一系列变换得到64位的输出。DES算法利用多次组合替代算法和换位算法,通过混淆和扩散的相互作用,把明文编制成密码强度很高的密文。解密则使用了相同的步骤和相同的密钥。
DES的压缩、扩展和置换操作使其具有很强的雪崩效应。即输入明文或密钥中一个比特的变化会导致输出中至少一半比特的密文发生变化,这使得穷举试凑寻找其中规律变得不可能。
加密的特点
DES算法产生密钥的方式简单,密钥一般也比较短。
DES算法加密解密速度快,效率很高,适合对大数据量的数据进行加密。
DES算法的安全性依赖于密钥的高度保密,通信双方必须有方法能保证安全的分享密钥,并定期更换DES密钥。
DES算法的源代码如下
#include<stdio.h>
#include<string.h>
//#define gets_s gets //出现[Error] 'gets_s' was not declared in this scope的话就加上这句,默认使用的gcc编译器的话会出现此错误,因为gets_s是vs提供的函数
int IP_Table[64] = { //IP置换矩阵
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 };
int E_Table[48] = { //扩展矩阵
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 };
int P_Table[32] = { // P 盒
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 };
int IPR_Table[64] = { //逆IP置换矩阵
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 };
int PC1_Table[56] = { //密钥第一次置换矩阵
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 };
int PC2_Table[48] = { // 密钥第二次置换矩阵
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 };
int S_Box[8][4][16] = { //8个S盒 三维数组
// S1
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
// S2
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
// S3
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
// S4
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
// S5
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
// S6
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
// S7
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
// S8
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
};
static void CharToBit(const char input[], int output[], int bits)//把CHAR转换为INT
{
int i, j;
for (j = 0; j<8; j++)
{
for (i = 0; i<8; i++)
{
output[7 * (j + 1) - i + j] = (input[j] >> i) & 1;
}
}
};
static void BitToChar(const int intput[], char output[], int bits)//把INT转换为CHAR
{
int i, j;
for (j = 0; j<8; j++)
{
for (i = 0; i<8; i++)
{
output[j] = output[j] * 2 + intput[i + 8 * j];
}
}
};
static void Xor(int *INA, int *INB, int len)//异或操作
{
int i;
for (i = 0; i<len; i++)
{
*(INA + i) = *(INA + i) ^ *(INB + i);
}
};
static void IP(const int input[64], int output[64], int table[64])//初始IP置换
{
int i;
for (i = 0; i<64; i++)
{
output[i] = input[table[i] - 1];//减1操作不可少!!
}
};
static void E(const int input[32], int output[48], int table[48])//E扩展
{
int i;
for (i = 0; i<48; i++)
{
output[i] = input[table[i] - 1];
}
};
static void P(const int input[32], int output[32], int table[32])//P置换
{
int i;
for (i = 0; i<32; i++)
{
output[i] = input[table[i] - 1];
}
};
static void IP_In(const int input[64], int output[64], int table[64])//逆IP
{
int i;
for (i = 0; i<64; i++)
{
output[i] = input[table[i] - 1];
}
};
static void PC_1(const int input[64], int output[56], int table[56])//PC_1
{
int i;
for (i = 0; i<56; i++)
{
output[i] = input[table[i] - 1];
}
};
static void PC_2(const int input[56], int output[48], int table[48])//PC_2
{
int i;
for (i = 0; i<48; i++)
{
output[i] = input[table[i] - 1];
}
};
static void S(const int input[48], int output[32], int table[8][4][16])//S盒压缩
{
int i = 0;
int j = 0;
int INT[8];
for (; i<48; i = i + 6)
{
INT[j] = table[j][(input[i] << 1) + (input[i + 5])][(input[i + 1] << 3) + (input[i + 2] << 2) + (input[i + 3] << 1) + (input[i + 4])];
j++;
}
for (j = 0; j<8; j++)
{
for (i = 0; i<4; i++)
{
output[3 * (j + 1) - i + j] = (INT[j] >> i) & 1;
}
}
};
static void F_func(int input[32], int output[32], int subkey[48])//完成DES算法轮变换
{
int len = 48;
int temp[48] = { 0 };
int temp_1[32] = { 0 };
E(input, temp, E_Table);
Xor(temp, subkey, len);
S(temp, temp_1, S_Box);
P(temp_1, output, P_Table);
};
static void RotateL(const int input[28], int output[28], int leftCount)//秘钥循环左移
{
int i;
int len = 28;
for (i = 0; i<len; i++)
{
output[i] = input[(i + leftCount) % len];
}
};
static void subKey_fun(const int input[64], int Subkey[16][48])//子密钥生成
{
int loop = 1, loop_2 = 2;
int i, j;
int c[28], d[28];
int pc_1[56] = { 0 };
int pc_2[16][56] = { 0 };
int rotatel_c[16][28] = { 0 };
int rotatel_d[16][28] = { 0 };
PC_1(input, pc_1, PC1_Table);
for (i = 0; i<28; i++)
{
c[i] = pc_1[i];
d[i] = pc_1[i + 28];
}
int leftCount = 0;
for (i = 1; i<17; i++)
{
if (i == 1 || i == 2 || i == 9 || i == 16)
{
leftCount += loop;
RotateL(c, rotatel_c[i - 1], leftCount);
RotateL(d, rotatel_d[i - 1], leftCount);
}
else
{
leftCount += loop_2;
RotateL(c, rotatel_c[i - 1], leftCount);
RotateL(d, rotatel_d[i - 1], leftCount);
}
}
for (i = 0; i<16; i++)
{
for (j = 0; j<28; j++)
{
pc_2[i][j] = rotatel_c[i][j];
pc_2[i][j + 28] = rotatel_d[i][j];
}
}
for (i = 0; i<16; i++)
{
PC_2(pc_2[i], Subkey[i], PC2_Table);
}
};
static void DES_Efun(char input[8], char key_in[8], int output[64])
{
int Ip[64] = { 0 };//存储初始置换后的矩阵
int output_1[64] = { 0 };
int subkeys[16][48];
int chartobit[64] = { 0 };
int key[64];
int l[17][32], r[17][32];
CharToBit(input, chartobit, 8);//正确,转换为64个二进制数的操作正确!
IP(chartobit, Ip, IP_Table);//正确,IP初始置换!
CharToBit(key_in, key, 8);//正确!
subKey_fun(key, subkeys);//正确!
for (int i = 0; i<32; i++)
{
l[0][i] = Ip[i];
r[0][i] = Ip[32 + i];
}
for (int j = 1; j<16; j++)//前15轮的操作
{
for (int k = 0; k<32; k++)
{
l[j][k] = r[j - 1][k];
}
F_func(r[j - 1], r[j], subkeys[j - 1]);
Xor(r[j], l[j - 1], 32);
}
int t = 0;
for (t = 0; t<32; t++)//最后一轮的操作
{
r[16][t] = r[15][t];
}
F_func(r[15], l[16], subkeys[15]);
Xor(l[16], l[15], 32);
for (t = 0; t<32; t++)
{
output_1[t] = l[16][t];
output_1[32 + t] = r[16][t];
}
IP_In(output_1, output, IPR_Table);
};
static void DES_Dfun(int input[64], char key_in[8], char output[8])
{
int Ip[64] = { 0 };//存储初始置换后的矩阵
int output_1[64] = { 0 };
int output_2[64] = { 0 };
int subkeys[16][48];
int chartobit[64] = { 0 };
int key[64];
int l[17][32], r[17][32];
IP(input, Ip, IP_Table);//正确,IP初始置换!
CharToBit(key_in, key, 8);//正确!
subKey_fun(key, subkeys);//正确!
for (int i = 0; i<32; i++)
{
l[0][i] = Ip[i];
r[0][i] = Ip[32 + i];
}
for (int j = 1; j<16; j++)//前15轮的操作
{
for (int k = 0; k<32; k++)
{
l[j][k] = r[j - 1][k];
}
F_func(r[j - 1], r[j], subkeys[16 - j]);
Xor(r[j], l[j - 1], 32);
}
int t = 0;
for (t = 0; t<32; t++)//最后一轮的操作
{
r[16][t] = r[15][t];
}
F_func(r[15], l[16], subkeys[0]);
Xor(l[16], l[15], 32);
for (t = 0; t<32; t++)
{
output_1[t] = l[16][t];
output_1[32 + t] = r[16][t];
}
IP_In(output_1, output_2, IPR_Table);
BitToChar(output_2, output, 8);
};
int main()
{
int output[64] = { 0 };
char MIN[9] = { 0 };
char MI[9] = { 0 };
printf("请输入明文(8字节)\n");
gets_s(MIN);
printf("请输入秘钥(8字节)\n");
gets_s(MI);
DES_Efun(MIN, MI, output);
printf("密文如下:\n");
for (int i = 0; i<64; i++)
{
printf("%d", output[i]);
if ((i + 1) % 4 == 0)
printf("\n");
}
printf("\n");
for(int i=0;i<8;i++) MIN[i]='0';//评论区见到有人不服,没看懂函数就说删掉解密部分输出明文没变,那就在解密前加上个赋值,你再试试?
printf("解密功能\n");
DES_Dfun(output, MI, MIN);
printf("明文如下:\n");
for (int i = 0; i<8; i++)
{
printf("%c", MIN[i]);
}
printf("\n\n");
return 0;
}
值得注意:DES的压缩、扩展和置换操作使其具有很强的雪崩效应。即输入明文或密钥中一个比特的变化会导致输出中至少一半比特的密文发生变化,这使得穷举试凑寻找其中规律变得不可能。
2.非对称加密算法之RSA算法
加密的原理
RSA算法基于数论构造,其算法具体实现基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
加密的具体过程
1.公钥和私钥的产生
(1)任意选择两个大的质数(素数)p和q,p不等于q,计算N=pq
(2)根据欧拉函数,不大于N且与N互质的整数个数为(p-1)(q-1)
(3)选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)
(4)用以下这个公式计算d:d×e ≡ 1 (mod (p-1)(q-1))
(5)将p和q销毁后,(N,e)是公钥,(N,d)是私钥
2.加密消息
假设Bob想给Alice送一个消息,他知道Alice产生的公钥N和e
将原始信息分为多段,每一段(假定为n)分别用以下公式计算出c:
n ^e ≡ c (mod N)
将多个n计算出的多个c串在一起,就是密文,发送即可。
3.解密消息
Alice得到Bob的消息c后就可以利用她的密钥(N,d)来解码。她可以用以下这个公式来将c转换为n:
e ^d ≡ n (mod N)
得到n后,她可以将原来的信息m重新复原。
RSA算法的应用
1.加密少量数据
比起DES和其它对称算法来说,RSA的运算速度要慢得多。
实际使用时,RSA算法不用来加密消息,而是用来加密传输密钥,加密消息用对称算法,如DES。
2.实现数字签名
将RSA算法反向使用(私钥加密公钥解密),对消息摘要加密,可以实现数字签名的功能。
数字签名可以防止数据篡改、数据抵赖和数据伪造发生。
RSA算法的源代码如下:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int prime[1305];//存放素数
int p[10005];//用筛选法求素数
void PRIME(){
int i,i2,k;
for(i=0;i<=10000;i+=2)
p[i]=0;
for(i=1;i<=10000;i+=2)
p[i]=1;
p[2]=1;p[1]=0;
for(i=3;i<=100;i+=2){
if(p[i]==1){
i2=i+i;
k=i2+i;
while(k<=10000){
p[k]=0;
k+=i2;
}
}
}
prime[0]=1;
prime[1]=2;
for(i=3;i<=10000;i+=2)
if(p[i])
prime[++prime[0]]=i;
}
// 计算逆元素
__int64 mod(__int64 a,__int64 n){
return (a%n+n)%n;
}
void gcd(__int64 a,__int64 b,__int64 &d,__int64 &x,__int64 &y){
if(b==0)
{
d=a;
x=1;
y=0;
return;
}
gcd(b,a%b,d,y,x);
y-=x*(a/b);
}
//a-1 mod n
__int64 Inv(__int64 a,__int64 n){ // 计算逆元素
__int64 d,x,y;
gcd(a,n,d,x,y);
if(d==1)
return mod(x,n);
else
return -1;
}
//求两个数的最大公约数
__int64 GCD(__int64 n,__int64 m){
__int64 t,r;
if(n<m){
t=n;
n=m;
m=t;
}
while((r=n%m)!=0){
n=m;
m=r;
}
return m;
}
//x=a^b(mod n)
__int64 ModPow(__int64 a,__int64 b,__int64 n){
__int64 d=1,i=0;
while(b>=(1<<i)) i++;
for(--i;i>=0;--i){
d=d*d%n;
if(b&(1<<i))
d=d*a%n;
}
return d;
}
int main(){
__int64 i,e,d,n,st,ed,eula;
__int64 m,c,ans;
PRIME();
printf("素数的个数:%d\n",prime[0]);
printf("选择两个不同的素数(输入编号,空格隔开):\n");//47和71分别是第15个和20个
while(scanf("%I64d%I64d",&st,&ed)!=EOF){
printf("你选择的两个素数分别是:%d和%d\n",prime[st],prime[ed]);
n=prime[st]*prime[ed];
printf("计算得到N是%I64d\n",n);
//N的Eula数
eula=(prime[st]-1)*(prime[ed]-1);
//找一个与eula互质的数
for(i=2;i<eula;i++)
if(GCD(eula,i)==1){
e=i;
break;
}
//e=79;
//上面找到了公开密钥n--e
d=Inv(e,eula);
//上面找到了私密钥n--d
printf("生成公钥:(%I64d %I64d)\n",e,n);
//输出密钥
printf("生成私钥:(%I64d %I64d)\n",d,n);
//切忌加密的数要比n小
printf("请输入要加密的数(<N)\n");
scanf("%I64d",&m);
c=ModPow(m,e,n);
printf("通过计算%I64d^%I64d(mod %I64d)得到密文=%I64d\n",m,e,n,c);
ans=ModPow(c,d,n);
printf("通过计算%I64d^%I64d(mod %I64d)得到明文=%I64d\n",c,d,n,ans);
printf("素数的个数:%d\n",prime[0]);
printf("选择两个不同的素数(输入编号,空格隔开):\n");//47和71分别是第15个和20个
}
return 0;
}
3.Hash加密算法之MD5算法
MD5算法的原理
MD5码以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
MD5算法总结
MD5,是一种信息摘要算法。简单来说,就是把一段信息(明文),通过一种有损的方式压缩成定长的字符(32位密文)。因为这种压缩方式是会损失信息的,所以是无法还原出“明文”的。虽然无法从数学上破解MD5算法,但由于现在计算机具备强大的计算能力,还是可以通过“穷举法”破解该算法。如果想用该算法加密,还可以通过“加盐”的方式提高解密难度。该算法允许多传一个参数"salt",指定通过MD5加密的次数,这样是能够提高解密难度的。
MD5算法的应用场景
数字签名是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串类似于写在纸上的物理签名,用于鉴别数字信息的真伪,同时也是对信息的发送者身份真实性的一个有效证明。
数字签名是公钥加密技术与消息摘要技术的结合应用。
MD5算法的源代码如下:
#include<iostream>
#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 (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((int)0,(int)1,(char)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++)
{
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));
}
int main()
{
string ss;
cout<<"请输入字串:"<<endl;
cin>>ss;
string s=getMD5(ss);
cout<<s<<endl;
return 0;
}
总结
加密算法的效能通常可以按照算法本身的复杂程度、密钥长度(密钥越长越安全)、加解密速度等来衡量。上述的算法中,除了DES密钥长度不够、MD2速度较慢已逐渐被淘汰外,其他常见的算法仍在目前的加密系统产品中使用。
更多推荐
所有评论(0)