共计 4437 个字符,预计需要花费 12 分钟才能阅读完成。
前言
RSA 的 key 长度为 1024 用公钥加密比拟长的字符串时会异样,这里介绍 java 如何对长文本进行分段加密,附上其它链接
RSA 加密 – Java
RSA 加密 – Vue
RSA 分段解密 – Vue
具体实现
-
实现类
import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.ArrayUtils; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.HashMap; import java.util.Map; public class RSAUtils { /** * 公钥 */ private static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCaaI4MBywkCjIppZnraqN3pbrcZTq/t0+aMBo8K3pK9BDD6XkM6N2Yfcva7BSFbUWuAcI7piXak0UKn9CElDuhNzUSgQn4IXKxIt3Iva5cV83qYumj+0yRjjLT8Muu1Y1rgBZjY9oBwhVoV+Twg25+UJ+6Q6HM4xTwQQJDoyy4jwIDAQAB"; /** * 私钥 */ private static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJpojgwHLCQKMimlmetqo3elutxlOr+3T5owGjwrekr0EMPpeQzo3Zh9y9rsFIVtRa4BwjumJdqTRQqf0ISUO6E3NRKBCfghcrEi3ci9rlxXzepi6aP7TJGOMtPwy67VjWuAFmNj2gHCFWhX5PCDbn5Qn7pDoczjFPBBAkOjLLiPAgMBAAECgYBnBBKhG7frY5IMDxwd4Euna767hB4qAlbte+JE+ozgrOzyiDXm0wXk0yjKqm8WhczTRwEbYsImjdKmP/GSQoN1AU7yEzM8j0Jgq46m9ZVrHhu2NpuZpr+XueWnA6FNz6tybBgcCwA4t8dvfbOrvjqhrCu01O1xWIpjronyFBN4IQJBAPGuF58xjXyANnp5YU8NhUQ73tTIveRlOpMXDSYkf9lWG26XIGUIsTe0f5jssiNmYtxG+lUm9LLfZgOLcrVkDZ0CQQCjjrBNMXub49efVTCg+nCGT2QXW2BHg/qs5vu8Y34LUHoD/hoEJ+AOWOdnhpRoYOpBwJAm3Gu4a1VmZGGafp0bAkAdfY3aWhSWtZpwNXF/UPoLCnc1Zc1uGkAchLqRBfEn1w7/3qcQTRA66OaNBYzzLuIvWOXhECDZ1tK+6fw0UCItAkAOLibW6n1fDKf7JnWq30u2OVfiNofoa2bmarhUowOgk3+grP0wcwyX8dlOPnrLeeuVe86DsASe3p9u2zEjJesVAkEAhkLiv4TXrC1QlJl7ghksUfFmdT7M4Zxlzj10ConMgq68HkLdmn2nNLsjhUHGwJe3EqM6aozn4zw/Z7uPIT9Fsw=="; /** * 私钥分段加密 * @param content * @return * @throws Exception */ public static String encryptLongByPrivateKey(String content) throws Exception { // 获取私钥 PrivateKey privateKey = getPrivateKey(PRIVATE_KEY); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, privateKey); // URLEncoder 编码解决中文乱码问题 byte[] data = URLEncoder.encode(content, "UTF-8").getBytes("UTF-8"); // 加密时超过 117 字节就报错。为此采纳分段加密的方法来加密 byte[] enBytes = null; for (int i = 0; i < data.length; i += 117) { // 留神要应用 2 的倍数,否则会呈现加密后的内容再解密时为乱码 byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + 117)); enBytes = ArrayUtils.addAll(enBytes, doFinal); } return Base64.getEncoder().encodeToString(enBytes); } /** * 公钥分段解密 * @param content * @return * @throws Exception */ public static String decryptLongByPublicKey(String content) throws Exception { // 获取公钥 PublicKey publicKey = getPublicKey(PUBLIC_KEY); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, publicKey); byte[] data = Base64.getDecoder().decode(content); // 返回 UTF- 8 编码的解密信息 int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) {if (inputLen - offSet > 128) {cache = cipher.doFinal(data, offSet, 128); } else {cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * 128; } byte[] decryptedData = out.toByteArray(); out.close(); return URLDecoder.decode(new String(decryptedData, "UTF-8")); } /** * 将 base64 编码后的公钥字符串转成 PublicKey 实例 * @param publicKey 公钥 * @return PublicKey 实例 * @throws Exception 异样信息 */ public static PublicKey getPublicKey(String publicKey) throws Exception {EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(keySpec); } /** * 将 base64 编码后的私钥字符串转成 PrivateKey 实例 * @param privateKey 私钥 * @return PrivateKey 实例 * @throws Exception 异样信息 */ private static PrivateKey getPrivateKey(String privateKey) throws Exception {byte[] keyBytes = Base64.getDecoder().decode(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(keySpec); } public static void main(String[] args) throws Exception {Map<String,Object> map = new HashMap<>(); map.put("name", "Cosini"); map.put("phone", "13888888888"); String content = JSONObject.toJSONString(map); // 密文 String cipherText = RSAUtils.encryptLongByPrivateKey(content); System.out.println("cipherText:" + cipherText); // 明文 String plainText = RSAUtils.decryptLongByPublicKey(cipherText); System.out.println("plainText:" + plainText); } }
- 后果如下所示:
- 注:分段加密中文乱码是因为一个中文 3 个字节,在解密最大长度分界如果被分隔成了两段转成 String 就会产生乱码。这里应用 URLEncoder 进行编码,解决中文字符乱码问题。
源码
- GitHub:https://github.com/Maggieq8324/coisini-rsa
- Gitee:https://gitee.com/maggieq8324/coisini-rsa
$$- End -$$
正文完