假如有一天,Alice和Bob想要加密通讯,发信人找到一种非对称的加密算法RSA,并向你求助。
那么RSA原理如何,究竟如何进行一次基于RSA加密与解密呢?下面进行简单讲解。
目录

RSA名字由来
RSA名字是由三个开发者的姓名首字母组合而得来的,分别是Ron Rivest,Adi Shamir和Leonard Adleman。
代数引入
首先我们选取两个大素数p和q(不能太接近)并计算n=p*q
利用欧拉函数计算Φ(n)=(p-1)(q-1),选取一个合适的e,其中e满足:
1<e<Φ(n),gcd(e,Φ(n))=1(e与Φ(n)互素)
此时e与n便是我们的公钥
计算d使得e*d mod Φ(n) = 1
这里因为e与Φ(n)互素,再根据欧拉定理,符合条件的d必然存在
利用公式 计算得d
此时d与n便是我们的私钥
加密与解密(非对称)
M(明文)是我们要加密和传输的信息,C(密文)是我们由明文加密得到的字段
加密步骤:
解密步骤:
转化原理
其中,
引入了公式:
(2)(欧拉定理)
证明欧拉定理
若正整数 a , n 互质,则 ≡1(mod n) 其中 φ(n) 是欧拉函数,其值为1~n 中与 n 互质的数的个数。
不妨设X1,X2 ...... Xφn是1~n与n互质的数。
首先我们先来考虑一些数:a*X1,a*X2 ...... a*Xφn
这些数有如下两个性质:
(1)任意两个数模n余数一定不同:
反证法:若存在a*X1≡a*X2(mod n),则 n |(a*X1 - a*X2 ),而a,n互质且(X1 - X2)< n,所以n不可能整除( a*X1 - a*X2 ),也就是说不存在a*X1≡a*X2(mod n)。归纳法:对于任意的与n互质的Xi均成立。故得证。
那么因为有 φ(n) 个这样的数,Xi mod n(i=1~φ(n))所以就有 φ(n) 个不同的余数,并且都是模数自然是(0~n-1)。
(2)对于任意的a*Xi(mod n)都与n互质。这不难想,因为a与n互质这是欧拉函数的条件,Xi是(1~n)与n互质的数的集合中的元素。所以如果a*Xi做为分子,n做为分母,那么他们构成的显然就是一个最简分数,也就是aXi和n互质。接下来就可以用欧几里得算法:
因为:gcd(a*Xi,n)= 1
所以:gcd(a*Xi,n)= gcd(n,a*Xi%n)= 1
这样,我们把上面两个性质结合一下来说,a*X1(mod n),a*X2(mod n) ...... a*Xφn(mod n)构成了一个集合(性质1证明了所有元素的互异性),并且这些数是1~n与n互质的所有数构成的集合(性质1已说明)。由此,我们巧妙的发现了,集合{ a*X1(mod n),a*X2(mod n) ...... a*Xφn(mod n)}经过一定的排序后和集合{ X1,X2 ...... Xφn }一一对应。那么:a*X1(mod n)* a*X2(mod n)* ...... * a*Xφn(mod n)= X1 * X2 * ...... * Xφn 因此:我们可以写出以下式子:
a*X1 * a*X2 * ...... * a*Xφn ≡ X1 * X2 * ...... * Xφn (mod n),即:( -1)*X1 * X2 * ...... * Xφn ≡ 0 (mod n)
又因为X1 * X2 * ...... * Xφn与n互质,所以, ( -1)| n,那么
≡ 1(mod n)。欧拉定理得证。
证明费马小定理
对于质数p,任意整数a,均满足:≡a(mod p)
证明如下:
这个可以用欧拉定理来说明:首先,我们把这个式子做一个简单变换得:-1 * a ≡ a(mod p) 因为a ≡ a(mod p)恒成立,所以
-1 mod p == 1时费马小定理才成立,又因为p是质数,所以 φ(n) = n-1,所以根据欧拉定理:若a,p互质则
-1 mod p == 1成立。那么对于a,p不互质,因为p是质数,所以,a一定是倍数
≡ a ≡ 0(mod p)。综上所述,费马小定理成立,它算是欧拉定理的一个特例。

