信息加密系列 | RSA算法概述与代码实现

简介

RSA(Rivest-Shamir-Adleman)是目前公认的最安全的公钥加密算法之一,它是由三位密学家Rivest、Shamir和Adleman在1977年提出的,现已成为一种广泛使用的加密算法。

RSA算法两个关键的部分:公钥和私钥。公钥是可以公开的,而私钥则只有拥有者才能知道。用公钥进行加密,只能用私钥进行解密;用私钥进行加密,则只能用公钥进行解密。这种机制使得RSA算法可以应用于信息的安全传输。

粗浅理解加解密过程

假设你把一段秘密信息放进了一个保险箱,你希望只有你和一个特定的人可以打开这个保险箱看到里面的内容。于是你用一个锁锁上了这个保险箱,并把锁的钥匙给了那个特定的人。

这个锁就相当于私钥,只有你和那个特定的人有它的钥匙,其他人无法打开保险箱。而这个保险箱,就相当于你想要保密的信息。

接下来,你将公钥(即保险箱的锁)公开,并邀请所有人都可以在保险箱上锁,把他们的信息放进保险箱。任何一个人都可以使用锁将他们的信息放进保险箱中,而只有你和那个特定的人才能使用钥匙打开并读取信息。

当你想要加密明文时,就相当于将一份信息放进保险箱中。你首先需要将明文变成数字,并使用公钥(即保险箱的锁)将其加密。这样就生成了一个密文,并将其放入保险箱中,只有用私钥(即保险箱的钥匙)才能够解开保险箱,并看到信息。

当你想要解密某个密文时,就相当于从保险箱中取出之前放入的信息。只有你和那个特定的人有私钥(即保险箱的钥匙),才能够打开保险箱,并使用私钥(即保险箱的钥匙)将密文解密为明文。这样你就可以获取到保密信息,而其他人则无法解密。

代码示例

python

下面是一个简单的Python RSA加解密工具类的实现:

import rsa

class RSAUtil:
    '''
    RSA加解密工具类
    '''


    def __init__(self, public_key_path, private_key_path):
        '''
        初始化函数,传入公钥、私钥文件路径
        '''

        with open(public_key_path, 'rb'as public_key_file:
            self.public_key = rsa.PublicKey.load_pkcs1(public_key_file.read())

        with open(private_key_path, 'rb'as private_key_file:
            self.private_key = rsa.PrivateKey.load_pkcs1(private_key_file.read())

    def encrypt(self, plain_text):
        '''
        加密方法,使用公钥加密
        '''

        plain_text = plain_text.encode('utf-8')
        cipher_text = rsa.encrypt(plain_text, self.public_key)
        return cipher_text

    def decrypt(self, cipher_text):
        '''
        解密方法,使用私钥解密
        '''

        plain_text = rsa.decrypt(cipher_text, self.private_key)
        plain_text = plain_text.decode('utf-8')
        return plain_text

该工具类使用了Python中的rsa库,您需要先安装该库,可以使用pip命令进行安装:

pip install rsa

在使用该工具类之前,您需要先生成一对RSA密钥,并将公钥保存在文件中。您可以使用以下代码生成一个公钥和私钥:

import rsa

(pubkey, privkey) = rsa.newkeys(512)

with open('public.pem''wb'as public_key_file:
    public_key_file.write(pubkey.save_pkcs1())

with open('private.pem''wb'as private_key_file:
    private_key_file.write(privkey.save_pkcs1())

这样,您就可以在自己的代码中使用该工具类来进行RSA加解密了:

rsa_util = RSAUtil('public.pem''private.pem')
cipher_text = rsa_util.encrypt('hello, world')
plain_text = rsa_util.decrypt(cipher_text)

Java

下面是一个简单的Java RSA加解密工具类的实现:

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.*;

public class RSAUtil {
    /**
     * 从文件中加载公钥
     *
     * @param fileName 公钥保存路径
     * @throws Exception 加载公钥时产生的异常
     */

    public static byte[] loadPublicKey(String fileName) throws Exception {
        FileInputStream fis = new FileInputStream(fileName);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = fis.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        fis.close();
        baos.close();
        return baos.toByteArray();
    }

    /**
     * 从文件中加载私钥
     *
     * @param fileName 私钥保存路径
     * @throws Exception 加载私钥时产生的异常
     */

    public static byte[] loadPrivateKey(String fileName) throws Exception {
        FileInputStream fis = new FileInputStream(fileName);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = fis.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        fis.close();
        baos.close();
        return baos.toByteArray();
    }

    /**
     * RSA公钥加密
     *
     * @param plainData 待加密数据
     * @param publicKey 公钥
     * @throws Exception 加密过程中产生的异常
     */

    public static byte[] encryptByPublicKey(byte[] plainData, byte[] publicKey) throws Exception {
        // 将公钥由byte数组转换为PublicKey对象
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);

        // 使用公钥加密数据
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] cipherData = cipher.doFinal(plainData);

        return cipherData;
    }

    /**
     * RSA私钥解密
     *
     * @param cipherData 待解密数据
     * @param privateKey 私钥
     * @throws Exception 解密过程中产生的异常
     */

    public static byte[] decryptByPrivateKey(byte[] cipherData, byte[] privateKey) throws Exception {
        // 将私钥由byte数组转换为PrivateKey对象
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey priKey = keyFactory.generatePrivate(keySpec);

        // 使用私钥解密数据
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        byte[] plainData = cipher.doFinal(cipherData);

        return plainData;
    }
}

该工具类主要使用了Java中的加密类库JCE(Java Cryptography Extension)提供的RAS算法,使用了cipher进行加密解密操作。

RSA加解密算法需要使用公钥/私钥对,我们可以将公钥/私钥保存到磁盘文件或数据库或 远程服务器上,此处我们假设公钥私钥以文件的形式保存,然后我们需要将文件中的数据读取出来转换成Keys对象,用于加解密操作。

上述代码实现了公钥和私钥的读取、加密和解密的实现。其中,encryptByPublicKey()方法使用公钥进行加密,decryptByPrivateKey()方法使用私钥进行解密。

参考文献

1. 《应用密码学》(第三版),布鲁斯·斯坦福德

2. 《密码学基础:中文第3版》,Neal Koblitz

3. RSA是什么意思,https://mip.keoaeic.org/journal_skills/13144.html


感谢你的观看,YES!
题图 | 图片遵循CC0 1.0协议


原文始发于微信公众号(左羊公社):信息加密系列 | RSA算法概述与代码实现

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/187478.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!