_includes/encrypted.html in jekyll-zeta-0.9.4.4 vs _includes/encrypted.html in jekyll-zeta-0.9.5

- old
+ new

@@ -1,6 +1,34 @@ +<style> +.errPsw{ + animation: shake 0.4s cubic-bezier(0.25, 1.5, 0.5, 1); + border:solid 2px #f0ada0; + border-radius: 4px; +} + @keyframes shake { + 0% { + transform: translateX(0); + } + 20% { + transform: translateX(-15px); + } + 40% { + transform: translateX(10px); + } + 60% { + transform: translateX(-7px); + } + 80% { + transform: translateX(5px); + } + 100% { + transform: translateX(0); + } + } +</style> + <div id="encrypted"> <h3> {{ site.theme_config.encrypt_title | default : 'Content is Encrypted'}} </h3> <input style="width:100%; " type="password" id="passwordinput" placeholder="输入密码"></input> <p> @@ -24,16 +52,28 @@ <script> var exports = exports || {} </script> <script src="//cdn.jsdelivr.net/gh/vitock/jsdelivr@0.1.2/js/base64js.js"></script> <script> + +function uint8ArrayToHex(uint8Array) { + return Array.from(uint8Array) + .map(byte => byte.toString(16).padStart(2, '0')) // 转换每个字节为2位16进制 + .join(''); // 连接成字符串 +} + + + + {%- assign HEXKEY = '' | rand_bytes:32 %} + const contentEnc = '{{ content | encrypt_content_v2:HEXKEY }}'; + !function(){ const substl = crypto.subtle const preFix = '{{encid}}'; const encid = preFix - const encryptedContent = '{{ content | encrypt_content:page, encid}}' + const encryptedContent = contentEnc; const base64str = encryptedContent.substring(3) const bfMsg = base64js.decode(base64str) const bfIv = bfMsg.subarray(0,12) const bfCipher = bfMsg.subarray(12) @@ -45,15 +85,98 @@ name:"PBKDF2",hash: "SHA-256",iterations: 12345,salt: new TextEncoder().encode(salt) } return await substl.deriveBits(pbkdf2,key,256); } + async function decryptRaw(bf,key,outV){ + if(bf.length < 8){ + if(outV){ + outV.count = bf.length + } + throw 'err' + } + let count = 0; + for (let i = 0; i < 4; i ++) { + count |= ((bf[i] ^ bf[i + 4] ^ i) << ((3 - i) * 8)) + } + if(outV){ + outV.count = count + } + if (bf.length < count) { + return + } + + let bfIv = bf.slice(4,20) + let bfCipher = bf.slice(20,count ) + + var aeskey = { + name:"AES-CTR", + } + var keyObj = await substl.importKey('raw',key,aeskey,false,['decrypt']) + var aesDec= {name: "AES-CTR",counter:bfIv,length:64}; + try{ + let bfDec = await substl.decrypt(aesDec,keyObj,bfCipher) + return new Uint8Array(bfDec) + }catch (error) { + throw error + } + + } + async function decryptBase64Msg(msg64,key){ + const base64str = msg64; + const bfMsg = base64js.decode(base64str) + return await decryptRaw(bfMsg,key) + + } + async function checkKey(key){ + const keyData = "{{ '' | encrypt_key:page,HEXKEY ,encid}}"; + {% assign TestData = HEXKEY | gen_test_data_forkey %} + const arrTest = '{{ TestData }}'.split('.'); + const testData = arrTest[0]; + const testDataEnc = arrTest[1]; + const bfTestData = base64js.decode(testDataEnc) + + + const bfKeyData = base64js.decode(keyData) + let keyBf = null + let C = 0; + let sum = 0; + while (C ++ < 400 ) { + if (sum >= bfKeyData.length ) { + break + } + let bfSub = bfKeyData.slice(sum) + + try { + let outV = {count:0} + let d = await decryptRaw(bfSub,key,outV) + + sum += outV.count + if (d) { + let dec = await decryptRaw(bfTestData,d) + let s = new TextDecoder().decode(dec) + if(s == testData){ + keyBf = d; + break; + } + }else{ + + } + + + } catch (error) { + + } + } + + return keyBf + } + async function decrypt (key0,isCached){ // const key = Uint8Array([...]); // 32 bytes key - var key = '' if(isCached){ key = readKey() } else{ @@ -61,19 +184,16 @@ key = await genKey(keyS) } if (key.length == 0) { return } - - var aeskey = { - name:"AES-GCM", - length:256 - } - var keyObj = await substl.importKey('raw',key,aeskey,false,['decrypt']) - var aesDec= {name: "AES-GCM",iv:bfIv,tagLength:128} try { - var bfDec = await substl.decrypt(aesDec,keyObj,bfCipher) + let keyBf = await checkKey(key) + if(!keyBf){ + throw 'error psw' + } + var bfDec = await decryptBase64Msg(contentEnc,keyBf) var plain = new TextDecoder().decode(bfDec); setKey(key) document.getElementById("encrypted").style.display = 'none' // / show decrypted @@ -90,11 +210,16 @@ window.dispatchEvent(loadevent) window.dispatchEvent(DOMContentLoaded_event) }, 500); } catch (error) { - alert("wrong password.") + console.log(error) + // alert("wrong password.") + document.getElementById('passwordinput').classList.add('errPsw'); + setTimeout(() => { + document.getElementById('passwordinput').classList.remove('errPsw') + }, 500); } } document.getElementById("DecryptBtn").onclick = function(){ var key = document.getElementById("passwordinput").value @@ -119,23 +244,28 @@ clearKey() } document.getElementById("ClearBtn1").onclick = function(){ localStorage.clear(); + document.getElementById('passwordinput').value = '' } document.getElementById("ClearBtn2").onclick = function(){ localStorage.clear(); } - {%- if site.theme_config.forbid_cache_password %} + + + + + {% if site.theme_config.forbid_cache_password %} function readKey(){ } function setKey(value){ } function clearKey() { } - {%- else %} + {% else %} function readKey(){ var key = encid; var v = localStorage.getItem(key) if (v) { return base64js.decode(v) @@ -156,10 +286,14 @@ var cachekey = readKey() if(cachekey){ decrypt(cachekey,true) } - {%- endif %} + {% endif %} + + + }() + </script> \ No newline at end of file