rsa实现js前台加密java后台解密
生活随笔
收集整理的這篇文章主要介紹了
rsa实现js前台加密java后台解密
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
前段時間咱老大吩咐我寫一個rsa前臺加密到后臺用java解密。(說實話這之前我還真沒用過)
不過沒辦法啊,這是任務(wù),于是研究了一下。圓滿完成任務(wù)了,下面共享下實現(xiàn)思路:
準備工作:其實鄙人也沒那么強啦,第三方包是必須的
??????????????????????????? bcprov-jdk15on-148.jar
??????????????????????????? commons-codec-1.7.jar
??????????????????????????? commons-lang-2.4.jar
??????????????????????????? log4j-1.2.15.jar
??????????????????????????? slf4j-api-1.6.1.jar
//關(guān)鍵工具類
package com.web.utils;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyFactory; import java.security.KeyPairGenerator; import java.security.Provider; import java.security.PublicKey; import java.security.PrivateKey; import java.security.SecureRandom; import java.security.NoSuchAlgorithmException; import java.security.InvalidParameterException; import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.spec.RSAPublicKeySpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.InvalidKeySpecException; import java.util.Date;import javax.crypto.Cipher;import org.apache.commons.io.IOUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateFormatUtils;/*** RSA算法加密/解密工具類。* * @author fuchun* @version 1.0.0, 2010-05-05*/ public abstract class RSAUtils {private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);/** 算法名稱 */private static final String ALGORITHOM = "RSA";/**保存生成的密鑰對的文件名稱。 */private static final String RSA_PAIR_FILENAME = "/__RSA_PAIR.txt";/** 密鑰大小 */private static final int KEY_SIZE = 1024;/** 默認的安全服務(wù)提供者 */private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider();private static KeyPairGenerator keyPairGen = null;private static KeyFactory keyFactory = null;/** 緩存的密鑰對。 */private static KeyPair oneKeyPair = null;private static File rsaPairFile = null;static {try {keyPairGen = KeyPairGenerator.getInstance(ALGORITHOM, DEFAULT_PROVIDER);keyFactory = KeyFactory.getInstance(ALGORITHOM, DEFAULT_PROVIDER);} catch (NoSuchAlgorithmException ex) {LOGGER.error(ex.getMessage());}rsaPairFile = new File(getRSAPairFilePath());}private RSAUtils() {}/*** 生成并返回RSA密鑰對。*/private static synchronized KeyPair generateKeyPair() {try {keyPairGen.initialize(KEY_SIZE, new SecureRandom(DateFormatUtils.format(new Date(),"yyyyMMdd").getBytes()));oneKeyPair = keyPairGen.generateKeyPair();saveKeyPair(oneKeyPair);return oneKeyPair;} catch (InvalidParameterException ex) {LOGGER.error("KeyPairGenerator does not support a key length of " + KEY_SIZE + ".", ex);} catch (NullPointerException ex) {LOGGER.error("RSAUtils#KEY_PAIR_GEN is null, can not generate KeyPairGenerator instance.",ex);}return null;}/*** 返回生成/讀取的密鑰對文件的路徑。*/private static String getRSAPairFilePath() {String urlPath = RSAUtils.class.getResource("/").getPath();return (new File(urlPath).getParent() + RSA_PAIR_FILENAME);}/*** 若需要創(chuàng)建新的密鑰對文件,則返回 {@code true},否則 {@code false}。*/private static boolean isCreateKeyPairFile() {// 是否創(chuàng)建新的密鑰對文件boolean createNewKeyPair = false;if (!rsaPairFile.exists() || rsaPairFile.isDirectory()) {createNewKeyPair = true;}return createNewKeyPair;}/*** 將指定的RSA密鑰對以文件形式保存。* * @param keyPair 要保存的密鑰對。*/private static void saveKeyPair(KeyPair keyPair) {FileOutputStream fos = null;ObjectOutputStream oos = null;try {fos = FileUtils.openOutputStream(rsaPairFile);oos = new ObjectOutputStream(fos);oos.writeObject(keyPair);} catch (Exception ex) {ex.printStackTrace();} finally {IOUtils.closeQuietly(oos);IOUtils.closeQuietly(fos);}}/*** 返回RSA密鑰對。*/public static KeyPair getKeyPair() {// 首先判斷是否需要重新生成新的密鑰對文件if (isCreateKeyPairFile()) {// 直接強制生成密鑰對文件,并存入緩存。return generateKeyPair();}if (oneKeyPair != null) {return oneKeyPair;}return readKeyPair();}// 同步讀出保存的密鑰對private static KeyPair readKeyPair() {FileInputStream fis = null;ObjectInputStream ois = null;try {fis = FileUtils.openInputStream(rsaPairFile);ois = new ObjectInputStream(fis);oneKeyPair = (KeyPair) ois.readObject();return oneKeyPair;} catch (Exception ex) {ex.printStackTrace();} finally {IOUtils.closeQuietly(ois);IOUtils.closeQuietly(fis);}return null;}/*** 根據(jù)給定的系數(shù)和專用指數(shù)構(gòu)造一個RSA專用的公鑰對象。* * @param modulus 系數(shù)。* @param publicExponent 專用指數(shù)。* @return RSA專用公鑰對象。*/public static RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) {RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(modulus),new BigInteger(publicExponent));try {return (RSAPublicKey) keyFactory.generatePublic(publicKeySpec);} catch (InvalidKeySpecException ex) {LOGGER.error("RSAPublicKeySpec is unavailable.", ex);} catch (NullPointerException ex) {LOGGER.error("RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance.", ex);}return null;}/*** 根據(jù)給定的系數(shù)和專用指數(shù)構(gòu)造一個RSA專用的私鑰對象。* * @param modulus 系數(shù)。* @param privateExponent 專用指數(shù)。* @return RSA專用私鑰對象。*/public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) {RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus),new BigInteger(privateExponent));try {return (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);} catch (InvalidKeySpecException ex) {LOGGER.error("RSAPrivateKeySpec is unavailable.", ex);} catch (NullPointerException ex) {LOGGER.error("RSAUtils#KEY_FACTORY is null, can not generate KeyFactory instance.", ex);}return null;}/*** 根據(jù)給定的16進制系數(shù)和專用指數(shù)字符串構(gòu)造一個RSA專用的私鑰對象。* * @param modulus 系數(shù)。* @param privateExponent 專用指數(shù)。* @return RSA專用私鑰對象。*/public static RSAPrivateKey getRSAPrivateKey(String hexModulus, String hexPrivateExponent) {if(StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPrivateExponent)) {if(LOGGER.isDebugEnabled()) {LOGGER.debug("hexModulus and hexPrivateExponent cannot be empty. RSAPrivateKey value is null to return.");}return null;}byte[] modulus = null;byte[] privateExponent = null;try {modulus = Hex.decodeHex(hexModulus.toCharArray());privateExponent = Hex.decodeHex(hexPrivateExponent.toCharArray());} catch(DecoderException ex) {LOGGER.error("hexModulus or hexPrivateExponent value is invalid. return null(RSAPrivateKey).");}if(modulus != null && privateExponent != null) {return generateRSAPrivateKey(modulus, privateExponent);}return null;}/*** 根據(jù)給定的16進制系數(shù)和專用指數(shù)字符串構(gòu)造一個RSA專用的公鑰對象。* * @param modulus 系數(shù)。* @param publicExponent 專用指數(shù)。* @return RSA專用公鑰對象。*/public static RSAPublicKey getRSAPublidKey(String hexModulus, String hexPublicExponent) {if(StringUtils.isBlank(hexModulus) || StringUtils.isBlank(hexPublicExponent)) {if(LOGGER.isDebugEnabled()) {LOGGER.debug("hexModulus and hexPublicExponent cannot be empty. return null(RSAPublicKey).");}return null;}byte[] modulus = null;byte[] publicExponent = null;try {modulus = Hex.decodeHex(hexModulus.toCharArray());publicExponent = Hex.decodeHex(hexPublicExponent.toCharArray());} catch(DecoderException ex) {LOGGER.error("hexModulus or hexPublicExponent value is invalid. return null(RSAPublicKey).");}if(modulus != null && publicExponent != null) {return generateRSAPublicKey(modulus, publicExponent);}return null;}/*** 使用指定的公鑰加密數(shù)據(jù)。* * @param publicKey 給定的公鑰。* @param data 要加密的數(shù)據(jù)。* @return 加密后的數(shù)據(jù)。*/public static byte[] encrypt(PublicKey publicKey, byte[] data) throws Exception {Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);ci.init(Cipher.ENCRYPT_MODE, publicKey);return ci.doFinal(data);}/*** 使用指定的私鑰解密數(shù)據(jù)。* * @param privateKey 給定的私鑰。* @param data 要解密的數(shù)據(jù)。* @return 原數(shù)據(jù)。*/public static byte[] decrypt(PrivateKey privateKey, byte[] data) throws Exception {Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER);ci.init(Cipher.DECRYPT_MODE, privateKey);return ci.doFinal(data);}/*** 使用給定的公鑰加密給定的字符串。* <p />* 若 {@code publicKey} 為 {@code null},或者 {@code plaintext} 為 {@code null} 則返回 {@code* null}。* * @param publicKey 給定的公鑰。* @param plaintext 字符串。* @return 給定字符串的密文。*/public static String encryptString(PublicKey publicKey, String plaintext) {if (publicKey == null || plaintext == null) {return null;}byte[] data = plaintext.getBytes();try {byte[] en_data = encrypt(publicKey, data);return new String(Hex.encodeHex(en_data));} catch (Exception ex) {LOGGER.error(ex.getCause().getMessage());}return null;}/*** 使用默認的公鑰加密給定的字符串。* <p />* 若{@code plaintext} 為 {@code null} 則返回 {@code null}。* * @param plaintext 字符串。* @return 給定字符串的密文。*/public static String encryptString(String plaintext) {if(plaintext == null) {return null;}byte[] data = plaintext.getBytes();KeyPair keyPair = getKeyPair();try {byte[] en_data = encrypt((RSAPublicKey)keyPair.getPublic(), data);return new String(Hex.encodeHex(en_data));} catch(NullPointerException ex) {LOGGER.error("keyPair cannot be null.");} catch(Exception ex) {LOGGER.error(ex.getCause().getMessage());}return null;}/*** 使用給定的私鑰解密給定的字符串。* <p />* 若私鑰為 {@code null},或者 {@code encrypttext} 為 {@code null}或空字符串則返回 {@code null}。* 私鑰不匹配時,返回 {@code null}。* * @param privateKey 給定的私鑰。* @param encrypttext 密文。* @return 原文字符串。*/public static String decryptString(PrivateKey privateKey, String encrypttext) {if (privateKey == null || StringUtils.isBlank(encrypttext)) {return null;}try {byte[] en_data = Hex.decodeHex(encrypttext.toCharArray());byte[] data = decrypt(privateKey, en_data);return new String(data);} catch (Exception ex) {LOGGER.error(String.format("\"%s\" Decryption failed. Cause: %s", encrypttext, ex.getCause().getMessage()));}return null;}/*** 使用默認的私鑰解密給定的字符串。* <p />* 若{@code encrypttext} 為 {@code null}或空字符串則返回 {@code null}。* 私鑰不匹配時,返回 {@code null}。* * @param encrypttext 密文。* @return 原文字符串。*/public static String decryptString(String encrypttext) {if(StringUtils.isBlank(encrypttext)) {return null;}KeyPair keyPair = getKeyPair();try {byte[] en_data = Hex.decodeHex(encrypttext.toCharArray());byte[] data = decrypt((RSAPrivateKey)keyPair.getPrivate(), en_data);return new String(data);} catch(NullPointerException ex) {LOGGER.error("keyPair cannot be null.");} catch (Exception ex) {LOGGER.error(String.format("\"%s\" Decryption failed. Cause: %s", encrypttext, ex.getMessage()));}return null;}/*** 使用默認的私鑰解密由JS加密(使用此類提供的公鑰加密)的字符串。* * @param encrypttext 密文。* @return {@code encrypttext} 的原文字符串。*/public static String decryptStringByJs(String encrypttext) {String text = decryptString(encrypttext);if(text == null) {return null;}return StringUtils.reverse(text);}/** 返回已初始化的默認的公鑰。*/public static RSAPublicKey getDefaultPublicKey() {KeyPair keyPair = getKeyPair();if(keyPair != null) {return (RSAPublicKey)keyPair.getPublic();}return null;}/** 返回已初始化的默認的私鑰。*/public static RSAPrivateKey getDefaultPrivateKey() {KeyPair keyPair = getKeyPair();if(keyPair != null) {return (RSAPrivateKey)keyPair.getPrivate();}return null;}public static PublicKeyMap getPublicKeyMap() {PublicKeyMap publicKeyMap = new PublicKeyMap();RSAPublicKey rsaPublicKey = getDefaultPublicKey();publicKeyMap.setModulus(new String(Hex.encodeHex(rsaPublicKey.getModulus().toByteArray())));publicKeyMap.setExponent(new String(Hex.encodeHex(rsaPublicKey.getPublicExponent().toByteArray())));return publicKeyMap;} } package com.web.utils;public class PublicKeyMap {private String modulus;private String exponent;public String getModulus() {return modulus;}public void setModulus(String modulus) {this.modulus = modulus;}public String getExponent() {return exponent;}public void setExponent(String exponent) {this.exponent = exponent;}@Overridepublic String toString() {return "PublicKeyMap [modulus=" + modulus + ", exponent=" + exponent+ "]";} } //測試action package com.web.actions;import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.web.utils.PublicKeyMap; import com.web.utils.RSAUtils;public class UserAction extends ActionSupport{private static final long serialVersionUID = 3859457733764601693L;private String password;private Object json;public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Object getJson() {return json;}public void setJson(Object json) {this.json = json;}/*** 獲取系數(shù)和指數(shù)* @return* @throws Exception*/public String keyPair() throws Exception{PublicKeyMap publicKeyMap = RSAUtils.getPublicKeyMap();System.out.println(publicKeyMap);setJson(publicKeyMap);return SUCCESS;}/*** 登錄* @return* @throws Exception*/public String login() throws Exception{String pwd = RSAUtils.decryptStringByJs(getPassword());System.out.println(pwd);ActionContext.getContext().put("pwd", pwd);return SUCCESS;} }
//struts.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN""http://struts.apache.org/dtds/struts-2.3.dtd"> <struts><package name="default" namespace="/user" extends="json-default"><action name="login" class="com.web.actions.UserAction" method="login"><result>/success.jsp</result></action><action name="keyPair" class="com.web.actions.UserAction" method="keyPair"><result type="json"><param name="root">json</param></result></action></package> </struts>//前臺顯示index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>RSA</title><script type="text/javascript" src="<s:url value="js/jquery-1.8.0.min.js" />"></script><script type="text/javascript" src="<s:url value="js/security.js" />"></script><script type="text/javascript">$(function(){$("#btn").click(function(){$.getJSON('<s:url namespace="/user" action="keyPair" />',function(data) {var modulus = data.modulus, exponent = data.exponent;var epwd = $('#password').val();if (epwd.length != 256) {var publicKey = RSAUtils.getKeyPair(exponent, '', modulus);$('#password').val(RSAUtils.encryptedString(publicKey, epwd));}$("#login").submit();});});});</script></head><body><form id="login" name="login" action="<s:url namespace="/user" action="login" />" method="post">密碼:<input type="password" id="password" name="password"/><input id="btn" type="button" value="提 交" /></form></body> </html>
//success.jsp成功?
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>成功!</title></head><body><h1>密碼是:</h1><h1><s:property value="#request.pwd"/></h1></body> </html>以上是實現(xiàn)代碼,希望能給各位朋友帶來幫助
?結(jié)果圖如下:
index.jsp
success.js
控制臺
轉(zhuǎn)載于:https://my.oschina.net/xiaoen/blog/121631
總結(jié)
以上是生活随笔為你收集整理的rsa实现js前台加密java后台解密的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 魅族x8值不值得买(魅族科技有限公司)
- 下一篇: 国内显卡出货量暴跌42%!希望就在眼前