Tip
通过本文,你将了解:
- 如何更方便的使用Li4n0/hugo_encryptor
- “PY_SSIZE_T_CLEAN macro must be defined for ‘#’ formats” 报错的解决方法
- 简易修改
Note
建议先参考本文利用Github Action
将博客部署到Github Page
上获得最佳体验。
前言
博客偶尔想放些涉及个人生活比较深入的东西,但又只希望与接触比较深的人或者部分相关人士查看。这种情况下设置个大家心知肚明的密码最好。
原理
简单来说,hugo-encryptor
加密流程如下:
- 利用
shortcode
渲染待加密内容 - 用一段python程序对渲染结果(
/public
文件夹下所有文件)进行匹配,加密待加密内容 - 部署
因此,如果只是配置了shortcode而没有运行加密程序的话,文章内容不会被加密。而具体配置过程也因此分成了
配置主题
、配置部署
两部分。
为主题引入hugo_encryptor
原作者给出的办法个人感觉不是很好看:
|
|
我更倾向于将其直接放入主题中去,我的方法如下:
找到主题对应的
layouts/partials/shortcodes
文件夹,在里面新建一个文件夹hugo-encryptor.html
。将以下代码复制粘贴入其中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
{{ $_hugo_config := `{ "version": 1 }` }} {{/* ## Hugo Encrypt ### Params: - `password`: require param - Simple <div class="hugo-encryptor-container"> <div class="hugo-encryptor-prompt"> <p>文章的部分内容被密码保护:</p> </div> <div class="hugo-encryptor-form"> <input class="hugo-encryptor-input" placeholder='请输入密码' /> <input class="hugo-encryptor-button" type="button" value='点击验证' onclick="_click_handler(this)" /> </div> <div class="hugo-encryptor-cipher-text" data-password="your password" style="display: none;" > <span style="display: none;">--- DON'T MODIFY THIS LINE ---</span> <p>your content</p> </div> </div> */}} {{/* DEFAULTS */}} <div class="hugo-encryptor-container"> <div class="hugo-encryptor-prompt"> {{ if eq .Site.Params.hugoEncryptorLanguage "en-us" }} <p>Part of this article is encrypted with password:</p> {{ else }} <p>文章的部分内容被密码保护:</p> {{ end }} </div> <div class="hugo-encryptor-form"> <input class="hugo-encryptor-input" placeholder='{{ if eq .Site.Params.hugoEncryptorLanguage "en-us" }}Please input the password{{ else }}请输入密码{{ end }}' /> <input class="hugo-encryptor-button" type="button" value='{{ if eq .Site.Params.hugoEncryptorLanguage "en-us" }}Click to verify{{ else }}点击验证{{ end }}' onclick="_click_handler(this)" /> </div> <div class="hugo-encryptor-cipher-text" data-password="{{ .Get 0 }}" style="display: none;" > <span style="display: none;">--- DON'T MODIFY THIS LINE ---</span> {{ .Inner }} </div> </div>
找到主题对应header部分的模板,在其末尾添加:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script> <script> const _do_decrypt = function (encrypted, password) { let key = CryptoJS.enc.Utf8.parse(password); let iv = CryptoJS.enc.Utf8.parse(password.substr(16)); let decrypted_data = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); return decrypted_data.toString(CryptoJS.enc.Utf8); }; const _click_handler = function (element) { let parent = element.parentNode.parentNode; let encrypted = parent.querySelector( ".hugo-encryptor-cipher-text").innerText; let password = parent.querySelector( ".hugo-encryptor-input").value; password = CryptoJS.MD5(password).toString(); let index = -1; let elements = document.querySelectorAll( ".hugo-encryptor-container"); for (index = 0; index < elements.length; ++index) { if (elements[index].isSameNode(parent)) { break; } } let decrypted = ""; try { decrypted = _do_decrypt(encrypted, password); } catch (err) { console.error(err); alert("Failed to decrypt."); return; } if (!decrypted.includes("--- DON'T MODIFY THIS LINE ---")) { alert("Incorrect password."); return; } let storage = localStorage; let key = location.pathname + ".password." + index; storage.setItem(key, password); parent.innerHTML = decrypted; } window.onload = () => { let index = -1; let elements = document.querySelectorAll( ".hugo-encryptor-container"); while (1) { ++index; let key = location.pathname + ".password." + index; let password = localStorage.getItem(key); if (!password) { break; } else { console.log("Found password for part " + index); let parent = elements[index]; let encrypted = parent.querySelector(".hugo-encryptor-cipher-text").innerText; let decrypted = _do_decrypt(encrypted, password); elements[index].innerHTML = decrypted; } } }; </script>
Warning
请注意,此时文章还未被加密,需完成python的配置才行。
配置部署
Note
建议先参考本文利用Github Action
将博客部署到Github Page
上获得最佳体验。本地运行属实麻烦,下文假设你使用Github Action
将博客部署到Github Page
上。
hugo-encryptor
的工作原理:- 利用
shortcode
渲染待加密内容 - 用一段python程序对渲染结果(
/public
文件夹下所有文件)进行匹配,加密待加密内容 - 部署
在上一小节中,我们已经实现了1. 利用
shortcode渲染待加密内容
,而由于我们使用Github Action
,我们可以将23两步结合起来,实现全自动加密,避免忘记运行加密程序导致隐私泄漏。
步骤如下:
- 在博客仓库创建一个文件夹
hugo_encryptor
,将Li4n0/hugo_encryptor中的hugo-encryptor.py
与requirements.txt
放入其中。 - 对原有的部署工作流如此修改:
|
|
其中,python版本选择3.9
最佳,3.10
及以上会报错:PY_SSIZE_T_CLEAN macro must be defined for '#' formats
。此时可以选择以下两种做法:
- 回退
3.9
版本python(推荐) - 重新用pip卸载再安装
pycryptodome
库
至此,基本配置结束。
|
|
为encryptor添加密码提示
为了让目标受众知道我设置的密码是什么,有必要增加密码提示功能,这比较简单,只需将
|
|
改为
|
|
即可。最终成果如下所示(密码hugo)。
文章的部分内容被密码保护,提示 “此博客用的框架”: