简介
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
原文始发于微信公众号(左羊公社):信息加密系列 | RSA算法概述与代码实现
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/187478.html