无垠之码

深度剖析代码之道


去中心化的信任模型WOT

1.信任模型


1.1中心化信任体系

信任由一个或少数几个中心权威实体提供,所有参与方默认信任该中心 在中心化的信任体系中存在明确的信任根也就是信任锚点,同时信任关系呈星型结构,身份、权限、规则由中心统一管理,用户之间不直接建立信任,而是通过中心背书

典型实现

  • PKI/CA体系HTTPS、TLS
  • Kerberos
  • OAuth/OpenID Connect
  • 企业IAM、LDAP、AD
  • 云厂商账号体系AWS/GCP/Azure

适用于企业内部系统,强合规、强治理,封闭或半封闭网络的中心化信任模型,存在明显的单点故障SPOF,单点风险,以及强控制审查的缺点。

1.2去中心化信任网络

OpenPGP不同于传统的中心化信任模型,它采用Web of Trust的去中心化信任网络,通过多方相互验证来建立和维护信任关系

  • 没有中心化机构
  • 每个用户可以签署他人公钥
  • 通过签署来建立信任链
  • 形成一个类似社交网络WOT(Web of Trust)的信任体系

OpenPGP不仅支持对原始数据的数字签名以验证其完整性与来源,更核心的特性在于支持密钥认证Key Certification——即通过对公钥-身份UID绑定关系的签署,构建去中心化的信任网

OpenPGP定义了两类概念(使用gpg --edit-key 36604E4252411821629DCC589270DF719D5C345A可以看到validity和trust属性):

签名级别:validity,表示你认为某把公钥是否真的属于这个用户

  等级:
  unknown:尚未为该密钥指定所有者信任,或信任关系尚未完成计算
  expired:信任计算失败,有可能是过期
  undefined: 没有足够的信息计算
  marginal:部分信任(Web of Trust中有限签名支持)
  full:完全信任(有多个信任签名支持)
  ultimate:终极信任
  revoked: 撤销

信任级别:trust,表示你认为这个密钥持有者是否有能力去签署其他公钥(给别人背书的能力)

  例:
  你信任Alice能签署Bob的密钥,你就把Alice标记为fully trusted
  这样Bob的密钥就可以被间接信任

2.GPG软件


91年,程序员Phil Zimmermann为了避开政府监视,开发了加密软件PGP(Pretty Good Privacy)。这个软件非常好用,迅速流传开来,成了许多程序员的必备工具。由于软件专利授权问题,98年,IETF互联网工程任务组将PGP的核心机制标准化,协议标准OpenPGP。99年GNU项目基于OpenPGP标准,实现开源,完全自由、无专利风险的软件实现GnuPG(GNU Privacy Guard)

2.1软件安装

apt install gnupg

# 配置文件介绍, GPG配置文件目录: ~/.gnupg
~/.gnupg/gpg.conf                         – 配置文件
~/.gnupg/trustdb.gpg                      – 信任库, 存储你对每个公钥的信任等级
~/.gnupg/private-keys-v1.d/               - 私钥文件, 加密保存
~/.gnupg/pubring.kbx                      - 公钥环, 存放你的公钥和导入的他人公钥
~/.gnupg/crls.d/                          - 吊销证书, 存放X.509证书的撤销列表
~/.gnupg/openpgp-revocs.d/                - 密钥撤销证书

2.2秘钥构建

在OpenPGP体系中,主密钥作为信任锚点,负责对用户身份和子密钥进行签名;实际的数据加密、签名和认证操作由用途受限的子密钥承担,从而降低主密钥暴露风险

  • 生成主秘钥
gpg --full-generate-key

Please select what kind of key you want:
   (1) RSA and RSA (default)       // RSA基于大整数分解问题
   (2) DSA and Elgamal             // DSA算法仅用于签名,优势签名验证快,离散对数问题,ElGamal算法消息加密(可签名使用)
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card

sec   rsa3072 2026-02-04 [SC]     // S表示签名Sign,C表示证书签发或身份签名Certification
      36604E4252411821629DCC589270DF719D5C345A  // KeyID/指纹
uid           [ultimate] diyao <530384671@qq.com>  // 信任级别ultimate
ssb   rsa3072 2026-02-04 [E]      // ssb子密钥,加密用途E,长度3072
  • 认证子秘钥
