一个以ajax请求为主的应用,数据传输加密的解决方案
2018-01-11 11:29
459 查看
首先是密钥交换的过程,Diffie-Hellman密钥交换算法参考维基百科的文档:
http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
client端js语言,服务端php语言 用DH密钥交换算法交换密钥。
var g = "2";
var p = "106025087133488299239129351247929016326438167258746469805890028339770628303789813787064911279666129";
function doStaff() {
var big_a = randBigInt(100);
var big_p = str2bigInt(p, 10, 0);
var big_g = str2bigInt(g, 10, 0);
var A = powMod(big_g, big_a, big_p);
var str_A = bigInt2str(A, 10);
var B;
var secret;
$.ajax({
url: 'server.php',
type: 'GET',
async: false,
data: {"A":str_A},
cache: false,
timeout: 5 * 1000,
dataType: 'json',
success: function(data, status, xhr) {
B = str2bigInt(data.B, 10, 0);
},
error: function() {
alert(2);
}
});
secret = powMod(B, big_a, big_p);
secret = bigInt2str(secret, 10);
上边的代码中,最后的到的secret,就是最终和服务端协商一致的密钥(这是一个很多位数字的字符串,我们的密钥使用16字节,那么我们可以考虑对它md5,作为对称加密的密钥)。
上述代码中big int相关的js,直接使用的一个开源的bigint.js(js代码有不开源的吗?^_^) 。 参见这里:http://leemon.com/crypto/BigInt.js
服务端php代码:
<?php
$g = "2";
$p = "106025087133488299239129351247929016326438167258746469805890028339770628303789813787064911279666129";
$b = "86410430023"; // TODO: change this to a random generated number.
$A = $_REQUEST['A'];
$B = bcpowmod($g, $b, $p);
$secret = bcpowmod($A, $b, $p);
echo '{"B":"' . $B .'"}';
?>
可见我们采用固定的g和p,这2个变量是公开的,不怕泄漏。
js端首先生成一个100bit长的整数a,并依据公式计算出A, 用ajax的形式发送到服务端php。 服务端收到A,自己生成变量b,依据公式计算出B,响应给客户端js。
此时,服务端和客户端分别可以依据公式计算出一个相同的secret。 这个secret没有在网络中传输过,双方可说是“心照不宣”,且双方自己选定的a和b是保密的,第三方无法根据公开传输的数据推算出a,b,当然也无法得到secret。 这就是DH算法的原理。
======================================================华丽的分割线========================================================
密钥交换完成后,我们假定双方拥有了对称加密的密钥。 接下来是一个AES算法的demo。 分别有js加密php解密,和反过来php加密js解密。
这里采用了一个js库,叫做crypt-js.它的官方地址是 http://code.google.com/p/crypto-js/#CryptoJS_3.1
js加密:
var pwd = "123456";
var key = CryptoJS.enc.Utf8.parse("96e79218965eb72c92a549dd5a330112"); //CryptoJS.MD5("111111");
var iv = CryptoJS.enc.Utf8.parse('1234567812345678');
var encrypted = CryptoJS.AES.encrypt(pwd, key, {iv:iv});
document.write(encrypted.toString());这里write出来的值,就是加密过后的密文,toString方法得到,按照crypto-js文档中说,是兼容openssl格式的可见文本形式。(加密通常得到的结果是byte数组,要以某种形式转换为可见字符,如base64,hex等方式。
这个形式转换也可以自定义)。
此值在php端解密:
php加密:
输出的结果是经过base64转换为可见字符的。
js解密:
http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
client端js语言,服务端php语言 用DH密钥交换算法交换密钥。
var g = "2";
var p = "106025087133488299239129351247929016326438167258746469805890028339770628303789813787064911279666129";
function doStaff() {
var big_a = randBigInt(100);
var big_p = str2bigInt(p, 10, 0);
var big_g = str2bigInt(g, 10, 0);
var A = powMod(big_g, big_a, big_p);
var str_A = bigInt2str(A, 10);
var B;
var secret;
$.ajax({
url: 'server.php',
type: 'GET',
async: false,
data: {"A":str_A},
cache: false,
timeout: 5 * 1000,
dataType: 'json',
success: function(data, status, xhr) {
B = str2bigInt(data.B, 10, 0);
},
error: function() {
alert(2);
}
});
secret = powMod(B, big_a, big_p);
secret = bigInt2str(secret, 10);
上边的代码中,最后的到的secret,就是最终和服务端协商一致的密钥(这是一个很多位数字的字符串,我们的密钥使用16字节,那么我们可以考虑对它md5,作为对称加密的密钥)。
上述代码中big int相关的js,直接使用的一个开源的bigint.js(js代码有不开源的吗?^_^) 。 参见这里:http://leemon.com/crypto/BigInt.js
服务端php代码:
<?php
$g = "2";
$p = "106025087133488299239129351247929016326438167258746469805890028339770628303789813787064911279666129";
$b = "86410430023"; // TODO: change this to a random generated number.
$A = $_REQUEST['A'];
$B = bcpowmod($g, $b, $p);
$secret = bcpowmod($A, $b, $p);
echo '{"B":"' . $B .'"}';
?>
可见我们采用固定的g和p,这2个变量是公开的,不怕泄漏。
js端首先生成一个100bit长的整数a,并依据公式计算出A, 用ajax的形式发送到服务端php。 服务端收到A,自己生成变量b,依据公式计算出B,响应给客户端js。
此时,服务端和客户端分别可以依据公式计算出一个相同的secret。 这个secret没有在网络中传输过,双方可说是“心照不宣”,且双方自己选定的a和b是保密的,第三方无法根据公开传输的数据推算出a,b,当然也无法得到secret。 这就是DH算法的原理。
======================================================华丽的分割线========================================================
密钥交换完成后,我们假定双方拥有了对称加密的密钥。 接下来是一个AES算法的demo。 分别有js加密php解密,和反过来php加密js解密。
这里采用了一个js库,叫做crypt-js.它的官方地址是 http://code.google.com/p/crypto-js/#CryptoJS_3.1
js加密:
var pwd = "123456";
var key = CryptoJS.enc.Utf8.parse("96e79218965eb72c92a549dd5a330112"); //CryptoJS.MD5("111111");
var iv = CryptoJS.enc.Utf8.parse('1234567812345678');
var encrypted = CryptoJS.AES.encrypt(pwd, key, {iv:iv});
document.write(encrypted.toString());这里write出来的值,就是加密过后的密文,toString方法得到,按照crypto-js文档中说,是兼容openssl格式的可见文本形式。(加密通常得到的结果是byte数组,要以某种形式转换为可见字符,如base64,hex等方式。
这个形式转换也可以自定义)。
此值在php端解密:
$iv='1234567812345678'; $key = "96e79218965eb72c92a549dd5a330112"; $data = "FBPJjTRA4MEkMcMDg7eOng=="; $data = base64_decode($data); $ttt = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv); echo "decrypted : $ttt";接下来的代码demo是php端加密, js解密。
php加密:
$svrMessage = "server message . .. adfasdfsdaf adfasdfsdaf"; $iv='1234567812345678'; $key = "96e79218965eb72c92a549dd5a330112"; $enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $svrMessage, MCRYPT_MODE_CBC, $iv); $enc = base64_encode($enc); echo "<br/>$enc";
输出的结果是经过base64转换为可见字符的。
js解密:
var received = "UQhDUzgusxZiejMuuVjh78BcpoQt82swQvSqyCvnuTdb3drBJTPghFBmTORflU6h"; var eee = CryptoJS.enc.Base64.parse(received); var ddd = CryptoJS.AES.decrypt({ ciphertext: CryptoJS.enc.Base64.parse(received), salt: "" }, key, {iv:iv}); document.write(ddd.toString(CryptoJS.enc.Utf8) + "<br />");
相关文章推荐
- jQuery 中 ajax 请求数据应用的一个小demo
- 关于Ajax请求中传输中文乱码问题的解决方案
- 同一个页面,发出ajax请求,经过controller,返回ModelAndView,数据显示不了
- ajax中如何将utf-8编码的数据请求发送到gbk编码应用的解决方法
- 关于分页插件pagination的应用及遇到的问题(用ajax请求数据进行拼接后分页显示)
- 使用3DES+Base64来加密传输iOS应用数据
- jQuery 中 ajax 提交数据应用的一个小demo
- AJAX请求数据步骤是什么?传输的数据是用的暗文还是明文?
- Ajax数据传输的一个问题
- Ajax:跨域请求接口数据时无法设置同步的一种解决方案
- ajax中如何将utf-8编码的数据请求发送到gbk编码应用的解决方法
- ajax+json进行数据传输请求(ssm框架)
- 分布式架构项目中各模块中页面发送ajax请求后台json数据的传输问题
- AJAX传输数据的中文乱码之完全解决方案
- JSP和Servlet互相传输数据的过程中产生的乱码问题及解决方案(没有使用AJAX的情况)
- Ajax数据传输的一个问题
- 浅谈Vue.js应用的四种AJAX请求数据模式
- 用.Net打造一个移动客户端(Android/IOS)的服务端框架NHM(二)——“请求”“交互”与传输数据(服务器端)
- 浏览器在一次 HTTP 请求中,需要传输一个 4097 字节的文本数据给服务端,可以采用那些方式?
- AJAX传输数据的中文乱码之完全解决方案