侧边栏壁纸
博主头像
Setyg的博客

当秋风染红落叶的时候,就是新生~

  • 累计撰写 86 篇文章
  • 累计创建 66 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

RSA非对称加密解密:原理、实现与应用

Setyg
2026-10-02 / 0 评论 / 0 点赞 / 2 阅读 / 0 字

RSA非对称加密解密:原理、实现与应用

引言:非对称加密是现代密码学的基石,而RSA算法是非对称加密中最具代表性的算法。与对称加密使用相同密钥进行加密解密不同,非对称加密使用一对密钥:公钥和私钥。公钥用于加密,私钥用于解密,或者私钥用于签名,公钥用于验证签名。

RSA算法由Ron Rivest、Adi Shamir和Leonard Adleman于1977年提出,至今仍在HTTPS、数字签名、加密通信等领域广泛应用。

一、RSA基本原理

1.1 数学基础

RSA算法基于以下数学原理:

  • 大数质因数分解困难:两个大质数相乘容易,但对乘积进行质因数分解极其困难
  • 欧拉函数:φ(n) = (p-1)(q-1),其中p和q是两个大质数
  • 模运算:特别是模幂运算的高效计算

1.2 密钥生成过程

  1. 选择两个大质数p和q
  2. 计算n = p × q
  3. 计算φ(n) = (p-1)(q-1)
  4. 选择整数e,使得1 < e < φ(n)且gcd(e, φ(n)) = 1
  5. 计算d,使得d × e ≡ 1 (mod φ(n))
  6. 公钥为(e, n),私钥为(d, n)

二、Python实现RSA加密解密

2.1 使用PyCryptodome库

# 生成RSA密钥对
def generate_rsa_keypair(key_size=2048):
    key = RSA.generate(key_size)
    private_key = key.export_key()
    public_key = key.publickey().export_key()
    return private_key, public_key

# RSA加密
def rsa_encrypt(public_key, plaintext):
    key = RSA.import_key(public_key)
    cipher = PKCS1_OAEP.new(key, hashAlgo=SHA256())
    ciphertext = cipher.encrypt(plaintext.encode('utf-8'))
    return base64.b64encode(ciphertext).decode('utf-8')

# RSA解密
def rsa_decrypt(private_key, ciphertext):
    key = RSA.import_key(private_key)
    cipher = PKCS1_OAEP.new(key, hashAlgo=SHA256())
    plaintext = cipher.decrypt(base64.b64decode(ciphertext))
    return plaintext.decode('utf-8')

# RSA签名
def rsa_sign(private_key, message):
    key = RSA.import_key(private_key)
    h = SHA256.new(message.encode('utf-8'))
    signer = pkcs1_15.new(key)
    signature = signer.sign(h)
    return base64.b64encode(signature).decode('utf-8')

# RSA签名验证
def rsa_verify(public_key, message, signature):
    key = RSA.import_key(public_key)
    h = SHA256.new(message.encode('utf-8'))
    signature = base64.b64decode(signature)
    try:
        pkcs1_15.new(key).verify(h, signature)
        return True
    except (ValueError, TypeError):
        return False

使用示例:

# 生成密钥对
private_key, public_key = generate_rsa_keypair()
print("Private Key:", private_key.decode('utf-8'))
print("Public Key:", public_key.decode('utf-8'))

# 加密解密
message = "这是一条需要加密的秘密消息"
encrypted = rsa_encrypt(public_key, message)
print("加密后:", encrypted)

decrypted = rsa_decrypt(private_key, encrypted)
print("解密后:", decrypted)

# 签名验证
signature = rsa_sign(private_key, message)
print("签名:", signature)

is_valid = rsa_verify(public_key, message, signature)
print("签名验证结果:", is_valid)

2.2 使用cryptography库

# 生成RSA密钥对
def generate_rsa_keys(key_size=2048):
    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=key_size,
        backend=default_backend()
    )
    public_key = private_key.public_key()
    return private_key, public_key

# RSA加密
def rsa_encrypt(public_key, plaintext):
    ciphertext = public_key.encrypt(
        plaintext.encode('utf-8'),
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    return base64.b64encode(ciphertext).decode('utf-8')

# RSA解密
def rsa_decrypt(private_key, ciphertext):
    plaintext = private_key.decrypt(
        base64.b64decode(ciphertext),
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    return plaintext.decode('utf-8')

注意:cryptography库提供了更现代化的API,推荐用于新项目。PyCryptodome库更传统,但在一些遗留系统中仍在使用。

三、其他语言实现

3.1 JavaScript (Node.js)

// 生成RSA密钥对
function generateRSAKeyPair(keySize = 2048) {
    const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
        modulusLength: keySize,
        publicKeyEncoding: {
            type: 'spki',
            format: 'pem'
        },
        privateKeyEncoding: {
            type: 'pkcs8',
            format: 'pem'
        }
    });
    return { privateKey, publicKey };
}