gpg --expert  --edit-key 36604E4252411821629DCC589270DF719D5C345A
addkey // 选择算法

Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)  // 自定义能力
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 

Current allowed actions: Authenticate // 按对应键盘开关能力
   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

gpg -K --keyid-format long

sec   rsa3072/9270DF719D5C345A 2026-02-04 [SC]
      36604E4252411821629DCC589270DF719D5C345A
uid                 [ultimate] diyao <530384671@qq.com>
ssb   rsa3072/A90CB653C6A7F36A 2026-02-04 [E]
ssb   rsa3072/B1D803A681C9FD3E 2026-02-04 [A]  // 创建认证功能子秘钥
  • 签名子密钥
sec   rsa3072/9270DF719D5C345A 2026-02-04 [SC]
      36604E4252411821629DCC589270DF719D5C345A
uid                 [ultimate] diyao <530384671@qq.com>
ssb   rsa3072/A90CB653C6A7F36A 2026-02-04 [E]
ssb   rsa3072/B1D803A681C9FD3E 2026-02-04 [A]
ssb   rsa3072/FE63137B8F6A8CEB 2026-02-04 [S]

2.3实战落地

  • 公钥分发

    公钥的分发主要有两种方式:通过文本或邮件直接分发,以及上传至开放的公钥管理平台。在将公钥上传至服务器后,OpenPGP通常会向与该公钥关联的邮箱发送验证邮件,要求收件人确认,从而确保密钥持有者的邮箱有效

1. gpg --armour --export 36604E4252411821629DCC589270DF719D5C345A > gpgkey.pub.asc // ASCII格式,邮件发送给朋友
2. gpg --send-keys 36604E4252411821629DCC589270DF719D5C345A                        // 上传至服务器hkps://keys.openpgp.org

     导出可用于ssh认证登录的公钥,该公钥可手动或者使用命令gpg --export-ssh-key 9270DF719D5C345A | gh ssh-key add -上传至github平台

gpg --export-ssh-key 9270DF719D5C345A
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCypPJJFW0v3VI9ZfHjeeAQ/iimezxCLJNhnifRHGcRy9qUveCaqPbKn7dsgY+nVy5nNNlb/fcVGz05h1/iSgPU8   +RDZrY79VirTZBQIoMc02mdGBO5AlCXyzA4DCRzauILB8gEzFBUzMs6S9Yaet9HnQROC4j46xLPf0zm4mR08r0zjsMVqlI800O0N/5HeHVubaug7mzLtDW00TMMFuBbmaw/pL9Ntq7JFtGYfaRpV3L124svmXLHzyd   PGIuW659nnV6ON2oq5gps7GFEbJ49WrvuCEZhxw2tgQFZYoNLrMV5CAi0+QEqBtV6G5V33xvmEVIoXv7qMwZwV5CBpt604rEZ0kd6pYtF66NmEDXq   +86KjBXLHDE8A0rVXDwvnvM5JTPKiCT59EUWG0gcw1Cg3PwutMe8jAFNuwn9xrdbZTXpnVkVQYekJoOEwTkGRGUklUag8nxpR5BmblS7LUOR/HkvyY1Ew3IaQiGy8LaytZZZf2BEhb0cIdrOqv9E= openpgp:0x81C9FD3E  
  • 公钥导入

    平台导入

导入:
  gpg --search-keys cauc.peter@gmail.com
  gpg: data source: https://keys.openpgp.org:443
  (1)     diyao <cauc.peter@gmail.com>
        3072 bit RSA key F9FBBD88D2D5C62C, created: 2026-02-02
  Keys 1-1 of 1 for "cauc.peter@gmail.com".  Enter number(s), N)ext, or Q)uit >  1  // 选择1

验证:
  gpg -k --keyid-format long
  pub   rsa3072/F9FBBD88D2D5C62C 2026-02-02 [SC]
        C26E8179A3ABB513F4CD43E8F9FBBD88D2D5C62C
  uid                 [ unknown] diyao <cauc.peter@gmail.com>
  // [unknown] 你没有对这个UID或密钥进行信任签署,也没有明确标记信任级别
  // [none] 公钥存在,但尚未验证邮箱或签名
  // [marginal] Web of Trust中部分信任(被多人签名,但未达到完全信任)
  // [full] 完全信任(足够签署可信密钥)
  // [ultimate] 你自己的密钥或你完全信任的密钥
  sub   ed25519/26AEB5DBD72535D8 2026-02-02 [SA]
  sub   cv25519/7CCCD6B5AC806EC3 2026-02-02 [E]

