在普通的页面提交时,如果没有使用SSL,提交的数据将使用纯文本的方式发送。如果使用抓包工具可以轻易地截获一些关键数据。

jCryption是一个jQuery插件,能够加密由Forms提交的POST/GET数据。官网地址:​​http://www.jcryption.org/​

 

未加密处理的效果如下:可很容易地看到登录时的用户名和口令。

客户端JavaScript加密数据,服务端Java解密数据_加密

 

使用jCryption后效果如下,提交的数据为密文。

客户端JavaScript加密数据,服务端Java解密数据_java_02

 

本例中服务端使用Java进行解密,使用了一个开源项目JavaCription,官网地址:​​https://jcryptionforjava.wordpress.com/​​。实现了针对jCryption2.0的Java解密。

处理机制如下:

1、客户端从服务端请求一个RSA公钥

2、客户端产生一个随机数作为AES密钥,用RSA公钥进行加密,发送到服务端

3、服务端用RSA私钥进行解密,同时将AES密钥保持到会话中

4、服务端用AES算法加密AES密钥并送回给客户端

5、客户端用AES算法解密,并与本地保存的AES密钥做比对,如果相符就认为服务端是合法的

6、客户端提交数据,数据用AES密钥进行加密

在此版本里为提供效率,只使用RSA非对称算法进行密钥交换,数据的加解密使用AES对称算法。

 

客户端

引入两个js文件

<script type="text/JavaScript" src="js/jquery-2.1.3.min.js"></script>

<script type="text/javascript" src="js/jquery.jcryption.js"></script>

表单加密,设定两个地址:1)获取公钥 2)握手交换AES密钥

<script type="text/javascript">

$(function() {

$("#form1").jCryption();

});

$.jCryption.defaultOptions.getKeysURL="encrypt?generateKeyPair=true";

$.jCryption.defaultOptions.handshakeURL="encrypt?handshake=true";

</script>

 

服务端

密钥服务Servlet



public class CryptoServlet extends HttpServlet{
/**
* serialVersionUID
*/
private static final long serialVersionUID = 4510110365995157499L;

/**
* Handles a POST request
*
* @see HttpServlet
*/
public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

/** Generates a KeyPair for RSA **/
if (req.getParameter("generateKeyPair") != null && req.getParameter("generateKeyPair").equals("true")) {

JCryption jc = new JCryption();
KeyPair keys = jc.getKeyPair();
request.getSession().getServletContext().setAttribute("jCryptionKeys", keys);
String e = jc.getPublicExponent();
String n = jc.getKeyModulus();
String md = String.valueOf(jc.getMaxDigits());

/** Sends response **/
PrintWriter out = response.getWriter();
out.print("{\"e\":\"" + e + "\",\"n\":\"" + n + "\",\"maxdigits\":\"" + md + "\"}");
return;
}
/** jCryption handshake **/
else if (req.getParameter("handshake") != null && req.getParameter("handshake").equals("true")) {

/** Decrypts password using private key **/
JCryption jc = new JCryption((KeyPair) request.getSession().getServletContext()
.getAttribute("jCryptionKeys"));
String a = req.getParameter("key");
System.out.println(a);
String key = jc.decrypt(req.getParameter("key"));

request.getSession().getServletContext().removeAttribute("jCryptionKeys");
request.getSession().getServletContext().setAttribute("jCryptionKey", key);

/** Encrypts password using AES **/
String ct = AesCtr.encrypt(key, key, 256);

/** Sends response **/
PrintWriter out = response.getWriter();
out.print("{\"challenge\":\"" + ct + "\"}");

return;
}
/** jCryption request to decrypt a String **/
else if (req.getParameter("decryptData") != null && req.getParameter("decryptData").equals("true")
&& req.getParameter("jCryption") != null) {

/** Decrypts the request using password **/
String key = (String) request.getSession().getServletContext().getAttribute("jCryptionKey");

String pt = AesCtr.decrypt(req.getParameter("jCryption"), key, 256);

/** Sends response **/
PrintWriter out = response.getWriter();
out.print("{\"data\":\"" + pt + "\"}");
return;
}
/** jCryption request to encrypt a String **/
else if (req.getParameter("encryptData") != null && req.getParameter("encryptData").equals("true")
&& req.getParameter("jCryption") != null) {

/** Encrypts the request using password **/
String key = (String) request.getSession().getServletContext().getAttribute("jCryptionKey");

String ct = AesCtr.encrypt(req.getParameter("jCryption"), key, 256);

/** Sends response **/
PrintWriter out = response.getWriter();
out.print("{\"data\":\"" + ct + "\"}");
return;
}
/** A test request from jCryption **/
else if (req.getParameter("decryptTest") != null && req.getParameter("decryptTest").equals("true")) {

/** Encrypts a timestamp **/
String key = (String) request.getSession().getServletContext().getAttribute("jCryptionKey");

String date = DateFormat.getInstance().format(new Date());

String ct = AesCtr.encrypt(date, key, 256);

/** Sends response **/
PrintWriter out = response.getWriter();
out.print("{\"encrypted\":\"" + ct + "\", \"unencrypted\":\"" + date + "\"}");
return;
}
}

/**
* Handles a GET request
*
* @see HttpServlet
*/
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
doPost(req, res);
}
}


 

过虑器,进行数据解密

 

密文:5QN8EsTjylTGSyvrmYGXDUD/MjF3qcl58pZtI7xhCk5HMUYFjf7kJe/leQLAuqzW4dPUNw==

明文:loginName=admin&password=admin&Submit=提交



public class SecureFilter implements Filter{
private FilterConfig conf;

public void destroy() {
// TODO Auto-generated method stub

}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
String jCryption = request.getParameter("jCryption");
System.out.println(jCryption);
String key = (String) conf.getServletContext().getAttribute("jCryptionKey");

String source = AesCtr.decrypt(jCryption, key, 256);
System.out.println(source);

String[] params = source.split("&");
for(int i=0;i<params.length;i++){
String [] aparam = params[i].split("=");
request.setAttribute(aparam[0], aparam[1]);
}

chain.doFilter(request, response);

}

public void init(FilterConfig filterConfig) throws ServletException {
this.conf = filterConfig;

}

}


 

处理器,从request.getAttribute中获取数据



String loginName = passwordAuthcInfo.getLoginName();
String loginPassword = passwordAuthcInfo.getPassword();
if(loginName == null && loginPassword == null){
loginName = (String)request.getAttribute("loginName");
loginPassword = (String)request.getAttribute("password");
}