RSA算法
1. 前言
RSA加密是工作中非常常见的加密算法之一,我们今天来详细看看它的加密流程以及代码。
2. 非对称算法
我们知道AES是对称算法,RSA是非对称算法。那么为什么会有对称以及非对称算法呢,非对称算法是不是比对称算法要安全呢?
对称加密,顾名思义,加密方与解密方使用同一钥匙(秘钥)。具体一些就是,发送方通过使用相应的加密算法和秘钥,对将要发送的信息进行加密;对于接收方而言,使用解密算法和相同的秘钥解锁信息,从而有能力阅读信息。
非对称算法也叫公钥算法,在公钥密码系统中,加密和解密使用的是不同的密钥,这两个密钥之间存在着相互依存关系:即用其中任一个密钥加密的信息只能用另一个密钥进行解密。这使得通信双方无需事先交换密钥就可进行保密通信。其中加密密钥和算法是对外公开的,人人都可以通过这个密钥加密文件然后发给收信者,这个加密密钥又称为公钥;而收信者收到加密文件后,它可以使用他的解密密钥解密,这个密钥是由他自己私人掌管的,并不需要分发,因此又成称为私钥,这就解决了密钥分发的问题。
2.1 具体交互流程
公钥通信的流程
假设Alice 要给Bob发送一条消息,Alice 是发送者,Bob是接收者
Alice(公钥加密) ==> Bob(私钥解密)
在公钥密码通信中,通信过程是由接收者Bob来启动。
(1)Bob 生成一个包含公钥和私钥的密钥对。
私钥由Bob自行妥善保管。
(2)Bob 将自己的公钥发送给Alice。
将公钥发送给Alice,表示Bob 请Alice 用这个公钥对消息进行加密并发送给他。
(3)Alice用Bob的公钥对消息进行加密。
加密后的消息需要用Bob 私钥才能够解密。
虽然Alice 拥有Bob的公钥,但是Bob的公钥是无法对密文进行解密的。
(4)Bob 用自己的私钥对密文进行解密。
通信完成,至此,整个流程都是安全的。
2.2 安全性保证
我们可以看下下图:Bob拿公钥B加密,只有Alice的私钥B才能解密
同样。Alice拿公钥A加密,只有Bob的私钥A才能解密
这样就能保证,只要私钥不泄露,传输一定是加密的,并且不会被第三方破解(大概率)
3. 用法
3.1 生成RSA公私钥
两者选其一即可,如果需要存的话就转化成string即可。
public static final String KEY_ALGORITHM = "RSA";
public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
public static Pair<PublicKey, PrivateKey> genKeyPair() throws Exception {
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,密钥大小为
keyPairGen.initialize(2048, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私钥、公钥
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
return new Pair<>(publicKey, privateKey);
}
public static Pair<String, String> genKeyPairString() throws Exception {
Pair<PublicKey, PrivateKey> pair = genKeyPair();
// 得到私钥、公钥
PublicKey publicKey = pair.getKey();
PrivateKey privateKey = pair.getValue();
// 得到私钥字符串
String publicKeyString = Base64.encodeBase64String(publicKey.getEncoded());
String privateKeyString = Base64.encodeBase64String((privateKey.getEncoded()));
return new Pair<>(publicKeyString, privateKeyString);
}
3.2 公钥加密
// 公钥加密
public static String encryptByPublicKey(String plainText, PublicKey publicKey) {
try {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] enBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.encodeBase64String(enBytes);
} catch (Exception e) {
// error
}
return null;
}
3.3 私钥解密
// 私钥解密
public static String decryptByPrivateKey(String enStr, PrivateKey privateKey) {
try {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] deBytes = cipher.doFinal(Base64.decodeBase64(enStr));
return new String(deBytes);
} catch (Exception e) {
// error
}
return null;
}
3.4 示例代码
public class Main {
public static void main(String[] args) throws Exception {
Pair<PublicKey, PrivateKey> pair = RSAUtils.genKeyPair();
PublicKey publicKey = pair.getKey();
PrivateKey privateKey = pair.getValue();
String s = "Hello World";
String encrypt = RSAUtils.encryptByPublicKey(s, publicKey);
System.out.println("length = " + encrypt.length() + ", encrypt = " + encrypt);
System.out.println(RSAUtils.decryptByPrivateKey(encrypt, privateKey));
}
}
4. 最后
java的生态由于非常的成熟了,上面的代码已经有好多人封装了。比如hutool工具,不论使用RSA还是使用其他都非常的方便,使用RSA示例
public class Main {
public static void main(String[] args) throws Exception {
String s = "Hello World";
RSA rsa = new RSA();
String encryptBase64 = rsa.encryptBase64(s, KeyType.PublicKey);
// 加密字符串
System.out.println(encryptBase64);
// 原文
System.out.println(rsa.decryptStr(encryptBase64, KeyType.PrivateKey));
// 公钥
System.out.println(rsa.getPublicKeyBase64());
// 私钥
System.out.println(rsa.getPrivateKeyBase64());
}
}