信任:
  gpg --edit-key F9FBBD88D2D5C62C
  uid 1  // 选择你要签署的UID
  sign   // 用自己的主密钥签署这个UID,确认这个邮箱属于这把主密钥(导入的公钥),设置validaty
  trust  // 设置trust属性
  4
  save

  gpg -k --keyid-format long
  pub   rsa3072/F9FBBD88D2D5C62C 2026-02-02 [SC]
        C26E8179A3ABB513F4CD43E8F9FBBD88D2D5C62C
  uid                 [  full  ] diyao <cauc.peter@gmail.com>
  // full表示我信任a的签署能力,由于a(diyao)的私钥进行对b的公钥进行签名,因此,我确信b的UID邮箱确实属于这把公钥,B用私钥签署的内容可以被验证且可信
  sub   ed25519/26AEB5DBD72535D8 2026-02-02 [SA]
  sub   cv25519/7CCCD6B5AC806EC3 2026-02-02 [E]

     文件导入

gpg --import gpgkey.pub.asc

     使用ssh-import-id gh:ewall-cauc命令可导入免密登录的ssh公钥

  • 私钥备份

    导出私钥后使用openssl对私钥进行加密

gpg --export-secret-keys --armor 36604E4252411821629DCC589270DF719D5C345A > gpgkey.sec.asc
openssl enc -aes-256-cbc -salt -in gpgkey.sec.asc -out gpgkey.sec.asc.enc
openssl enc -d -aes-256-cbc -in gpgkey.sec.asc.enc -out gpgkey.sec.asc
gpg --import gpgkey.sec.asc
  • 证书的吊销

在gpg的体现中只有根密钥具有C(证书签发能力),吊销指根密钥宣布作废,其授权全部连带,子密钥失效
吊销是不可逆的单向操作。一旦吊销证书被同步至服务器,该身份将在全球信任网络中‘社会性死亡’,即便找回私钥也无法撤回。

1. 吊销
gpg -o C26E8179A3ABB513F4CD43E8F9FBBD88D2D5C62C.revoke.asc --gen-revoke C26E8179A3ABB513F4CD43E8F9FBBD88D2D5C62C
gpg --import C26E8179A3ABB513F4CD43E8F9FBBD88D2D5C62C.revoke.asc
gpg --keyserver keyserver.ubuntu.com --send-keys C26E8179A3ABB513F4CD43E8F9FBBD88D2D5C62C(或者使用邮箱)
gpg --delete-secret-and-public-key C26E8179A3ABB513F4CD43E8F9FBBD88D2D5C62C // 删除全部密钥

2. 验证(b机器)
gpg --keyserver keyserver.ubuntu.com --refresh-keys
gpg: refreshing 1 key from hkp://keyserver.ubuntu.com
gpg: key 65BD821F61628D60: "zhangsan (test-1) <test-1@diyao.me>" revocation certificate added
gpg: key 65BD821F61628D60: "zhangsan (test-1) <test-1@diyao.me>" 1 new signature
gpg: Total number processed: 1
gpg:         new signatures: 1

gpg -k
pub   rsa3072 2026-02-05 [SC] [revoked: 2026-02-05]
      4A0A1E25DAED061AD5971AA665BD821F61628D60
uid           [ revoked] zhangsan (test-1) <test-1@diyao.me>
  • 免密ssh登录
gpg --list-key --with-keygrip
echo 36604E4252411821629DCC589270DF719D5C345A > ~/.gnupg/sshcontrol
gpgconf --launch gpg-agent  // 重启gpg-agent进程
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
ssh-add -L  // 验证gpg用于登录的私钥是否已加载至内存
export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye
  • 文件签名与验证

     单签

gpg --sign file.txt  
gpg --verify file.txt.gpg 

     多签
     一个文件包含多个独立签名,在软件发布、配置审批、交接流程里非常常见,验证谁签名了谁没有签名,工程/治理/运维场景里的投票或表决

