Hugo 加密文章简单尝试
目录
警告
本文最后更新于 2024-02-24,文中内容可能已过时。
关于 Hugo 加密文章的简单尝试。
前言
我在使用 Hexo 的时候,注意到有一些加密文章相关插件。加密文章,在 Wordpress 等等有服务器支持的博客程序中是一个比较容易实现的功能,用户把密码口令发送到服务器验证,然后返回相关资源。但是静态博客,无后端的情况下,解密过程是在前端的,也就是无法对尝试次数之类的进行任何限制。这其实并不算很安全的一种方案。
即使如此也有其用途。在 Hexo 插件中,使用方法就是在文章 Metadata 加上一些字段就行了。也就说这种方法如果想保密不能公开源码。在 Hugo 这里要麻烦一些,Hugo 本身似乎并没有提供插件功能,也没有不修改源码就增加内置函数的功能。倒是找到了使用 python 处理的一些方法。
因此,我进行了以下尝试。
- 把所有需要加密的初始文本片段,加入一个被 git 忽略的文件夹。
- 运行一个脚本,或者手动使用加密工具加密,然后生成的密文填入一个 txt 文件中。
- 生成的加密文件作为静态文件附件公开,一同随网站发布。
- 写了个 Hugo 的 Shortcode 用于生成用户端解密显示,填入加密文件 URL 。
Demo
这样在使用前端效果如下,口令是 hi
我使用的加密算法是 Xxtea ,这是一个很容易实现的算法。就博客文章加密场景,或许一个异或运算加密就足够了,这样能少引入一个 js 。不过 Xxtea 在网络上也有不少现成的加解密工具可以使用,也挺不错的。
Hugo shortcode 代码贴在下面,或者在我网站源码里也能找到。引入的 js 在 https://github.com/xxtea/xxtea-js
代码
Shortcode 代码
{{- $url := .Get "url" -}}
{{- $md5Hash := md5 $url -}}
{{- $md5Short := substr $md5Hash 0 8 -}}
<div id="{{- $md5Short -}}-bar" style="display: none;">
<input id="password" placeholder="请输入口令..."></input>
<div><button id="submitBtn">解密</button></div>
</div>
<div id="{{- $md5Short -}}">
</div>
<script type="text/javascript" src="https://cdn.ftls.xyz/js/crypto/xxtea.js"></script>
<script>
const msg = document.getElementById("{{- $md5Short -}}");
const submitBtn = document.getElementById("submitBtn");
let newText = "";
function getNewText() {
fetch("{{ $url }}")
.then(response => response.text())
.then(text => {
console.log("加载密文: " + text);
msg.innerHTML = "已加载密文";
newText = text;
document.getElementById("{{- $md5Short -}}-bar").style.display = "block";
});
}
getNewText();
submitBtn.addEventListener("click", () => {
const password = document.getElementById("password").value;
console.log("口令: " + password, "密文: " + newText);
try {
let decrypt_data = XXTEA.decryptFromBase64(newText.trim(), password);
msg.innerHTML = decrypt_data;
} catch (error) {
msg.innerHTML = "口令错误";
}
});
</script>
一个加密小程序,可以使用 Deno 运行
// XXTEA 方法 XXTEA.encryptToBase64 XXTEA.decryptFromBase64
// https://github.com/xxtea/xxtea-js MIT license
// https://github.com/zhaidw/xxtea-ts MIT license
import XXTEA from "https://deno.land/x/xxtea@v0.1.0/mod.ts";
const fileName = "README.md";
const text = Deno.readTextFileSync(fileName);
const encrypted = XXTEA.encryptToBase64(text, "password");
Deno.writeTextFileSync(fileName + ".xxtea.txt", encrypted);
// deno run --allow-read --allow-write test.js
或者将一个文件夹内的文本文件,批量加密
// deno run --allow-read --allow-write xxtea-utils.ts
console.log("XXTEA 加密 CLI")
console.log(Deno.args);
import XXTEA from "https://deno.land/x/xxtea@v0.1.0/mod.ts";
const basePath = ""
const inputFilesPath = basePath + "kkbt/xxtea/"
for (const file of Deno.readDirSync(inputFilesPath)) {
console.log(file.name);
if (file.isFile) {
const text = Deno.readTextFileSync(inputFilesPath + file.name)
const data = XXTEA.encryptToBase64(text, "password");
Deno.writeTextFileSync(basePath + "kkbt/xxtea/output/" + file.name + ".xxtea.txt", data);
}
}
欢迎赞赏~
赞赏