惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Help Net Security
Help Net Security
宝玉的分享
宝玉的分享
Microsoft Security Blog
Microsoft Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
A
About on SuperTechFans
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
量子位
博客园 - 叶小钗
Last Week in AI
Last Week in AI
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
V2EX
D
DataBreaches.Net
Vercel News
Vercel News
博客园 - Franky
Recorded Future
Recorded Future
B
Blog RSS Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
GbyAI
GbyAI
M
MIT News - Artificial intelligence
F
Full Disclosure
S
SegmentFault 最新的问题
L
LangChain Blog
F
Fortinet All Blogs
美团技术团队
IT之家
IT之家
博客园 - 司徒正美
Cyberwarzone
Cyberwarzone
NISL@THU
NISL@THU
P
Privacy International News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Y
Y Combinator Blog
C
Check Point Blog
The GitHub Blog
The GitHub Blog
L
Lohrmann on Cybersecurity
I
Intezer
I
InfoQ
Spread Privacy
Spread Privacy
Project Zero
Project Zero
T
Threatpost
S
Secure Thoughts
C
Comments on: Blog
N
News | PayPal Newsroom
Application and Cybersecurity Blog
Application and Cybersecurity Blog
H
Heimdal Security Blog
T
The Blog of Author Tim Ferriss
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Hugging Face - Blog
Hugging Face - Blog
U
Unit 42

Dlog

数字时代的沉默守护者:致敬 KeePass 之父 Dominik Reichl 刀锋上的晨间哲学:316L 不锈钢与我的理容仪式 📘 Git 极简生存指南 📘 TortoiseGit 子模块核验手册:如何看懂 PaperMod 改了什么? 📘 TortoiseGit 子模块更新(升级)操作手册 平安夜,给这个 17 岁的数字家园挂上一串代码风铃 🎄 数字世界的火漆印章:我为什么要给博客文章加上 GPG 签名 异星工场蓝图代码 重构实录:Hugo+PaperMod 的终极现代化改造 上帝视角:为 PaperMod 接入 Microsoft Clarity 用户行为分析 Markdown 写作指南:像写代码一样写文章 🛶 “寻路者”的回归:海洋与波利尼西亚文化的重生 PaperMod 主题微调:Profile Mode 下的中文排版精修 告别腾讯 404,重构幽灵页面 南太平洋的极客简史:从石币区块链到草编飞机 数字领土的隐秘江湖:那些关于域名的疯狂往事 R2速率限制规则配置 蝴蝶效应:一张 25MB 的图片,让我买下了 .org 大良印记买锅记 海棠血泪 修复访客地图 PaperMod 中的 Google Analytic 配置 fnOS极简版「智能屏幕管理」方案 fnOS「开机10分钟后自动关闭屏幕」配置方案 Markdown中常用的HTML代码 再看海贼王 修复Microsoft Store应用更新 新旧交替之际 剃须装备 湿式剃须 升级Toha主题及测试 剃须日志 巧连神数:第201~第215课 巧连神数:第181~第200课 巧连神数:第161~第180课 巧连神数:第141~第160课 巧连神数:第121~第140课 巧连神数:第101~第120课 巧连神数:第81~第100课 巧连神数:第61~第80课 巧连神数:第41~第60课 巧连神数:第21~第40课 巧连神数:第1~第20课 巧连神数:前言 Le Cimetière Marin Who Has Seen The Wind 看过的书和漫画 整理iPhone和Android解锁TikTok的方法 自动更新网站底部 Copyright © 年份 游戏推荐 浅谈“国产”keepass--奇密FantasyPass 菜谱清单 看过的影视动漫 微星GE75 Raider 记·日本无条件投降76周年 《怒火·重案》 《風立ちぬ》 Netlify构建Hugo博客导致文章修改时间失效 毛泽东:《论持久战》 七子之歌 Hugo Front Matter 浅谈吴亦凡 文章内添加音乐 祛湿食谱 尼康Z5 更新主题测试及杂谈 针对steam中国上市的想法 马里奥制造2 关于QQ等读取浏览器历史记录等敏感信息及解决办法 Git的拉取Pull和获取Fetch的区别 记大马的“奇闻轶事” 解决toha主题新版本无法使用GIF头像的bug 修改背景毛玻璃效果及添加自定义CSS 添加一键返回顶部功能 网址分享 设置Git使用本地代理 增加文章更新时间 为Toha主题增加中文翻译 SteamBD 嵊州杂记 修复更新 更改测试 测试hugo+一键推送 Toha Markdown 示例 今天偶然找到《Relife》啦 测试使用HexoEditor G胖是个孩子气、小心眼儿的阴谋家 clowwindy语录 在GitHub中使用GPG签名你的commit 如何在GPG中导入OpenKeychain备份 Hexo NexT主题相关设置及优化(不定期更新) 常用软件推荐(不定期更新) ASF常用命令 Hexo常用命令(不定期更新) 醉翁亭记 一个正在裸奔面对世界的伟大母亲的呼喊! 切糕之我见 关于腾讯和44573的版权纠纷案 关于学生是否需要“孝敬”老师的杂谈 望夫树
🔐 Web Key Directory (WKD) 部署指南
Chow Ray · 2025-12-27 · via Dlog

在给博客加上 GPG 数字签名后,我开始思考一个问题:如何让读者更优雅地获取我的公钥?

传统的做法是把公钥上传到 Keyserver,或者直接贴个下载链接。但最极客的做法是支持 Web Key Directory (WKD) 协议。

简单来说,配置好 WKD 后,任何人只需在终端输入:

