RSA加解密——前端js加密,後臺解密
阿新 • • 發佈:2018-12-17
一、前端js
1、前端js
先引入 jsencrypt.js
<script src="${pageContext.request.contextPath}/static/scripts/jquery/dist/jsencrypt.js"></script>
頁面放置一個隱藏的input標籤,用於存放公鑰
<input type="hidden" value="${publicKeyString}" id="publicKeyString">
js進行加密,$("#pwd").val()為加密前的密碼,ps為加密後的密碼
var encrypt = new JSEncrypt();
encrypt.setPublicKey($("#publicKeyString").val());
var d=encrypt.encrypt($("#pwd").val());
var ps= encodeURI(d).replace(/\+/g, '%2B');
二、後臺
後臺進行解密(我的公鑰祕鑰用了固定的一組,存放在檔案中,可以用不同的公鑰祕鑰)
//對密碼進行解密 password = password.replaceAll("%2B","+"); //獲取私鑰 String path = this.getClass().getResource("/LoginRsaKey/privateKey.txt").getFile(); String privateKey = ToStringUtils.readTxt(path); byte[] decryptByPrivateKey = RSAUtils_user.decryptByPrivateKey(Base64Utils.decode(password), privateKey); //解密後的密碼 String decodePassword = new String(decryptByPrivateKey);
公鑰祕鑰存放位置:
三、公鑰祕鑰生成:
Map<String, Object> keyMap=RSAUtils.genKeyPair();
String publicKey = RSAUtils.getPublicKey(keyMap);
String privateKey = RSAUtils.getPrivateKey(keyMap);
四、相關的工具類:
ToStringUtils.java
package com.synjones.gatewayManage.utils; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectOutputStream; import java.util.Calendar; import java.util.Random; public class ToStringUtils { public static String getDateFilePrefix() { Calendar calendar = Calendar.getInstance(); String now_y = String.valueOf(calendar.get(Calendar.YEAR));//得到年份 String now_m = String.valueOf(calendar.get(Calendar.MONTH)+1);//得到月份 String now_d = String.valueOf(calendar.get(Calendar.DATE));//得到月份中今天的號數 String now_h = String.valueOf(calendar.get(Calendar.HOUR_OF_DAY));//得到一天中現在的時間,24小時制 String now_mm = String.valueOf(calendar.get(Calendar.MINUTE));//得到分鐘數 String now_s = String.valueOf(calendar.get(Calendar.SECOND));//得到秒數 //String now_ms =String.valueOf( calendar.get(Calendar.MILLISECOND));//得到秒數 return now_y + "-" + now_m + "-" + now_d + "-" + now_h + "-" + now_mm + "-" + now_s + "-" ; //+ now_ms + "-"; } /** * 陣列轉成十六進位制字串 * @param byte[] * @return HexString */ public static String toHexString1(byte[] b){ StringBuffer buffer = new StringBuffer(); for (int i = 0; i < b.length; ++i){ buffer.append(toHexString1(b[i])); } return buffer.toString(); } public static String toHexString1(byte b){ String s = Integer.toHexString(b & 0xFF); if (s.length() == 1){ return "0" + s; }else{ return s; } } /** * 反轉 * @param s * @return */ public static String stringRevToStr(String s) { String revS = new StringBuffer(s).reverse().toString(); char[] charArray = revS.toCharArray(); String val = ""; for (int i = 0; i < charArray.length; i += 2) { char b = charArray[i]; char c = charArray[i + 1]; val += c; val += b; } //Integer revStoInt = Integer.valueOf(val); return val; } /** * 16進位制轉換成為string型別字串 * @param s * @return */ public static String hexStringToString(String s) { if (s == null || s.equals("")) { return null; } s = s.replace(" ", ""); byte[] baKeyword = new byte[s.length() / 2]; for (int i = 0; i < baKeyword.length; i++) { try { baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16)); } catch (Exception e) { e.printStackTrace(); } } try { s = new String(baKeyword, "UTF-8"); new String(); } catch (Exception e1) { e1.printStackTrace(); } return s; } /** * 物件轉Byte陣列 * @param obj * @return */ public static byte[] objectToByteArray(Object obj) { byte[] bytes = null; ByteArrayOutputStream byteArrayOutputStream = null; ObjectOutputStream objectOutputStream = null; try { byteArrayOutputStream = new ByteArrayOutputStream(); objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(obj); objectOutputStream.flush(); bytes = byteArrayOutputStream.toByteArray(); } catch (IOException e) { System.out.println("objectToByteArray failed, " + e); } finally { if (objectOutputStream != null) { try { objectOutputStream.close(); } catch (IOException e) { //LOGGER.error("close objectOutputStream failed, " + e); System.out.println("close objectOutputStream failed, " + e); } } if (byteArrayOutputStream != null) { try { byteArrayOutputStream.close(); } catch (IOException e) { //LOGGER.error("close byteArrayOutputStream failed, " + e); System.out.println("close byteArrayOutputStream failed, " + e); } } } return bytes; } /** * 物件轉陣列 * @param obj * @return */ public static byte[] toByteArray (Object obj) { byte[] bytes = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.flush(); bytes = bos.toByteArray (); oos.close(); bos.close(); } catch (IOException ex) { ex.printStackTrace(); } return bytes; } public static byte[] hexStringToByteArray(String s) { int len = s.length(); byte[] data = new byte[len / 2]; try { for (int i = 0; i < len; i += 2) { data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16)); } } catch (Exception e) { //Log.d("", "Argument(s) for hexStringToByteArray(String s)"+ "was not a hex string"); } return data; } //使用1位元組就可以表示b public static String numToHex8(int b) { return String.format("%02X", b);//2表示需要兩個16進行數 } //需要使用2位元組表示b public static String numToHex16(int b) { return String.format("%04X", b); } //需要使用4位元組表示b public static String numToHex32(int b) { return String.format("%08X", b); } public static byte[] toByteArray(short[] src) { int count = src.length; byte[] dest = new byte[count << 1]; for (int i = 0; i < count; i++) { dest[i * 2] = (byte) (src[i] >> 8); dest[i * 2 + 1] = (byte) (src[i] >> 0); } return dest; } public static byte[] shortToByteArray(short s) { byte[] targets = new byte[2]; for (int i = 0; i < 2; i++) { int offset = (targets.length - 1 - i) * 8; targets[i] = (byte) ((s >>> offset) & 0xff); } return targets; } /** * int轉byte * @param value * @return */ public static byte[] intToBytes( int value ) { byte[] src = new byte[4]; src[3] = (byte) ((value>>24) & 0xFF); src[2] = (byte) ((value>>16) & 0xFF); src[1] = (byte) ((value>>8) & 0xFF); src[0] = (byte) (value & 0xFF); return src; } //byte 轉 int public static int ByteArrayToInt(byte[] bArr) { if(bArr.length!=4){ return -1; } return (int) ((((bArr[3] & 0xff) << 24) | ((bArr[2] & 0xff) << 16) | ((bArr[1] & 0xff) << 8) | ((bArr[0] & 0xff) << 0))); } /** * byte轉long * @param byteNum * @return */ public static long bytes2Long(byte[] byteNum) { long num = 0; for (int ix = 0; ix < 8; ++ix) { num <<= 8; num |= (byteNum[ix] & 0xff); } return num; } /** * 位元組陣列到long的轉換. */ public static long byteToLong(byte[] b) { long s = 0; long s0 = b[0] & 0xff;// 最低位 long s1 = b[1] & 0xff; long s2 = b[2] & 0xff; long s3 = b[3] & 0xff; long s4 = b[4] & 0xff;// 最低位 long s5 = b[5] & 0xff; long s6 = b[6] & 0xff; long s7 = b[7] & 0xff; // s0不變 s1 <<= 8; s2 <<= 16; s3 <<= 24; s4 <<= 8 * 4; s5 <<= 8 * 5; s6 <<= 8 * 6; s7 <<= 8 * 7; s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7; return s; } /** * 合併陣列 * @param values * @return */ public static byte[] byteMergerAll(byte[]... values) { int length_byte = 0; for (int i = 0; i < values.length; i++) { length_byte += values[i].length; } byte[] all_byte = new byte[length_byte]; int countLength = 0; for (int i = 0; i < values.length; i++) { byte[] b = values[i]; System.arraycopy(b, 0, all_byte, countLength, b.length); countLength += b.length; } return all_byte; } public static String checkByte(byte[] b) { String result = "value"; int leng = 0; for(int i=0;i<b.length;i++){ if(b[i]==0){ leng++; } } if(leng==b.length){ result = "notValue"; } return result; } /** * 積壓流水 * @param head * @param tail * @return */ public static int getJy(int head, int tail) { int jy = 0; if ((int)tail - (int)head >= 0) { jy = tail - head; } else { jy = tail - head + 100000;//總流水數100000 } return jy; } public static byte[] shortToByte(short number) { int temp = number; byte[] b = new byte[2]; for (int i = 0; i < b.length; i++) { b[i] = new Integer(temp & 0xff).byteValue();// 將最低位儲存在最低位 temp = temp >> 8; // 向右移8位 } return b; } public static short byteToShort(byte[] b) { short s = 0; short s0 = (short) (b[0] & 0xff);// 最低位 short s1 = (short) (b[1] & 0xff); s1 <<= 8; s = (short) (s0 | s1); return s; } //去讀私鑰 public static String readTxt(String filePath) { String lineTxt = null; try { File file = new File(filePath); if(file.isFile() && file.exists()) { InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "utf-8"); BufferedReader br = new BufferedReader(isr); while ((lineTxt = br.readLine()) != null) { System.out.println(lineTxt); return lineTxt; } br.close(); } else { System.out.println("檔案不存在!"); } } catch (Exception e) { System.out.println("檔案讀取錯誤!"); } return lineTxt; } }
Base64Utils.java
package com.synjones.gatewayManage.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.codec.binary.Base64;
public class Base64Utils {
/** *//**
* 檔案讀取緩衝區大小
*/
private static final int CACHE_SIZE = 1024;
/** *//**
* <p>
* BASE64字串解碼為二進位制資料
* </p>
*
* @param base64
* @return
* @throws Exception
*/
public static byte[] decode(String base64) throws Exception {
return Base64.decodeBase64(base64.getBytes());
}
/** *//**
* <p>
* 二進位制資料編碼為BASE64字串
* </p>
*
* @param bytes
* @return
* @throws Exception
*/
public static String encode(byte[] bytes) throws Exception {
return new String(Base64.encodeBase64(bytes));
}
/** *//**
* <p>
* 將檔案編碼為BASE64字串
* </p>
* <p>
* 大檔案慎用,可能會導致記憶體溢位
* </p>
*
* @param filePath 檔案絕對路徑
* @return
* @throws Exception
*/
public static String encodeFile(String filePath) throws Exception {
byte[] bytes = fileToByte(filePath);
return encode(bytes);
}
/** *//**
* <p>
* BASE64字串轉回檔案
* </p>
*
* @param filePath 檔案絕對路徑
* @param base64 編碼字串
* @throws Exception
*/
public static void decodeToFile(String filePath, String base64) throws Exception {
byte[] bytes = decode(base64);
byteArrayToFile(bytes, filePath);
}
/** *//**
* <p>
* 檔案轉換為二進位制陣列
* </p>
*
* @param filePath 檔案路徑
* @return
* @throws Exception
*/
public static byte[] fileToByte(String filePath) throws Exception {
byte[] data = new byte[0];
File file = new File(filePath);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
out.write(cache, 0, nRead);
out.flush();
}
out.close();
in.close();
data = out.toByteArray();
}
return data;
}
/** *//**
* <p>
* 二進位制資料寫檔案
* </p>
*
* @param bytes 二進位制資料
* @param filePath 檔案生成目錄
*/
public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
InputStream in = new ByteArrayInputStream(bytes);
File destFile = new File(filePath);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
destFile.createNewFile();
OutputStream out = new FileOutputStream(destFile);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
out.write(cache, 0, nRead);
out.flush();
}
out.close();
in.close();
}
}
RSAUtils_user.java
package com.synjones.gatewayManage.utils;
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
public class RSAUtils_user {
/** *//**
* 加密演算法RSA
*/ public static final String KEY_ALGORITHM = "RSA";
/** *//**
* 簽名演算法
*/
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
/** *//**
* 獲取公鑰的key
*/
private static final String PUBLIC_KEY = "RSAPublicKey";
/** *//**
* 獲取私鑰的key
*/
private static final String PRIVATE_KEY = "RSAPrivateKey";
/** *//**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/** *//**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/** *//**
* <p>
* 生成金鑰對(公鑰和私鑰)
* </p>
*
* @return
* @throws Exception
*/
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
/** *//**
* <p>
* 用私鑰對資訊生成數字簽名
* </p>
*
* @param data 已加密資料
* @param privateKey 私鑰(BASE64編碼)
*
* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateK);
signature.update(data);
return Base64Utils.encode(signature.sign());
}
/** *//**
* <p>
* 校驗數字簽名
* </p>
*
* @param data 已加密資料
* @param publicKey 公鑰(BASE64編碼)
* @param sign 數字簽名
*
* @return
* @throws Exception
*
*/
public static boolean verify(byte[] data, String publicKey, String sign)
throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicK = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicK);
signature.update(data);
return signature.verify(Base64Utils.decode(sign));
}
/** *//**
* <P>
* 私鑰解密
* </p>
*
* @param encryptedData 已加密資料
* @param privateKey 私鑰(BASE64編碼)
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 對資料分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/** *//**
* <p>
* 公鑰解密
* </p>
*
* @param encryptedData 已加密資料
* @param publicKey 公鑰(BASE64編碼)
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 對資料分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/** *//**
* <p>
* 公鑰加密
* </p>
*
* @param data 源資料
* @param publicKey 公鑰(BASE64編碼)
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String publicKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 對資料加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 對資料分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/** *//**
* <p>
* 私鑰加密
* </p>
*
* @param data 源資料
* @param privateKey 私鑰(BASE64編碼)
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String privateKey)
throws Exception {
byte[] keyBytes = Base64Utils.decode(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 對資料分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/** *//**
* <p>
* 獲取私鑰
* </p>
*
* @param keyMap 金鑰對
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64Utils.encode(key.getEncoded());
}
/** *//**
* <p>
* 獲取公鑰
* </p>
*
* @param keyMap 金鑰對
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Object> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64Utils.encode(key.getEncoded());
}
}