一个以ajax请求为主的应用,数据传输加密的解决方案

2 篇文章 0 订阅

首先是密钥交换的过程,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端解密:
$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 />");

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值