GPG 就会自动去我的域名下寻找并下载公钥。这不仅酷,更是将“身份”与“域名”进行了强绑定。

本文记录了在 Hugo + Cloudflare Pages 架构下的部署流程,以及在 Windows 环境下遇到的坑。

🛠️ 前置:解决 Windows Git Bash 的 GPG 冲突

在 Windows 上使用 Git Bash 时,最头疼的问题就是它自带了一个简版 GPG,无法读取安装在系统(Gpg4win/Kleopatra)里的密钥。

导致的结果就是:git commit -S 报错,或者运行脚本时提示 No secret key

1. 强制 Git 使用系统 GPG

告诉 Git 不要用自带的,而是去调用 Gpg4win:

# 请根据实际安装位置修改路径
git config --global gpg.program "E:\Program Files (x86)\GnuPG\bin\gpg.exe"

2. 强制终端使用系统 GPG

为了在 Git Bash 命令行里直接敲 gpg 时也能调用系统程序,需要修改 ~/.bashrc

# 编辑配置文件
code ~/.bashrc

# 在末尾加入别名
alias gpg='/e/Program\ Files\ \(x86\)/GnuPG/bin/gpg.exe'

保存后运行 source ~/.bashrc 生效。现在,环境终于打通了。


🟢 方法一:手动部署 (命令行流)

如果你不常更换密钥,手动生成一次是最快的方法。WKD 的原理其实就是在网站特定的目录下,放一个以 哈希值 命名的公钥文件。

1. 创建目录结构

Hugo 的静态文件放在 static 目录下:

mkdir -p static/.well-known/openpgp/wkd/hu

2. 获取 WKD 哈希值

WKD 使用 Z-Base32 算法对邮箱进行哈希。GPG 自带了计算功能:

输出中 wkd/hu/ 后面那串 32位字符 就是我们要的文件名(例如 4n9x8k2d7fp1a3qy5j6h4bv0c8mz2s5r)。

3. 导出二进制公钥

注意:WKD 要求公钥必须是 二进制 (Binary) 格式,不能是 ASCII Armor(即不能包含 BEGIN PGP…)。

# 语法:gpg --no-armor --export 邮箱 > 目标路径/哈希文件名
gpg --no-armor --export [email protected] > static/.well-known/openpgp/wkd/hu/4n9x8k2d7fp1a3qy5j6h4bv0c8mz2s5r

4. 创建策略文件

协议要求存在一个空的 policy 文件:

touch static/.well-known/openpgp/wkd/policy

部署到 Cloudflare 后,WKD 即刻生效。


🐍 方法二:Python 脚本自动化 (DevOps 流)

作为一个工科男,我更喜欢把这个过程脚本化,集成到博客的工具箱里。

我编写了一个 Python 脚本,它会自动寻找系统 GPG 路径,计算哈希,并导出文件。

脚本路径_tools/gen_wkd.py

import os
import subprocess
import sys

# === 配置区域 ===
TARGET_EMAIL = "[email protected]"

# 路径锚点
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.dirname(SCRIPT_DIR)
WKD_BASE_DIR = os.path.join(PROJECT_ROOT, 'static', '.well-known', 'openpgp', 'wkd')
HU_DIR = os.path.join(WKD_BASE_DIR, 'hu')

# 自动寻找系统 GPG 路径 (兼容多盘符安装)
def find_gpg():
    candidates = [
        r"E:\Program Files (x86)\GnuPG\bin\gpg.exe",
        r"C:\Program Files (x86)\GnuPG\bin\gpg.exe",
        "gpg"
    ]
    for path in candidates:
        if os.path.exists(path): return path
    return "gpg"

GPG_EXE = find_gpg()

def main():
    # 强制 UTF-8 输出,防止 Windows 终端乱码
    sys.stdout.reconfigure(encoding='utf-8')
    print(f"🔐 开始生成 WKD 配置 (针对: {TARGET_EMAIL})...")

    if not os.path.exists(HU_DIR):
        os.makedirs(HU_DIR)

    # 创建 policy 文件
    policy_path = os.path.join(WKD_BASE_DIR, 'policy')
    if not os.path.exists(policy_path):
        open(policy_path, 'w').close()

    try:
        # 1. 获取哈希
        cmd = [GPG_EXE, "--list-keys", "--with-wkd-hash", TARGET_EMAIL]
        result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
        
        # 正则提取哈希
        import re
        match = re.search(r'wkd/hu/([a-z0-9]{32})', result.stdout)
        if not match:
            print("❌ 未找到 WKD 哈希,请检查邮箱或 GPG 版本。")
            return
            
        wkd_hash = match.group(1)
        print(f"   🔍 哈希值: {wkd_hash}")

        # 2. 导出公钥
        output_file = os.path.join(HU_DIR, wkd_hash)
        export_cmd = [GPG_EXE, "--no-armor", "--export", "--output", output_file, TARGET_EMAIL]
        subprocess.run(export_cmd, check=True)
        
        print(f"   ✅ WKD 配置已生成至: static/.../hu/{wkd_hash}")

    except Exception as e:
        print(f"❌ 执行出错: {e}")

if __name__ == "__main__":
    main()

验证

网站部署完成后,在任何一台安装了 GPG 的电脑上运行:

如果看到公钥被成功导入,说明你也拥有了自己的 Web Key Directory

这不仅仅是一个技术配置,更是去中心化网络身份认证的重要一环。


💡 维护贴士

  • 如果你更新了密钥(比如延长了有效期、添加了新子钥),记得重新运行一次导出命令(手动或脚本),并重新部署博客。