js与php互相加解密抵抗截包侦测

虽然有https加持,但防止中间劫持,但是我还是想加密通迅内容,

例如一些敏感且重要信息。

方案,本来想用seajs或umi.js或angularjs等等动态加载执行的,但为了节约,我就换以下方案:

假设要访问的是https://localhost/my.php

使用一个read.php?f=my.php使用curl远程访问my文件加密下发,通过解密js+pjax重载网页,后面有示例代码

pjax魔改 + php端openssl_encrypt + js端crypto-js + aes

环境要求

php端 mcrypt_encrypt 或者 openssl_encrypt

js端 jquery 并且crypto-js

如果动态加载Js模块,那么需要require.js,比如CryptoJS = require("crypto-js")

http://requirejs.org/docs/download.html

否则使用 <script src="crypto-js.js"></script>

文件结构和说明:

js/crypto-js.js 用于js加解密
js/aes.js 是cryptojs包里有的东西
js/jquery.min.js 所有前端都需要的东西
js/jquery.pjax.js 无白屏无感加载网页
js/nprogress.js 用于pjax进度显示
css/nprogress.css
js/require.js 可选
index.php 用来显示主页
my.php 用来测试
read.php 主要是这,加密下发

各文件下载地址, 其中aes在crypto-js包里

https://github.com/brix/crypto-js/releases

https://github.com/jquery/jquery

https://github.com/defunkt/jquery-pjax

https://github.com/rstacruz/nprogress

https://github.com/requirejs/requirejs

其中只有jquery-pjax.js我们需要修改,用编辑器打开修改

查找 function extractContainer 函数定义

开始几行改成以下几行代码

function extractContainer(endata, xhr, options) {
  var obj = {}
  //接收read.php内容解密
  var data=decodeaescontent(endata)

新增一个函数

function decodeaescontent(endata)
{
    var base64arr = endata.split('@')
    var key = CryptoJS.enc.Utf8.parse('0000111122223333')
    var iv = CryptoJS.enc.Base64.parse(base64arr[0])
    var ciphertext = base64arr[1]
    var bytes = CryptoJS.AES.decrypt(ciphertext.toString(), key, { iv: iv, padding: CryptoJS.pad.ZeroPadding })
    return bytes.toString(CryptoJS.enc.Utf8);
}

read.php 接管代码

<?php
function curl_file_get_contents($durl){
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $durl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ;
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ;
    $data = curl_exec($ch);
    curl_close($ch);
    return $data;
}
//获取路径如https://localhost/[your dir]
$url='https://'.$_SERVER['HTTP_HOST'].$_SERVER["REQUEST_URI"]; 
$fullurl=dirname($url)."/".$_GET['f'];
//访问https://localost/my.php
$text = curl_file_get_contents($fullurl);
//与js端对应的密码16位字符
$key = "0000111122223333";
//高于php7.3+使用
function encodePageByOpenssl($key,$text)
{
    $isStrong=false;
    $ivLength = openssl_cipher_iv_length('aes-128-cbc');
    $iv = openssl_random_pseudo_bytes($ivLength, $isStrong);
    $ciphertext = openssl_encrypt($text, 'aes-128-cbc', $key, true, $iv);
    $msgBase64 = trim(base64_encode($ciphertext));
    return base64_encode($iv)."@".$msgBase64;
}
//低于php7.3使用
function encodePageByMcrypt($key,$text)
{
    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
    $ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);
    $msgBase64 = trim(base64_encode($ciphertext));
    return base64_encode($iv)."@".$msgBase64;
}

echo encodePageByMcrypt($key,$text);
 ?>

其它简单代码

index.php

