一、js引入Barrett.js、BigInt.js、RSA.js
二、js请求后台获取key
$http({
method: 'post',
url: 'action/key',
params: {
t:Math.random()
},
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(data, status) {
$scope.publicKey = data;
if($scope.publicKey){
$scope.login();
}
}).error(function(data, status) {
alert('失败');
});
三、java生成key
需要引入bcprov-jdk16-1.46.jar
package com.neusoft.streamone.app.security.controller;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.neusoft.streamone.app.utils.RSAUtils;
@Controller
@RequestMapping("/key")
public class KeyController {
@RequestMapping
@ResponseBody
public Map<String, Object> generate(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> m = new HashMap<String, Object>();
RSAPublicKey publicKey = null;
try{
Map<String, Object> keyMap = RSAUtils.getkeyPairMap();
publicKey=RSAUtils.getPublicKey(keyMap);
m.put("modulus", publicKey.getModulus().toString(16));
m.put("exponent", publicKey.getPublicExponent().toString(16));
RSAPrivateKey privateKey=RSAUtils.getPrivateKey(keyMap);
request.getSession().setAttribute(RSAUtils.PRIVATE_KEY, privateKey);
}catch(Exception e){
e.printStackTrace();
}
return m;
}
}
package com.neusoft.streamone.app.utils;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
public class RSAUtils {
//非对称密钥算法
public static final String KEY_ALGORITHM = "RSA";
//密钥长度,DH算法的默认密钥长度是1024,密钥长度必须是64的倍数,在512到65536位之间
private static final int KEY_SIZE = 512;
//公钥
public static final String PUBLIC_KEY = "RSAPublicKey";
//私钥
public static final String PRIVATE_KEY = "RSAPrivateKey";
private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider();
//初始化密钥
public static Map<String,Object> getkeyPairMap() throws Exception {
KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
KeyPair keyPair=keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey=(RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();
Map<String,Object> keyMap=new HashMap<String,Object>();
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
//私钥解密
public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
//取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);
//生成私钥
PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);
//数据解密
Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
public static String decryptToString(RSAPrivateKey key, String text) throws Exception {
if(StringUtils.isBlank(text)) {
return null;
}
byte[] en_data = Hex.decodeHex(text.toCharArray());
byte[] data = decrypt(key, en_data);
return StringUtils.reverse(new String(data));
}
public static byte[] decrypt(PrivateKey privateKey, byte[] data) throws Exception {
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM, DEFAULT_PROVIDER);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
//取得私钥
public static RSAPrivateKey getPrivateKey(Map<String,Object> keyMap){
return (RSAPrivateKey)keyMap.get(PRIVATE_KEY);
}
//取得公钥
public static RSAPublicKey getPublicKey(Map<String,Object> keyMap) throws Exception{
return (RSAPublicKey) keyMap.get(PUBLIC_KEY);
}
}
四、根据返回key值加密登陆
$scope.login = function() {
var loginParam = {
userName : encryptByPublicKey('admin', $scope.publicKey),
passWord : encryptByPublicKey('123456', $scope.publicKey)
};
$http.post('action/login?format=json&t='+Math.random(), loginParam, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(response, status, headers, config) {
...
}).error(function(data, status, headers, config) {
...
});
};
function encryptByPublicKey(input, publicKey){
setMaxDigits(76);
var keyPair = new RSAKeyPair(publicKey.exponent, '', publicKey.modulus);
var s = encryptedString(keyPair, input);
return s;
}
五、后台解密
protected void login(HttpServletRequest request) {
RSAPrivateKey privateKey = (RSAPrivateKey)request.getSession().getAttribute(RSAUtils.PRIVATE_KEY);
String username = getUsername(request);
String password = getPassword(request);
username = RSAUtils.decryptToString(privateKey, username);
password = RSAUtils.decryptToString(privateKey, password);
}