RSA 加解密算法
RSA 是一种非对称加密算法,广泛应用于安全通信、数字签名、证书生成等场景。它的安全性基于大数分解的难度。在RSA算法中,用户生成一对公钥和私钥。公钥用于加密,而私钥用于解密。
RSA 算法的基本步骤:
-
密钥生成:
- 选择两个大的质数 p p p 和 q q q。
- 计算 n = p × q n = p \times q n=p×q。
- 计算欧拉函数 ϕ ( n ) = ( p − 1 ) × ( q − 1 ) \phi(n) = (p-1) \times (q-1) ϕ(n)=(p−1)×(q−1)。
- 选择整数 e e e,使得 1 < e < ϕ ( n ) 1 < e < \phi(n) 1<e<ϕ(n) 且 e e e 和 ϕ ( n ) \phi(n) ϕ(n) 是互质的。
- 计算 d d d 作为 e e e 模 ϕ ( n ) \phi(n) ϕ(n) 的乘法逆元,即 d × e ≡ 1 m o d ϕ ( n ) d \times e \equiv 1 \mod \phi(n) d×e≡1modϕ(n)。
- 公钥为 ( e , n ) (e, n) (e,n),私钥为 ( d , n ) (d, n) (d,n)。
-
加密:
- 令 M M M 是明文信息。
- 计算密文 C C C 为 C ≡ M e m o d n C \equiv M^e \mod n C≡Memodn。
-
解密:
- 使用私钥 ( d , n ) (d, n) (d,n)。
- 计算 M ≡ C d m o d n M \equiv C^d \mod n M≡Cdmodn 来获取原始消息 M M M。
C++ 实现:
下面是一个简化的 C++ 实现来展示 RSA 算法的核心概念:
// 引入所需的头文件
#include <iostream> // 为了使用cout等C++标准输入输出功能
#include <cmath> // 为了使用数学函数
#include <vector> // 为了使用vector容器
#include <ctime> // 为了使用时间函数
#include <cstdlib> // 为了使用rand()和srand()
// 定义一个函数来计算 (a * b) % mod,避免大数溢出
long long modMultiply(long long a, long long b, long long mod) {
long long result = 0; // 初始化结果为0
a = a % mod; // 取模,确保a小于mod
while (b) { // 当b不为0时循环
if (b & 1) // 如果b是奇数
result = (result + a) % mod; // 更新结果
a = (a * 2) % mod; // 双倍增加a
b /= 2; // 将b减半
}
return result % mod; // 返回结果
}
// 定义一个函数来计算 (base^exponent) % mod
long long modPower(long long base, long long exponent, long long mod) {
long long result = 1; // 初始化结果为1
base = base % mod; // 取模,确保base小于mod
while (exponent) { // 当exponent不为0时循环
if (exponent & 1) // 如果exponent是奇数
result = modMultiply(result, base, mod); // 更新结果
exponent >>= 1; // 将exponent减半
base = modMultiply(base, base, mod); // 更新base的值
}
return result; // 返回结果
}
// 定义一个函数判断给定的数是否为素数
bool isPrime(long long n) {
if (n <= 1) // 如果n小于或等于1,返回false
return false;
if (n <= 3) // 如果n小于或等于3,返回true
return true;
if (n % 2 == 0 || n % 3 == 0) // 如果n能被2或3整除,返回false
return false;
for (long long i = 5; i * i <= n; i += 6) // 从5开始,每次增加6来检查n是否是素数
if (n % i == 0 || n % (i + 2) == 0) // 如果n能被i或i+2整除,返回false
return false;
return true; // 如果上述条件都不满足,返回true
}
// 定义一个函数来计算两个数的最大公约数
long long gcd(long long a, long long b) {
if (!b) // 如果b为0,返回a
return a;
return gcd(b, a % b); // 否则,递归调用自身
}
// 定义一个函数使用扩展欧几里得算法来求解ax + by = gcd(a, b)
long long extendedEuclid(long long a, long long b, long long &x, long long &y) {
if (b == 0) { // 如果b为0,基本情况
x = 1;
y = 0;
return a;
}
long long x1, y1;
long long gcd = extendedEuclid(b, a % b, x1, y1); // 递归调用
x = y1;
y = x1 - (a / b) * y1;
return gcd;
}
// 定义一个函数来计算给定整数a关于模m的模逆
long long modInverse(long long a, long long m) {
long long x, y;
long long g = extendedEuclid(a, m, x, y); // 使用扩展欧几里得算法
if (g != 1) // 如果gcd(a, m)不是1,那么逆不存在
return -1;
return (x % m + m) % m; // 返回模逆
}
// 主程序入口
int main() {
srand(time(NULL)); // 初始化随机数种子
long long p, q;
do {
p = rand() % 50 + 1; // 随机生成一个小于50的数,用于演示
} while (!isPrime(p)); // 保证p是素数
do {
q = rand() % 50 + 1; // 同上,为q做同样的处理
} while (!isPrime(q));
long long n = p * q; // 计算n = p * q
long long phi = (p - 1) * (q - 1); // 计算欧拉函数值phi
long long e;
do {
e = rand() % phi; // 生成一个随机数e
} while (gcd(e, phi) != 1); // 保证e和phi是互质的
long long d = modInverse(e, phi); // 计算模逆,也就是私钥d
// 输出公钥和私钥
std::cout << "Public Key (n, e): (" << n << ", " << e << ")" << std::endl;
std::cout << "Private Key (n, d): (" << n << ", " << d << ")" << std::endl;
long long message = rand() % n; // 随机生成一个消息
std::cout << "Original Message: " << message << std::endl;
// 使用公钥e进行加密
long long encryptedMessage = modPower(message, e, n);
std::cout << "Encrypted Message: " << encryptedMessage << std::endl;
// 使用私钥d进行解密
long long decryptedMessage = modPower(encryptedMessage, d, n);
std::cout << "Decrypted Message: " << decryptedMessage << std::endl;
return 0; // 结束程序
}
python 实现:
import random
def mod_power(base, exponent, mod):
"""计算 (base^exponent) % mod"""
result = 1
base = base % mod
while exponent > 0:
if exponent % 2:
result = (result * base) % mod
exponent >>= 1
base = (base * base) % mod
return result
def is_prime(n):
"""判断 n 是否为素数"""
if n <= 1:
return False
if n <= 3:
return True
if n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
def gcd(a, b):
"""计算最大公约数"""
while b:
a, b = b, a % b
return a
def extended_euclid(a, m):
"""使用扩展欧几里得算法来找到模逆"""
if m == 0:
return (1, 0)
x1, y1 = extended_euclid(m, a % m)
x, y = y1, x1 - (a // m) * y1
return x, y
def mod_inverse(a, m):
"""计算给定整数a关于模m的模逆"""
x, y = extended_euclid(a, m)
return (x % m + m) % m
def generate_keys():
"""生成 RSA 密钥对"""
p = q = 1
while not is_prime(p):
p = random.randint(2, 100) # 为了简化,这里选择的范围较小
while not is_prime(q) or q == p:
q = random.randint(2, 100)
n = p * q
phi = (p - 1) * (q - 1)
e = random.randint(2, phi)
while gcd(e, phi) != 1:
e = random.randint(2, phi)
d = mod_inverse(e, phi)
return ((e, n), (d, n))
def encrypt(message, pub_key):
"""使用公钥加密消息"""
e, n = pub_key
return mod_power(message, e, n)
def decrypt(ciphertext, priv_key):
"""使用私钥解密密文"""
d, n = priv_key
return mod_power(ciphertext, d, n)
if __name__ == "__main__":
public_key, private_key = generate_keys()
print("Public Key:", public_key)
print("Private Key:", private_key)
message = random.randint(2, public_key[1] - 1)
print("\nOriginal Message:", message)
encrypted_message = encrypt(message, public_key)
print("Encrypted Message:", encrypted_message)
decrypted_message = decrypt(encrypted_message, private_key)
print("Decrypted Message:", decrypted_message)
java 实现:
import java.math.BigInteger;
import java.util.Random;
public class RSA {
private BigInteger n, d, e;
private int bitlength = 1024;
private Random r;
public RSA() {
r = new Random();
BigInteger p = BigInteger.probablePrime(bitlength, r);
BigInteger q = BigInteger.probablePrime(bitlength, r);
n = p.multiply(q);
BigInteger m = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
e = BigInteger.probablePrime(bitlength / 2, r);
while (m.gcd(e).compareTo(BigInteger.ONE) > 0 && e.compareTo(m) < 0) {
e.add(BigInteger.ONE);
}
d = e.modInverse(m);
}
public RSA(BigInteger e, BigInteger d, BigInteger n) {
this.e = e;
this.d = d;
this.n = n;
}
public static void main(String[] args) {
RSA rsa = new RSA();
String testString = "Hello, RSA!";
System.out.println("Encrypting: " + testString);
byte[] encrypted = rsa.encrypt(testString.getBytes());
byte[] decrypted = rsa.decrypt(encrypted);
System.out.println("Decrypted: " + new String(decrypted));
}
public byte[] encrypt(byte[] message) {
return (new BigInteger(message)).modPow(e, n).toByteArray();
}
public byte[] decrypt(byte[] message) {
return (new BigInteger(message)).modPow(d, n).toByteArray();
}
}
总结:
RSA 是现代密码学中的一块基石。它的魅力在于它的数学基础和它的双密钥系统,使得加密和解密使用不同的密钥。尽管上面的实现是为了教学目的,并不适用于实际的加密任务,但它为理解 RSA 提供了一个很好的起点。
希望这篇博客可以帮助你理解 RSA 加密算法的基础概念和它的工作原理。喜欢的话给博主点个赞吧!谢谢!