利用crypto-js实现静态网页数据加密

crypto-js是什么

使用crypto-js也是很久之前的事了,一直都没有好好整理,今天借助博客重构的机会,好好捋一下。crypto-js是一个加密算法库,支持哈希算法,如:MD5、SHA-1、SHA-2、SHA-3、RIPEMD-160也支持多种加密方式,如:AES、DES, Triple DES、Rabbit、RC4, RC4Drop。可实现多种多样的加密算法。

使用

github.com/brix/crypto-js 上引入相关文件,因为我只需要使用aes加密算法,所以没有引入整个库而是只下载了aes.js单个文件。 借助强大的crypto-js,我们只需要几行代码就可以实现加密效果,下面是一个使用aes加密的demo,效果为在页面加密字符串“123456”,并解密加密的密文。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./aes.js"></script>
</head>

<body>
    <script>
        //aes加密
        function encrypt(word) {
            var key = CryptoJS.enc.Utf8.parse("1234560000000000"); //16位
            var iv = CryptoJS.enc.Utf8.parse("1234567890000000");
            var encrypted = '';
            if (typeof (word) == 'string') {
                var srcs = CryptoJS.enc.Utf8.parse(word);
                encrypted = CryptoJS.AES.encrypt(srcs, key, {
                    iv: iv,
                    mode: CryptoJS.mode.CBC,
                    padding: CryptoJS.pad.Pkcs7
                });
            } else if (typeof (word) == 'object') { //对象格式的转成json字符串
                data = JSON.stringify(word);
                var srcs = CryptoJS.enc.Utf8.parse(data);
                encrypted = CryptoJS.AES.encrypt(srcs, key, {
                    iv: iv,
                    mode: CryptoJS.mode.CBC,
                    padding: CryptoJS.pad.Pkcs7
                })
            }
            return encrypted.ciphertext.toString();
        }
        // aes解密
        function decrypt(word) {
            var key = CryptoJS.enc.Utf8.parse("1234560000000000");
            var iv = CryptoJS.enc.Utf8.parse("1234567890000000");
            var encryptedHexStr = CryptoJS.enc.Hex.parse(word);
            var srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
            var decrypt = CryptoJS.AES.decrypt(srcs, key, {
                iv: iv,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
            });
            var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
            return decryptedStr.toString();
        }
    </script>
    <script>
        var str = "123456";
        var encrypted = encrypt(str);
        var decrypt1 = decrypt(encrypted.toString());
        document.writeln("aes cbc 加密 解密");
        document.writeln("<br/>");
        document.writeln("待加密:" + str);
        document.writeln("<br/>");
        document.writeln("加密的密文:".concat(encrypted));
        document.writeln("<br/>");
        document.writeln("解密密文的结果:" + decrypt1);
    </script>
</body>

</html>

代码效果如下图

其他应用

借助crypto-js还可以实现一些很好玩的加密,例如静态页面文章的加密。出于某种原因我的文章“造谣人士生平事”之前就使用了这种加密方式。 判断文章标题是“加密”开头后,就引入aes.js文件

<script>
        
        var postTitleValue = document.querySelector(".post-title").innerHTML.trim();
        if (postTitleValue.slice(0, 2) === "加密") {

            var oScript = document.createElement("script");
            oScript.src = "./aes.js";
            document.body.appendChild(oScript);
        }
    </script>

引入aes.js后添加密钥和密钥偏移量输入框,添加加密解密函数,添加点击事件。默认的密钥和密码偏移量都为"1234560000000000",但是千万不要使用默认密码和密钥,最方便的做法是使用在线随机数生成工具生成随机密钥和随机密钥偏移量。