// RSA加密
function rsaEncrypt(publicKey, plaintext) {
    const buffer = Buffer.from(plaintext, 'utf-8');
    const encrypted = crypto.publicEncrypt({
        key: publicKey,
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
        oaepHash: 'sha256'
    }, buffer);
    return encrypted.toString('base64');
}

// RSA解密
function rsaDecrypt(privateKey, ciphertext) {
    const buffer = Buffer.from(ciphertext, 'base64');
    const decrypted = crypto.privateDecrypt({
        key: privateKey,
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
        oaepHash: 'sha256'
    }, buffer);
    return decrypted.toString('utf-8');
}

3.2 Java实现

// 生成RSA密钥对
public static KeyPair generateRSAKeyPair(int keySize) throws Exception {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(keySize);
    return keyPairGenerator.generateKeyPair();
}

// RSA加密
public static String rsaEncrypt(PublicKey publicKey, String plaintext) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    byte[] encrypted = cipher.doFinal(plaintext.getBytes("UTF-8"));
    return Base64.getEncoder().encodeToString(encrypted);
}

// RSA解密
public static String rsaDecrypt(PrivateKey privateKey, String ciphertext) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(ciphertext));
    return new String(decrypted, "UTF-8");
}

多语言对比:不同语言的RSA实现原理相同,但API风格各异。Python提供了最简洁的接口,Java需要更多的类型转换,JavaScript则提供了异步操作的支持。

四、实际应用案例

4.1 安全文件传输

class SecureFileTransfer:
    def __init__(self, key_size=2048):
        self.private_key, self.public_key = self.generate_keypair(key_size)
    
    def encrypt_file(self, public_key_path, input_file, output_file):
        # 读取公钥
        with open(public_key_path, 'rb') as f:
            public_key = RSA.import_key(f.read())
        
        # 读取文件内容
        with open(input_file, 'rb') as f:
            file_data = f.read()
        
        # 分块加密
        cipher = PKCS1_OAEP.new(public_key, hashAlgo=SHA256())
        chunk_size = 190  # RSA 2048位加密的最大块大小
        encrypted_chunks = []
        
        for i in range(0, len(file_data), chunk_size):
            chunk = file_data[i:i+chunk_size]
            encrypted_chunk = cipher.encrypt(chunk)
            encrypted_chunks.append(encrypted_chunk)
        
        # 写入加密文件
        with open(output_file, 'wb') as f:
            for chunk in encrypted_chunks:
                f.write(chunk)

4.2 HTTPS连接模拟

class SecureHTTPServer:
    def __init__(self, host='localhost', port=4443):
        self.host = host
        self.port = port
        self.context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        self.context.load_cert_chain('server.crt', 'server.key')
    
    def start(self):
        # 创建服务器socket
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind((self.host, self.port))
        
        # 包装SSL
        ssl_socket = self.context.wrap_socket(server_socket, server_side=True)
        ssl_socket.listen(5)
        
        print(f"HTTPS服务器启动在 {self.host}:{self.port}")
        
        while True:
            client_socket, addr = ssl_socket.accept()
            print(f"客户端连接: {addr}")
            
            # 处理请求
            request = client_socket.recv(1024).decode('utf-8')
            print(f"收到请求:\n{request}")
            
            # 发送响应
            response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n

HTTPS连接成功!

" client_socket.send(response.encode('utf-8')) client_socket.close()

应用场景:RSA算法广泛应用于以下场景:

  • HTTPS协议:保护Web通信安全
  • 数字签名:验证文档完整性和身份
  • 加密邮件:保护邮件内容隐私
  • 软件更新:验证更新包的完整性
  • VPN连接:建立安全隧道

五、密钥管理最佳实践

5.1 密钥存储

class RSAKeyManager:
    def __init__(self, password=None):
        self.password = password
        self.key_dir = "rsa_keys"
        self.encryption_key = self._get_encryption_key()
    
    def _get_encryption_key(self):
        # 生成或获取加密密钥
        key_file = "encryption.key"
        if os.path.exists(key_file):
            with open(key_file, 'rb') as f:
                return f.read()
        else:
            key = Fernet.generate_key()
            with open(key_file, 'wb') as f:
                f.write(key)
            return key
    
    def save_key_pair(self, private_key, public_key, name):
        # 序列化密钥
        private_pem = private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption()
        )
        
        public_pem = public_key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        )
        
        # 加密私钥
        fernet = Fernet(self.encryption_key)
        encrypted_private = fernet.encrypt(private_pem)
        
        # 保存密钥
        if not os.path.exists(self.key_dir):
            os.makedirs(self.key_dir)
        
        private_file = os.path.join(self.key_dir, f"{name}_private.enc")
        public_file = os.path.join(self.key_dir, f"{name}_public.pem")
        
        with open(private_file, 'wb') as f:
            f.write(encrypted_private)
        with open(public_file, 'wb') as f:
            f.write(public_pem)
        
        return private_file, public_file

5.2 密钥轮换

