1、RSA算法加密解密思路。
java后台随机生成公钥、私钥。存储于session中,告知前台js获取公钥。通过jsencrypt.min.js进行加密。传输回后台,后台通过私钥解密。
2、RSA常见异常分解。
问题一
Cannot find any provider supporting RSA
出现此问题,属于JDK版本bug问题,笔者1.8.0_171遇到此问题,更换1.8.0_211之后即可解决。
问题二
DER input, Integer tag error
出现此问题,主要是公钥,私钥混用到至,通过断点发现解密时,用的公钥进行解密,哈哈。
问题三
Decryption error
出现此问题,主要是前台页面传参至后台,出现“+”符号被替换成“ ”空格导致无法进行解密。
3.代码部分。
引用地址:https://blog.csdn.net/qq_36827957/article/details/81563973
<script language=javascript> var publicKey = ‘<%=session.getAttribute("publicKey")%>‘; $(document).ready(function() { $(‘#doSearch‘).click(function(e) { var phoneNo= $("#phoneNo").val(); var encrypt = new JSEncrypt(); encrypt.setPublicKey(publicKey); phoneNo = encrypt.encrypt(phoneNo); alert(phoneNo); document.frm.submit(); }); }); </script>
放入session部分
@RequestMapping(value = "/index") public String login(Model model, HttpSession session,HttpServletRequest request) { Map<String, String> rsaMap = new HashMap<String, String>(); rsaMap = RsaUtil.createRSAKeys(); String publicKey = rsaMap.get("publicKey"); String privateKey = rsaMap.get("privateKey"); session.setAttribute("publicKey", publicKey); session.setAttribute("niceKey", privateKey); return "index"; }
解析部分
@RequestMapping(value = "/search", method = RequestMethod.POST) public String search(@ModelAttribute String phoneNo, HttpServletRequest request, HttpSession session, Model model) { if (phoneNo==null || "".equals(phoneNo)) { model.addAttribute("returnUrl", "fail"); return "fail"; } //RSA解密 phoneNo = phoneNo.replace(" ", "+"); phoneNo = RsaUtil.decode(phoneNo, session.getAttribute("niceKey").toString()); System.out.println("phoneNo:" + phoneNo); { //业务代码 } return "success"; }
RSA工具类部分
package com.thinksep.utils; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.crypto.Cipher; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tomcat.util.codec.binary.Base64; /** * @author * @createDate */ public class RsaUtil { protected static final Log log = LogFactory.getLog(RsaUtil.class); private static String KEY_RSA_TYPE = "RSA"; private static int KEY_SIZE = 1024;//JDK方式RSA加密最大只有1024位 private static int ENCODE_PART_SIZE = KEY_SIZE/8; public static final String PUBLIC_KEY_NAME = "public"; public static final String PRIVATE_KEY_NAME = "private"; /** * 创建公钥秘钥 * @return */ public static Map<String,String> createRSAKeys(){ Map<String,String> keyPairMap = new HashMap<>();//里面存放公私秘钥的Base64位加密 try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_RSA_TYPE); keyPairGenerator.initialize(KEY_SIZE,new SecureRandom()); KeyPair keyPair = keyPairGenerator.generateKeyPair(); //获取公钥秘钥 String publicKeyValue = Base64.encodeBase64String(keyPair.getPublic().getEncoded()); String privateKeyValue = Base64.encodeBase64String(keyPair.getPrivate().getEncoded()); //存入公钥秘钥,以便以后获取 keyPairMap.put(PUBLIC_KEY_NAME,publicKeyValue); keyPairMap.put(PRIVATE_KEY_NAME,privateKeyValue); } catch (NoSuchAlgorithmException e) { log.error("当前JDK版本没找到RSA加密算法!"); e.printStackTrace(); } return keyPairMap; } /** * 公钥加密 * 描述: * 1字节 = 8位; * 最大加密长度如 1024位私钥时,最大加密长度为 128-11 = 117字节,不管多长数据,加密出来都是 128 字节长度。 * @param sourceStr * @param publicKeyBase64Str * @return */ public static String encode(String sourceStr,String publicKeyBase64Str){ byte [] publicBytes = Base64.decodeBase64(publicKeyBase64Str); //公钥加密 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes); List<byte[]> alreadyEncodeListData = new LinkedList<>(); int maxEncodeSize = ENCODE_PART_SIZE - 11; String encodeBase64Result = null; try { KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE); cipher.init(Cipher.ENCRYPT_MODE,publicKey); byte[] sourceBytes = sourceStr.getBytes("utf-8"); int sourceLen = sourceBytes.length; for(int i=0;i<sourceLen;i+=maxEncodeSize){ int curPosition = sourceLen - i; int tempLen = curPosition; if(curPosition > maxEncodeSize){ tempLen = maxEncodeSize; } byte[] tempBytes = new byte[tempLen];//待加密分段数据 System.arraycopy(sourceBytes,i,tempBytes,0,tempLen); byte[] tempAlreadyEncodeData = cipher.doFinal(tempBytes); alreadyEncodeListData.add(tempAlreadyEncodeData); } int partLen = alreadyEncodeListData.size();//加密次数 int allEncodeLen = partLen * ENCODE_PART_SIZE; byte[] encodeData = new byte[allEncodeLen];//存放所有RSA分段加密数据 for (int i = 0; i < partLen; i++) { byte[] tempByteList = alreadyEncodeListData.get(i); System.arraycopy(tempByteList,0,encodeData,i*ENCODE_PART_SIZE,ENCODE_PART_SIZE); } encodeBase64Result = Base64.encodeBase64String(encodeData); } catch (Exception e) { e.printStackTrace(); } return encodeBase64Result; } /** * 私钥解密 * @param sourceBase64RSA * @param privateKeyBase64Str */ public static String decode(String sourceBase64RSA,String privateKeyBase64Str){ byte[] privateBytes = Base64.decodeBase64(privateKeyBase64Str); byte[] encodeSource = Base64.decodeBase64(sourceBase64RSA); int encodePartLen = encodeSource.length/ENCODE_PART_SIZE; List<byte[]> decodeListData = new LinkedList<>();//所有解密数据 String decodeStrResult = null; //私钥解密 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateBytes); try { KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE); cipher.init(Cipher.DECRYPT_MODE,privateKey); int allDecodeByteLen = 0;//初始化所有被解密数据长度 for (int i = 0; i < encodePartLen; i++) { byte[] tempEncodedData = new byte[ENCODE_PART_SIZE]; System.arraycopy(encodeSource,i*ENCODE_PART_SIZE,tempEncodedData,0,ENCODE_PART_SIZE); byte[] decodePartData = cipher.doFinal(tempEncodedData); decodeListData.add(decodePartData); allDecodeByteLen += decodePartData.length; } byte [] decodeResultBytes = new byte[allDecodeByteLen]; for (int i = 0,curPosition = 0; i < encodePartLen; i++) { byte[] tempSorceBytes = decodeListData.get(i); int tempSourceBytesLen = tempSorceBytes.length; System.arraycopy(tempSorceBytes,0,decodeResultBytes,curPosition,tempSourceBytesLen); curPosition += tempSourceBytesLen; } decodeStrResult = new String(decodeResultBytes,"UTF-8"); }catch (Exception e){ e.printStackTrace(); } return decodeStrResult; } }
原文地址:https://www.cnblogs.com/thinksep/p/10987920.html
时间: 2024-10-10 09:19:09