RSA 公钥加密算法是 1977 年由 Ron Rivest、Adi Shamirh 和 Leonard Adleman 在(美国麻省理工学院)开发的。RSA 取名来自开发他们三者的名字。
RSA 算法基于一个十分简单的 数论事实 :将两个大素数相乘十分容易,但想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
RSA 算法是一种 非对称密码 算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。
下面我们就详细讲解下 RSA 算法加解密过程。
由于理论太枯燥,我们来举个实际例子运行一遍这个算法。
在 RSA 算法中,加密过程实际上就是利用公钥 (e,n) 计算 C=Me(mod n)。假设原文 M=6,代入上面的值,得到 C=61213(mod 9991)=7863。 于是 C=7863,Alice 就把 7863 发给了 Bob。
Bob 收到了密文 C=7863,就用自己的私钥 (d,n)=(4117,9991) 进行解密。RSA 证明,原文的 e 次方对 n 取模恒等于 c 的 d 次方,即 Cd≡Me(mod n) 一定成立,所以 M=Cdmod n。代入 C,d,n 的值,得到 M=78634117mod 9991=6。
所以 Bob 就从密文 C 和私钥 (d,n)=(4117,9991) 知道了加密之前的原文 M=6。
在整个通信过程 Alice 只用到了公钥 (e,n) 进行加密,Bob 只用到了私钥 (d,n) 解密,没有任何关于秘钥的传递,只有加密后的密文 C 有可能在通信中被窃听到。
回顾上面的加密过程,我们用到了六个变量: p,q,n,φ(n),e,d,其中只有公钥 (e,n) 是公开的。想要破解密文,只要知道私钥 (d,n),计算 M=Cdmod n 就可以破解 RSA 算法。
那么,有没有可能在已知公钥 (e,n) 的情况下,推导出私钥 (d,n)?
根据 RSA 构造的规则(见上述 RSA 加密过程 1-6 步),可以得到以下信息:
结论:如果 n 可以被因数分解,d 就可以沿着 4,3,2,1 步骤推出,也就意味着私钥被破解。
但是 大整数的质因数分解 ,是一件非常困难的事情。目前,除了暴力破解,还没有发现别的有效方法。
RSA 项目 源码 如下所示:
- /********************************************************************************************
- * Copyright(c) tcpipstack
- * File Name : RSA.c
- * Abstract Description : RSA 加解密算法的简单演示
- * Create Date : 9999/01/01
- * Author : tcpipstack
- *-------------------------Revision History--------------------------------------------------
- * No Version Date Revised By Item Description
- * 1 1.0 10/08/17
- *
- ********************************************************************************************/
-
- #include <stdio.h>
- #include <math.h>
-
- /* RSA 算法中加密方公布的密钥是 N 和 E,解密方使用 N 和 D 解密 */
- #define P 5 /* P 和 Q 必须为素数,在实际运用中通常为很大的数 */
- #define Q 7
-
- #define N (P*Q) /* add the (), or will cause the mistake */
- #define Z ((P - 1)*(Q - 1))
-
- #define E 5 /* 加密方选择 E,E 必须和 Z 只有一个公约数 */
- #define D 5 /* (E * D - 1) 必须能够被 Z 整除 */
- /* 由于 long int 无法表示过大的数字,所以 D 取 5 */
-
- void main(void)
- {
- int i;
- int TrsMsg[4] = {12, 15, 22, 5};
- long en[4], de[4];
- int SecCode[4], DeMsg[4];
-
- printf("下面是一个 RSA 加解密算法的简单演示:\n");
- printf("\t Copyright(C) Long.Luo.\n\n");
- printf("报文\t 加密\t 加密后密文\n");
-
- for (i=0; i<4; i++)
- {
- /* s = m(E) mod N */
- en[i] = (int)pow(TrsMsg[i], E);
- SecCode[i] = en[i] % N;
-
- printf("%d\t%d\t\t%d\n", TrsMsg[i], en[i], SecCode[i]);
- }
-
- printf("\n 原始报文\t 密文\t 加密\t\t 解密报文\n");
- for (i=0; i<4; i++)
- {
- /* d = s(D) mod N */
- de[i] = pow(SecCode[i], D);
- DeMsg[i] = de[i] % N;
-
- printf("%d\t\t%d\t%d\t\t%d\n", TrsMsg[i], SecCode[i], de[i], DeMsg[i]);
- }
-
- getchar();
- }
输出结果如下所示:
- 下面是一个 RSA 加解密算法的简单演示:
- Copyright(C) Long.Luo.
-
- 报文 加密 加密后密文
- 12 248832 17
- 15 759375 15
- 22 5153632 22
- 5 3125 10
-
- 原始报文 密文 加密 解密报文
- 12 17 1419857 12
- 15 15 759375 15
- 22 22 5153632 22
- 5 10 100000 5
通过以上,我们就了解了 RSA 算法的原理及其实现。