class RSAKeyRotator:
    def __init__(self, key_manager):
        self.key_manager = key_manager
    
    def rotate_keys(self, name):
        # 生成新密钥对
        new_private, new_public = self.key_manager.generate_key_pair()
        
        # 保存新密钥
        new_private_file, new_public_file = self.key_manager.save_key_pair(
            new_private, new_public, f"{name}_new"
        )
        
        # 加载旧公钥
        old_public = self.key_manager.load_public_key(name)
        
        # 这里可以添加重新加密现有数据的逻辑
        # 例如:使用新私钥签名,用旧公钥加密等
        
        print(f"新密钥对已保存到 {new_private_file} 和 {new_public_file}")
        
        return new_private_file, new_public_file

安全提醒:

  • 私钥保护:私钥必须严格保密,建议使用密码保护
  • 密钥备份:重要密钥需要安全备份,防止丢失
  • 定期轮换:特别是用于签名的密钥,需要定期更换
  • 访问控制:限制密钥文件的访问权限
  • 硬件安全:考虑使用硬件安全模块(HSM)存储密钥

六、性能优化与安全考虑

6.1 混合加密方案

class HybridEncryption:
    @staticmethod
    def generate_aes_key():
        return get_random_bytes(32)  # AES-256
    
    @staticmethod
    def encrypt_hybrid(public_key, plaintext):
        # 生成AES密钥
        aes_key = HybridEncryption.generate_aes_key()
        
        # 用AES加密数据
        encrypted_data = HybridEncryption.encrypt_with_aes(aes_key, plaintext)
        
        # 用RSA加密AES密钥
        rsa_key = RSA.import_key(public_key)
        cipher_rsa = PKCS1_OAEP.new(rsa_key)
        encrypted_key = cipher_rsa.encrypt(aes_key)
        
        return {
            'encrypted_key': base64.b64encode(encrypted_key).decode('utf-8'),
            'encrypted_data': encrypted_data
        }
    
    @staticmethod
    def decrypt_hybrid(private_key, encrypted_package):
        # 用RSA解密AES密钥
        rsa_key = RSA.import_key(private_key)
        cipher_rsa = PKCS1_OAEP.new(rsa_key)
        aes_key = cipher_rsa.decrypt(base64.b64decode(encrypted_package['encrypted_key']))
        
        # 用AES解密数据
        return HybridEncryption.decrypt_with_aes(aes_key, encrypted_package['encrypted_data'])

6.2 RSA性能测试

class RSAPerformanceTest:
    def __init__(self, key_sizes=[1024, 2048, 4096]):
        self.key_sizes = key_sizes
        self.test_messages = [
            "短消息",
            "这是一条中等长度的测试消息",
            "这是一条很长的测试消息,包含了大量的文本内容,用于测试RSA算法在不同长度消息下的性能表现。"
        ]
    
    def test_encryption(self, key, message):
        cipher = PKCS1_OAEP.new(key, hashAlgo=SHA256())
        
        # 测试加密
        start_time = time.time()
        ciphertext = cipher.encrypt(message.encode('utf-8'))
        encrypt_time = time.time() - start_time
        
        # 测试解密
        start_time = time.time()
        plaintext = cipher.decrypt(ciphertext)
        decrypt_time = time.time() - start_time
        
        return encrypt_time, decrypt_time
密钥长度 加密时间 解密时间 总时间
1024位 ~0.001秒 ~0.002秒 ~0.003秒
2048位 ~0.003秒 ~0.008秒 ~0.011秒
4096位 ~0.015秒 ~0.045秒 ~0.060秒

性能优化建议:

  • 密钥长度选择:根据安全需求选择合适的密钥长度
  • 混合加密:RSA加密对称密钥,对称加密数据
  • 批量处理:对大量数据使用流式加密
  • 缓存优化:缓存常用的公钥和私钥
  • 硬件加速:使用支持AES-NI的CPU

七、总结

关键要点:

  • RSA原理:基于大数质因数分解的数学难题
  • 密钥对:公钥加密、私钥解密,或私钥签名、公钥验证
  • 填充方案:OAEP比PKCS1更安全,推荐使用
  • 密钥长度:至少2048位,推荐3072位或更长
  • 混合加密:RSA加密对称密钥,对称加密数据,兼顾安全性和性能
  • 密钥管理:妥善保管私钥,定期轮换密钥

最佳实践:

  • 使用成熟的加密库,避免自己实现算法
  • 妥善保管私钥,使用加密存储
  • 定期轮换密钥,特别是用于签名的密钥
  • 考虑使用证书颁发机构(CA)管理公钥
  • 注意性能优化,对大数据使用混合加密方案

未来展望:

RSA算法虽然在量子计算面前面临挑战,但在可预见的未来仍将是非对称加密的主力。理解并正确使用RSA,对于构建安全的系统至关重要。

量子计算的发展将推动后量子密码学(PQC)算法的标准化,开发者需要关注NIST后量子密码标准化进程,为未来的算法迁移做好准备。

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区