C++简单实现
测试数字较小时准确率较高
#include <iostream>
#include<algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
// e是公钥
// d是私钥
ll e, d, n;
ll gcd(ll a, ll b) //求最大公约数
{
ll c = 0;
if (a < b) swap(a, b);
c = b;
do
{
b = c;
c = a % b;
a = b;
} while (c != 0);
return b;
}
// 0不是 1是
ll isPrime(ll i) //判断i是否是素数
{
ll flag = 0;
for (ll a = 2; a < i; a++)
{
if (i % a == 0)
{
flag = 1;
break;
}
}
if (flag == 1) return 0;
else return 1;
}
ll myPow(ll a, ll b, ll n) //求a^b mod n
{
ll y;
/*使用二进制平方乘法计算 pow(a,b) % n*/
y = 1;
while (b != 0)
{
/*对于b中的每个1,累加y*/
if (b & 1)
y = (y * a) % n;
/*对于b中的每一位,计算a的平方*/
a = (a * a) % n;
/*准备b中的下一位*/
b = b >> 1;
}
return y;
}
void extgcd(ll a, ll b, ll& d, ll& x, ll& y)
{
if (!b)
{
d = a;
x = 1;
y = 0;
}
else
{
extgcd(b, a % b, d, y, x);
y -= x * (a / b);
}
}
ll ModularInverse(ll a, ll b) //获取(1/a)mod b的结果
{
ll d, x, y;
extgcd(a, b, d, x, y);
return d == 1 ? (x + b) % b : -1;
}
void KeyGeneration() //获取公钥密钥
{
ll p, q;
ll phi_n;
do
{
do
p = rand();
while (p % 2 == 0);
} while (!isPrime(p)); // 得到素数 p
do
{
do
q = rand();
while (q % 2 == 0);
} while (!isPrime(q)); // 得到素数q
n = p * q;
phi_n = (p - 1) * (q - 1);
do
e = rand() % (phi_n - 2) + 2; // 1 < e < phi_n
while (gcd(e, phi_n) != 1);
d = ModularInverse(e, phi_n);
}
// 一位一位地输出加密的结果
ll Encryption(ll value) //加密
{
ll cipher;
cipher = myPow(value, e, n);
cout << cipher;
return cipher;
}
// 一位一位地输出解 密的结果
void Decryption(ll value) //解密
{
ll decipher;
decipher = myPow(value, d, n);
cout << decipher;
}
int main()
{
ll num;
cout << "请输入要加密的明文数字,ctrl+c结束" << endl;
while (cin >> num) {
ll de;
cout << "输入的明文为" << num << endl;
KeyGeneration(); //获取公钥密钥
cout << "加密密钥:" << e << endl;
cout << "加密结果为:";
de = Encryption(num);
cout << "\n私钥为:" << d;
// cout<<"de="<<de<<endl;
cout << "\n解密结果";
Decryption(de);
cout << "\n-------------" << endl;
}
return 0;
}
关于RSA安全性及讨论
根据前面说到的RSA算法原理,RSA的破解方法可以是找到私钥d,或者找到n的两个质因数p和q,然后根据φ(n)和公钥求得d。RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理论上的证明,也并没有从理论上证明破译RSA的难度与大数分解难度等价。 因为没有证明破解RSA就一定需要做大数分解。 RSA算法的安全强度随着其密钥长度的增加而增加,因此现在加密所采用的n一般在2048位二进制数。
RSA是一种非对称加密算法,基于欧拉定理和费马小定理。它涉及到两个大素数p和q的乘积n以及欧拉函数Φ(n),通过选取互素的e和计算d来形成公钥和私钥。加密过程是将明文用公钥e加密成密文,解密则是用私钥d对密文进行解密。RSA的安全性依赖于大数分解的难度,目前广泛用于网络安全领域。
7324

被折叠的 条评论
为什么被折叠?



