RSA加密的简单使用

本文详细介绍了RSA非对称加密原理,强调了其安全性基于大整数分解难题。通过Java代码展示了如何生成公钥和私钥,以及如何使用公钥加密和私钥解密数据。同时,提醒了在传输过程中注意加密数据的保护,以防止解密失败。
摘要由CSDN通过智能技术生成

RSA是一种非对称加密,发送方用公钥加密,接收方用私钥解密。只要私钥不泄漏,即使获得了公钥和数据,也无法进行解密。RSA的安全性依赖于大整数因式分解的困难,目前已知被分解的最大整数为768个二进制位,也就是说已知能被破解的最大RSA秘钥为768位,但是一般情况都采用1024位的秘钥,重要数据使用2048位的秘钥(当然安全性的提升要付出更多的解密时间)。
首先生成公钥和私钥:

public static void main(String[] args) {
	try {
		KeyPairGenerator kp = KeyPairGenerator.getInstance("RSA");
		kp.initialize(1024); // 要是需要2048的秘钥的话就修改一下参数
		KeyPair keyPair = kp.generateKeyPair();
		PublicKey publicKey = keyPair.getPublic();
		System.out.println("公钥为:" + new String(Base64.getEncoder().encode(publicKey.getEncoded())));
		PrivateKey privateKey = keyPair.getPrivate();
		System.out.println("私钥为:" + new String(Base64.getEncoder().encode(privateKey.getEncoded())));
	} catch (NoSuchAlgorithmException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

执行就能得到结果:

公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl0vjjliUX5ZfefPqQ8Mf57EBRWqcHHggs6AYRHYVWJWxkpSTYFbCLuU7R6MnAIaWFZrfLvVfTNE6or7aDmbeHFnYHOZwvZfPRPDL3Iu915wTM3Ns62kQuXNbHNspN/xxiLnSjzMUvbnL5aVc/NJazzuMg+FVma910w9i2c2EMmwIDAQAB
私钥为:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOXS+OOWJRfll958+pDwx/nsQFFapwceCCzoBhEdhVYlbGSlJNgVsIu5TtHoycAhpYVmt8u9V9M0TqivtoOZt4cWdgc5nC9l89E8Mvci73XnBMzc2zraRC5c1sc2yk3/HGIudKPMxS9ucvlpVz80lrPO4yD4VWZr3XTD2LZzYQybAgMBAAECgYBHnZRdJv5sEelfNUbHP6CxKoNoVn1R5HPbunmZf7969rJuMl/mzetzvszm8EleC54OkdGYNWpWsCgKvKZ9H7tmT8yQfIwP5uvXZY9bbnL0mSU97LmdvJ/NW0+BDZYTz0Uz0OV6yvyluBe4g7YqhckzXToLO8SJrIB15W6hx2qhgQJBAPiBqvkZOPYL3ey9h+hhMyOE9VfFm/LxHxoCFM6MaN4IkBWCoOFMHoK7U4gVOwio3cURBUlHN5wlITwcyvktYbsCQQDswRYqJDBJ5tF412yy8RpF0glJRVM2FAgG0zz8bBvEYJMRVSVi9+Q1u+cFgIPvHDpkaOEezLq+pR3uBGKJ92KhAkBm3n5g+UDsEUN/sYFl/36E0JAjEkkZCxk90ei9C8CJUPAcB2QDf1gN8++DII68afLLld0jVVi+yVv1n1GiTlfrAkEAhrCCj47u+dwap4jHCjYoIDiRl+GcqVNUDa33MBPA6EOY529tSZSFfBxeHb8zT8DbZ2xTRlZqlzMQh+xustbOgQJBAJSq6ioVUR8YwYMl0VD4svuZiuv6aAu2P1BK3f/ftbPyDPm3SKn3TV0/Rpe3KJO1Di2G+8gXyR8tge6Dm3RAdoU=

当然每次得到的公钥私钥都是不一样的,然后把公钥交给发送方以进行加密

public static void main(String[] args) {
	// 公钥字符串,这里直接赋值了,当然一般不会这么写,把公钥放在一个数据文件或者配置里面去获取
	String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDl0vjjliUX5ZfefPqQ8Mf57EBRWqcHHggs6AYRHYVWJWxkpSTYFbCLuU7R6MnAIaWFZrfLvVfTNE6or7aDmbeHFnYHOZwvZfPRPDL3Iu915wTM3Ns62kQuXNbHNspN/xxiLnSjzMUvbnL5aVc/NJazzuMg+FVma910w9i2c2EMmwIDAQAB";

	try {
		// 把公钥字符串转换成对象
		byte[] publicKeyBy = Base64.getDecoder().decode(publicKeyStr.getBytes());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyBy));

		 // 以上获得的PublicKey可以固化下来,只要秘钥不变,就可以一直使用,但是下面的cipherPublic 不要固化!因为他不是线程安全的,如果使用同一个cipherPublic 并发访问时可能会抛出异常javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes
		Cipher cipherPublic = Cipher.getInstance("RSA");
		// 设置为加密模式并设置公钥
		cipherPublic.init(Cipher.ENCRYPT_MODE, publicKey);
		
		// 定义一个发送的数据
		String sendMsg = "你好呀!";
		// 获得加密的byte[]
		byte[] encryptByte = cipherPublic.doFinal(sendMsg.toString().getBytes("UTF-8"));
		// 转变成字符串以进行传输
		String strKey = Base64.getEncoder().encodeToString(encryptByte);
		System.out.println("加密后的数据为:" + strKey);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

得到的结果为:

加密后的数据为:dBz/nSJ+jK13dhEhNZOeBcMgQjJfauWP9xl0OLYKiuhKOzYbI+zOezyM1PhHqTvl3hjaTf+wzpzUd+2p75v4Zn8sxSmRw8CIzXTtY/4g3v94cdZbvTfWe+snLXt7qTMdK9grrBqSvBhp/JsOPhd336h/lo77mYd0XEUNJhIFyl0=

获得加密数据后接收方就可以进行相应的解密了,不过要注意一些传输方式会破坏加密数据,如url的get方式传输时,加密数据的’+'会被转换成 ’ ',所以接收到数据之后要注意转换回来,不然就解密错误了:

public static void main(String[] args) {

	// 私钥字符串,这里直接赋值了,同样的,可以把私钥放在一个数据文件或者配置里面去获取
	String privateKeyStr = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOXS+OOWJRfll958+pDwx/nsQFFapwceCCzoBhEdhVYlbGSlJNgVsIu5TtHoycAhpYVmt8u9V9M0TqivtoOZt4cWdgc5nC9l89E8Mvci73XnBMzc2zraRC5c1sc2yk3/HGIudKPMxS9ucvlpVz80lrPO4yD4VWZr3XTD2LZzYQybAgMBAAECgYBHnZRdJv5sEelfNUbHP6CxKoNoVn1R5HPbunmZf7969rJuMl/mzetzvszm8EleC54OkdGYNWpWsCgKvKZ9H7tmT8yQfIwP5uvXZY9bbnL0mSU97LmdvJ/NW0+BDZYTz0Uz0OV6yvyluBe4g7YqhckzXToLO8SJrIB15W6hx2qhgQJBAPiBqvkZOPYL3ey9h+hhMyOE9VfFm/LxHxoCFM6MaN4IkBWCoOFMHoK7U4gVOwio3cURBUlHN5wlITwcyvktYbsCQQDswRYqJDBJ5tF412yy8RpF0glJRVM2FAgG0zz8bBvEYJMRVSVi9+Q1u+cFgIPvHDpkaOEezLq+pR3uBGKJ92KhAkBm3n5g+UDsEUN/sYFl/36E0JAjEkkZCxk90ei9C8CJUPAcB2QDf1gN8++DII68afLLld0jVVi+yVv1n1GiTlfrAkEAhrCCj47u+dwap4jHCjYoIDiRl+GcqVNUDa33MBPA6EOY529tSZSFfBxeHb8zT8DbZ2xTRlZqlzMQh+xustbOgQJBAJSq6ioVUR8YwYMl0VD4svuZiuv6aAu2P1BK3f/ftbPyDPm3SKn3TV0/Rpe3KJO1Di2G+8gXyR8tge6Dm3RAdoU=";
	// 刚才我们获得的加密数据,一般通过各种传输途径接收到
	String encryptReceiveMsg = "dBz/nSJ+jK13dhEhNZOeBcMgQjJfauWP9xl0OLYKiuhKOzYbI+zOezyM1PhHqTvl3hjaTf+wzpzUd+2p75v4Zn8sxSmRw8CIzXTtY/4g3v94cdZbvTfWe+snLXt7qTMdK9grrBqSvBhp/JsOPhd336h/lo77mYd0XEUNJhIFyl0=";

	try {
		// 把私钥字符串转换成对象
		byte[] privateKeyBy = Base64.getDecoder().decode(privateKeyStr.getBytes());
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBy));
		// 同样的,可以固化cipherPrivate ,但是不能固化cipherPrivate,因为它不是线程安全的
		Cipher cipherPrivate = Cipher.getInstance("RSA");
		// 设置为解密模式并设置私钥
		cipherPrivate.init(Cipher.DECRYPT_MODE, privateKey);
		
		// 进行解密
		byte[] decryptByte = cipherPrivate.doFinal(Base64.getDecoder().decode(encryptReceiveMsg));
		// 转换成字符串 
		String receiveMsg = new String(decryptByte, "UTF-8");
		System.out.println("解密后的数据:" + receiveMsg);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

得到解密结果:

解密后的数据:你好呀!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yue_hu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值