_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