gpg -u alice@email.com --detach-sign file.tar.gz // 使用alice私钥对file.tar.gz签名
gpg -u bob@email.com --detach-sign file.tar.gz   // 使用bob私钥对file.tar.gz签名
gpg --verify file.tar.gz.sig file.tar.gz

     引申:
      1. 加密货币中多签, 用户多方授权, 资产消费必须满足"M个独立私钥中的N个同时授权"
      2. 环签名, 签名者是这N个人中的一个, 但你不知道是哪一个, Monero币隐藏交易过程
      3. 群签名, 有一个管理员,在必要时揭示身份, 一般匿名
      4. 阈值签名, N个参与者持有同一把虚拟私钥的不同份额,至少M个参与者联合才能生成有效签名
      5. 盲签, 签名者在不知道消息内容的情况下为消息生成有效签名

     在匿名选举场景:
      1. 选民收到印有其选举资格的信封后,将其填妥的匿名选票放入信封(盲化Blinding)
      2. 官员首先验证证件然后在信封上签字,签字通过复写纸转移到选票上(盲签名Signing)
      3. 一旦选票被签名,信封归还给选民,选民将选票放到一个没有标记的新的普通信封里(去盲Unblinding)
      4. 选民通过匿名通道提交选票,没人能将这张票与最初的"信封"关联(匿名发布)
      5. 签名者没有看过消息内容,但是一个第三方组织能通过官员的公钥来检查签名是有效性, 代表该票合法(验证Verification)

  • 文件加密与解密
# --armor参数输出base64编码
gpg --symmetric file.txt               // 使用对称密钥加密
gpg --decrypt file.txt.gpg             // 使用对称密钥解密
gpg -e -r cauc.peter@gmai.com file.txt // 使用cauc.peter@gmai.com接受者的公钥加密,可加多个-r参数,此时多个接收者都可以解密
gpg file.txt.gpg                       // 接受者使用自己的私钥解密
  • Git commit签名
gpg --list-secret-keys --keyid-format LONG
git config --global user.signingkey F9FBBD88D2D5C62C
git config --global commit.gpgsign true

3.踩坑避雷

3.1信任链条(签名信息)无法通过公钥服务器同步

在分布式测试中,即便建立了逻辑上的信任链,验证依然可能弹出警告

  1. 张三使用自己的私钥对李四的公钥签名,即承认李四的邮箱与公钥是匹配,同时将自己签名过的李四公钥证书上传至服务器
  2. 王五下载张三的公钥并签名,同时设置对张三的trust级别为信任, 承认张三的背书能力,也认定张三的邮箱与公钥是匹配
  3. 当李四向王五发送签名邮件时,(王五下载李四的公钥), 王五本地验证虽显示Good Signature数学校验通过,但依然触发 WARNING 警告,提示身份不可信
  4. 需要张三将本地的关于李四的公钥导出至王五的主机,才能信任闭环

原因:

  1. 签名剥离机制 张三将带有他签名的李四公钥上传至服务器,但现代公钥服务器如keyserver.ubuntu.com为了防范垃圾关联攻击,通常会剥离非原作者的第三方签名(即张三上传了李四的公钥证书,这些关联的签名信息被丢弃)
  2. 信息不同步 王五从服务器下载的李四公钥是干净的版本。由于王五本地的李四公钥上没有张三的签名,导致信任链条在本地无法闭合

传统的Keyserver存在撤销和更新同步缓慢,无法删除垃圾签名,需要用户手动搜索、对比指纹并导入以及其他一些缺点, 现在WKD(Web Key Directory),当你给alice@example.com发送加密邮件时,GPG会根据邮箱地址自动推导出对应的URL,下载alice的公钥加密, 对应本案例中,直接根据邮箱信息,推到出https://example.com/.well-known/openpgpkey/hu/[用户名哈希值]

现实世界的专业圈子里,大家更倾向于直接发送公钥文件,或者使用keybase.io等更现代的平台,而不是单纯依赖传统的公共密钥服务器

3.2使用keybase.io的现代平台

如果你已经学会了基本原理或者应用,那么现在请忘记它!
Keybase能自动管理信任链和公钥验证,避免传统公钥服务器的信任链丢失问题,以及在参考文献中提到的一些其他安全问题,弥补gpg的相关缺陷

