加密基礎(chǔ)知識四 前端JS加密傳輸 crypto-js

圖片發(fā)自簡書App

原文地址

一、使用HTTP簡單加密

對系統(tǒng)安全性要求比較高,那么需要選擇https協(xié)議來傳輸數(shù)據(jù)。當(dāng)然很多情況下一般的web網(wǎng)站,如果安全要求不是很高的話,用http協(xié)議就可以了。在這種情況下,密碼的明文傳輸顯然是不合適的,因為如果請求在傳輸過程中被截了,就可以直接拿明文密碼登錄網(wǎng)站了。

對于使用http協(xié)議的web前端的加密,只能防君子不能防小人。前端是完全暴露的,包括你的加密算法。 知道了加密算法,密碼都是可以破解的,只是時間問題。所以加密是為了增加破解的時間成本,如果破解需要花費的時間讓人難以接受,這也就達(dá)到了目的。

而為了保證數(shù)據(jù)庫中存儲的密碼更安全,則需要在后端用多種單向(非對稱)加密手段混合進(jìn)行加密存儲。前端加密后端又需要解密,所以需要對稱加密算法,即前端使用 encrypted = encrypt(password+key),后端使用 password = decrypt(encrypted +key) ,前端只傳輸密碼與key加密后的字符串encrypted ,這樣即使請求被攔截了,也知道了加密算法,但是由于缺少key所以很難破解出明文密碼。所以這個key很關(guān)鍵。而這個key是由后端控制生成與銷毀的,用完即失效,所以即使可以模擬用加密后的密碼來發(fā)請求模擬登錄,但是key已經(jīng)失效了,后端還是驗證不過的。

注意,如果本地環(huán)境本就是不安全的,key被知道了,那就瞬間就可以用解密算法破解出密碼了。這里只是假設(shè)傳輸?shù)倪^程中被截獲的情形。所以前端加密是防不了小人的。如果真要防,可以將加密算法的js文件進(jìn)行壓縮加密,不斷更新的手段來使js文件難以獲取,讓黑客難以獲取加密算法。變態(tài)的google就是這么干的,自己實現(xiàn)一個js虛擬機(jī),通過不斷更新加密混淆js文件讓加密算法難以獲取。這樣黑客不知道加密算法就無法破解了。

二、GOOGLE的JS加密算法庫crypto-js

https://github.com/brix/crypto-js下載,develop和master下載稍有區(qū)別。以MD5測試為例,只引入md5.js(未壓縮前為9K)會報錯,需要先引入core.js(未壓縮前為22K)。而在master分支下載的crypto-js,是所有加密算法合集(未壓縮前為188K),只需要引入這一個JS文件即可。

<head>
    <script type="text/javascript" src="core.js"></script>
    <script src="md5.js"></script>
</head>
<body>
</body>
<script>
var hash = CryptoJS.MD5("Message");
console.log("test:",hash.toString());
</script>

打印結(jié)果是test: 4c2a8fe7eaf24721cc7a9f0175115bd4,與網(wǎng)站上對照結(jié)果一致。

1.再來測試一下AES加密

var encrypt = getAES("Message");
console.log("encrypt:",encrypt);
var decrypt = getDAes(encrypt);
console.log("decrypt:",decrypt);

function getAesString(data,key,iv){//加密
    var key  = CryptoJS.enc.Utf8.parse(key);
    var iv   = CryptoJS.enc.Utf8.parse(iv);
    var encrypted =CryptoJS.AES.encrypt(data,key,
        {
            iv:iv,
            mode:CryptoJS.mode.CBC,
            padding:CryptoJS.pad.Pkcs7
        });
    return encrypted.toString();    //返回的是base64格式的密文
}
function getDAesString(encrypted,key,iv){//解密
    var key  = CryptoJS.enc.Utf8.parse(key);
    var iv   = CryptoJS.enc.Utf8.parse(iv);
    var decrypted =CryptoJS.AES.decrypt(encrypted,key,
        {
            iv:iv,
            mode:CryptoJS.mode.CBC,
            padding:CryptoJS.pad.Pkcs7
        });
    return decrypted.toString(CryptoJS.enc.Utf8);     
}

function getAES(data){ //加密
    var key  = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';  //密鑰
    var iv   = '1234567812345678';
    var encrypted =getAesString(data,key,iv); //密文
    var encrypted1 =CryptoJS.enc.Utf8.parse(encrypted);
    return encrypted;
}

function getDAes(data){//解密
    var key  = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';  //密鑰
    var iv   = '1234567812345678';
    var decryptedStr =getDAesString(data,key,iv);
    return decryptedStr;
}

輸出結(jié)果

encrypt: GtV+06AIR7HQ8Bm4pRHdGw==
decrypt: Message

key和iv我們都可以更換,但是需要保證的是加解密的key和vi保持一致

2.參考前端crypto-js AES加密 PHP后端解密

前端js

<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/md5.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/components/pad-zeropadding.js"></script>
<script>
    var key_hash = CryptoJS.MD5("Message");
    var key = CryptoJS.enc.Utf8.parse(key_hash);
    var iv  = CryptoJS.enc.Utf8.parse('1234567812345678');
    var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv,mode:CryptoJS.mode.CBC,padding:CryptoJS.pad.ZeroPadding});
    document.write("encode:"+encrypted);
</script>

php代碼

<?php
$text = "Message";
$key = md5($text);  //key的長度必須16,32位,這里直接MD5一個長度為32位的key
$iv='1234567812345678';
$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);
$decode = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $crypttext, MCRYPT_MODE_CBC, $iv);
echo base64_encode($crypttext);
echo "<br/>";
echo $decode;
echo "<br/>";
?>

3.實戰(zhàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。