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());
	}
}
posted @ 2023-07-02 21:47  程序员博博  阅读(174)  评论(0编辑  收藏  举报