curl --remote-name https://prerelease.keybase.io/keybase_amd64.deb
sudo apt install ./keybase_amd64.deb
run_keybase

keybase命令行提供如下命令(首先利用图像界面注册帐号),keybase提供了一个端到端的加密文件系统(服务器存储的密文bu)

NAME:
   keybase - Keybase command line client.

USAGE:
   keybase [global options] command [command options] [arguments...]
   
VERSION:
   6.5.1-20260204010455+5c615aa1ce
   
COMMANDS:
   account              Modify your account                                           // 帐号修改
   blocks               Manage user and team blocks                                   // 屏蔽功能,类似将特定的账户团队加入黑名单
   bot                  Manage bot accounts                                           // 机器人账户,自动发送消息、响应命令、管理会话 CICD
   chat                 Chat securely with keybase users                              // 直接与其他keybase用户聊天,keybase chat send wangxuan "你好"
   ctl                  Control the background keybase service                        // keybase后台服务控制命令,控制重启,提高日志级别等
   currency             Manage cryptocurrency addresses                               // keybase内置数字货币钱包,管理数字货币
   decrypt              Decrypt messages or files for keybase users                   // 解密keybase的消息,文件
   deprovision          Revoke the current device, log out, and delete local state.   // 移动端,网页端,等设备的登录授权
   device               Manage your devices                                           // 设备
   encrypt              Encrypt messages or files for keybase users and teams         // 加密keybase的消息,文件
   follow, track        Verify a user's authenticity and optionally follow them       // 类似Twitter/GitHub上的Follow功能
   fs                   Perform filesystem operations                                 // 操作Keybase的加密文件系统
   git                  Manage git repos                                              // 提供一个加密Git仓库,远端加密存储
   id                   Identify a user and check their signature chain               // 确认一个用户,验证其信任链条
   kvstore              Manage a simple cleartext key to encrypted value store        // 提供的轻量级kv数据库
   list-followers       List those who follow you                                     // 
   list-following       List who you or the given user is publicly following          //
   log                  Manage keybase logs                                           // 日志管理
   login                Establish a session with the keybase server                   //
   logout               Logout and remove session information                         //
   oneshot              Establish a oneshot device, as in logging into keybase from a disposable container // 一次性设备
   paperkey             Generate paper keys for recovering your account                                    // 用户账户恢复的密钥
   passphrase           Change or recover your keybase passphrase                                          // 密码管理
   pgp                  Manage keybase PGP keys          // openpgp的基本操作                                                  
   ping                 Ping the keybase API server      // keybase服务器延时测试
   prove                Generate a new proof             // 申明对某个公开帐号的所有权,比如github:ewall-cauc帐号的所有权,keybase会要求你在gist中粘贴特定文本
   rekey                Rekey status and actions   
   selfprovision        Provision a new device if the current device is a clone.      // 新设备的授权 
   sign                 Sign a document                  // 文档签名
   signup               Signup for a new account
   sigs                 Manage signatures
   status               Show information about current user
   team                 Manage teams                     // 团队管理
   unfollow, untrack    Unfollow a user                  
   update               The updater
   verify               Verify message or file signatures for keybase users  // 验证签名
   version              Print out version and build information
   wallet               Send and receive Stellar XLM                         // 钱包功能
   whoami               Output the name of the current user; will exit with a non-zero status if none
   service              start the Keybase service to power all other CLI options
   help, h              Shows a list of commands or help for one command

ADDITIONAL HELP TOPICS: 
   // 帮助文档,关于keybase的高级用法,比如如何和gpg相互,keybase秘钥信息本地如何存储,以及怎么结合tor网络使用
   advanced             Description of advanced global options
   gpg                  Description of how keybase interacts with GPG
   keyring              Description of how keybase stores secret keys locally
   tor                  Description of how keybase works with Tor

4.参考文献

  1. https://ulyc.github.io/2021/01/13/2021年-用更现代的方法使用PGP-上/
  2. https://ulyc.github.io/2021/01/18/2021年-用更现代的方法使用PGP-中/
  3. https://ulyc.github.io/2021/01/26/2021年-用更现代的方法使用PGP-下/