<!DOCTYPE html>
<html lang="en">
<head>
<title>测试</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel='stylesheet' type="text/css" href="css/nprogress.css"/>
</head>
<body>
<a hfef="read.php?f=my.php">访问mypage</a>
<div id="loadwrap">
在这里重载内容,我是主页,注意相关js或css也应该在loadwrap定义内
</div>
<script src='js/jquery.min.js'></script>
<script src="js/crypto-js.js"></script>
<script src="js/aes.js"></script>
<script src="js/jquery.pjax.js"></script>
<script src='js/nprogress.js'></script>
<script type="text/javascript">
//jquery.pjax.js
$(document).pjax('a[target!=_blank]', '#loadwrap',{
    type:'post',
    scrollTo:false,
    fragment: '#loadwrap',
    timeout: 8000
});
$(document).on('pjax:start', function() { NProgress.start(); });
$(document).on('pjax:end',   function() { NProgress.done();  });
$(document).on('pjax:click', function() {
    enable_loading = false;
})
$(document).on('pjax:send', function(){
    var str = "<p class='tc mt-10'>加载中...</p>";
    $(".loading").css("display", "block");
    $('#loadwrap').html(str);
})
$(document).on('pjax:complete', function() {
    //回调函数
    $("img[src$=jpg],img[src$=jpeg],img[src$=png],img[src$=gif]").parent("a[class!=noview]").addClass("swipebox");
    if( $('pre').length ){ prettyPrint(); } 
    //回调函数解决文章页代码不高亮的问题
    $(".loading").css("display", "none");
    //pjax加载结束的回调函数 解决js无法定位的问题
    //重新定位容器内容的函数写在这里
});
//清除过期缓存
if (!!window.localStorage) {
    for (var key in localStorage) {
        try {
            if ((key.split("_") || [""])[0] === "pjax") {
                var item = localStorage.getItem(key);
                if (item) {
                    item = JSON.parse(item);
                    if ((parseInt(item.time) + 600 * 1000) <= new Date * 1) {
                        localStorage.removeItem(key)
                    }
                }
            }
        } catch (e) { }
    }
}
</script>
</body>
</html>

my.php和index.php相似内容不同而已

<!DOCTYPE html>
<html lang="en">
<head>
<title>测试</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel='stylesheet' type="text/css" href="css/nprogress.css"/>
</head>
<body>
<a hfef="read.php?f=index.php">主页</a>
<a hfef="read.php?f=my.php">访问mypage</a>
<div id="loadwrap">
在这里重载内容,我是my,注意相关js或css也应该在loadwrap定义内
</div>
<script src='js/jquery.min.js'></script>
<script src="js/crypto-js.js"></script>
<script src="js/aes.js"></script>
<script src="js/jquery.pjax.js"></script>
<script src='js/nprogress.js'></script>
<script type="text/javascript">
//jquery.pjax.js
$(document).pjax('a[target!=_blank]', '#loadwrap',{
    type:'post',
    scrollTo:false,
    fragment: '#loadwrap',
    timeout: 8000
});
$(document).on('pjax:start', function() { NProgress.start(); });
$(document).on('pjax:end',   function() { NProgress.done();  });
$(document).on('pjax:click', function() {
    enable_loading = false;
})
$(document).on('pjax:send', function(){
    var str = "<p class='tc mt-10'>加载中...</p>";
    $(".loading").css("display", "block");
    $('#loadwrap').html(str);
})
$(document).on('pjax:complete', function() {
    //回调函数
    $("img[src$=jpg],img[src$=jpeg],img[src$=png],img[src$=gif]").parent("a[class!=noview]").addClass("swipebox");
    if( $('pre').length ){ prettyPrint(); } 
    //回调函数解决文章页代码不高亮的问题
    $(".loading").css("display", "none");
    //pjax加载结束的回调函数 解决js无法定位的问题
    //重新定位容器内容的函数写在这里
});
//清除过期缓存
if (!!window.localStorage) {
    for (var key in localStorage) {
        try {
            if ((key.split("_") || [""])[0] === "pjax") {
                var item = localStorage.getItem(key);
                if (item) {
                    item = JSON.parse(item);
                    if ((parseInt(item.time) + 600 * 1000) <= new Date * 1) {
                        localStorage.removeItem(key)
                    }
                }
            }
        } catch (e) { }
    }
}
</script>
</body>
</html>

你可以上github下载这些演示文件

https://github.com/venski/php-js-crypto

点赞