//aes加密
function encrypt(word, keyy, ivv) {
    var key = keyy ? CryptoJS.enc.Utf8.parse(keyy) : CryptoJS.enc.Utf8.parse("1234560000000000"); //16位
    var iv = ivv ? CryptoJS.enc.Utf8.parse(ivv) : CryptoJS.enc.Utf8.parse("1234567890000000");
    var encrypted = '';
    if (typeof (word) == 'string') {
        var srcs = CryptoJS.enc.Utf8.parse(word);
        encrypted = CryptoJS.AES.encrypt(srcs, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
    } else if (typeof (word) == 'object') { //对象格式的转成json字符串
        data = JSON.stringify(word);
        var srcs = CryptoJS.enc.Utf8.parse(data);
        encrypted = CryptoJS.AES.encrypt(srcs, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        })
    }
    return encrypted.ciphertext.toString();
}
// aes解密
function decrypt(word, keyy, ivv) {
    var key = keyy ? CryptoJS.enc.Utf8.parse(keyy) : CryptoJS.enc.Utf8.parse("1234560000000000");
    var iv = ivv ? CryptoJS.enc.Utf8.parse(ivv) : CryptoJS.enc.Utf8.parse("1234567890000000");
    var encryptedHexStr = CryptoJS.enc.Hex.parse(word);
    var srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    var decrypt = CryptoJS.AES.decrypt(srcs, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr.toString();
}
var lock = document.createElement("div"),
    input = document.createElement("input"),
    inputIvv = document.createElement("input"),
    btn1 = document.createElement("button"),
    btn2 = document.createElement("button"),
    markdown = document.querySelector(".markdown-body");
    markdown.style.display="none"
lock.id = "lock";
input.id = "lock-input";
inputIvv.id = "lock-inputIvv";
input.type="password";
inputIvv.type="password";
btn1.id = "lock-btn1";
btn2.id = "lock-btn2";
btn1.innerHTML = "解密";
btn2.innerHTML = "加密";
document.body.appendChild(lock);
lock.appendChild(input);
lock.appendChild(inputIvv);
lock.appendChild(btn1);
lock.appendChild(btn2);

btn1.onclick = function () {
    var keyy = input.value;
    var ivv = inputIvv.value;
    var markdownValue = markdown.innerHTML.trim();
    //去除生成干扰,我的文章每次生成会自动包一层div,这一步是为了保证密文永不改变内容,你们不需要这一步
    var str = markdownValue.slice(3,-4);
    console.log(str);
    var decr = decrypt(str.toString(), keyy, ivv);
    markdown.innerHTML = decr.trim();
    markdown.style.display="block"
}
btn2.onclick = function () {
    var keyy = input.value;
    var ivv = inputIvv.value;
    var markdownValue = markdown.innerHTML.trim();
    var str = markdownValue;
    var decr = encrypt(str.toString(), keyy, ivv);
    markdown.innerHTML = decr.trim();
    markdown.style.display="block"
}

加密输入框的css,使用了页面压缩,看起来比较乱。

#lock{overflow:hidden;width:248px;position:absolute;left:50%;top:230px;margin-left:-100px}#lock-btn1,#lock-btn2{margin-left:31.5px;float:left;display:block;width:60px;height:20px;border-radius:20px;background-color:transparent;color:#000;-webkit-transition:all 150ms linear;-moz-transition:all 150ms linear;-o-transition:all 150ms linear;-ms-transition:all 150ms linear;transition:all 150ms linear;font-size:14px;font-weight:normal;text-align:center;border:1px solid #66615b}#lock-btn2{margin-left:61.5px}#lock-btn1:hover,#lock-btn2:hover{background-color:#66615b;color:rgba(255,255,255,0.7);border-color:#66615b}#lock-input,#lock-inputIvv{border-radius:20px;outline:0;padding:0 10px;width:100px;height:20px;background:transparent;color:#000;font-size:1.25em;float:left}#lock-input:hover,#lock-inputIvv:hover{background-color:#66615b;color:rgba(255,255,255,0.7);border-color:rgba(255,255,255,0.7)}

每次需要发布加密的文章时,将文章标题命名为”加密.XXX“,页面就会出现加密解密框,首次发布请输入密钥和密钥偏移量 点击加密,拿到密文。然后将文章内容改为密文。保存好你的密钥和密钥偏移量,以后查看加密文章时,输入密钥和密钥偏移量 点击解密,即可看到原始的文章。 代码效果如下两图