用gnupg创建自己的网络身份

Author: R.W.Flurando

Tags: 软件, 加密, 签名, 信任

前言

很久没有更新博客了,一是没时间,而是没心情

现在这几天要放五一假(虽然是调出来的,但也比没有好吧)

加之在接受痤疮的治疗

心情很不错

于是我花时间研究了一下gnupg的pgp签名相关内容

可以说这个身份认证是非常重要的

它相当于是分布式的实名认证,每个人都可以建立属于自己的信任网

有人可能奇怪,为什么需要这个呢?我微信聊天对面还能不是本人吗?

这是因为,世界上不是只有微信。

你使用微信的时候,如何确定对面是你要聊的人,本质在于你信任微信会通过实名认证确保你发出的消息会到那个人手机上对不对?

但你不可能跟谁都用微信,而且也不是什么时候聊天的双方都愿意通过微信交流一切

微信就是中心化的实名认证,你基于对它的信任来使用

而pgp(gnupg遵守的身份认证规范)是分布式的,你自己去对别人实名认证,比如约出来对比身份证之类,以及你可以信任你实名认证过的人实名认证的人。

注意,依照设计,这种信任的传递只有一层。

举个例子,你有个好朋友,可以线下见面并确认是本人的,你可以信任他,同时他有一个信任的朋友,但这个人你从未谋面,按照信任网的设计,你可以在与他那个朋友聊天时信任其身份,但他那个朋友信任的其他人在你这里就一点参考价值也没有了。

为什么呢?

原则是你只能信任自己信任的人。

在例子中,你信任好朋友,所以信任好朋友能实名认证他的好朋友,但朋友的朋友可不是朋友了,除非你某一天当面用检查身份证或驾驶证的方法实名认证他的好朋友。

大致理念就是这样。

我知道有人可能奇怪,说好的网上,结果还要当面实名,能当面实名不当面聊,而且也没见有人顶替自己发消息啊

说的很好,因为这不是pgp的全部

你信任一个人的身份,可以使用gnupg对他的凭证签名

相当于做担保

同理别人也可以给你签名

那么你的凭证上就可以附有别人的签名

试想,你现在要和一个素昧平生的人交流,但你没有办法对他实名认证

如何确认你对面那个人就是你想交流的那个人呢?

好,现在他要证明自己身份,拿出了凭证

你接过来检查,发现上面有一百多个签名,其中不乏业内名人

而那些业内名人你虽然也不认识,但你信任他们的影响力之大以至于这些名人身份的签名无法伪造

那么你是不是就比他拿出张空白凭证更加信任其身份了?

这就是信任网的意义,它真正的目的不是让你和本来就能私下见本人看身份证的人增进信任,而是让你能通过不受任何第三方控制的方式去信任你本来无法验证身份的人。

毕竟,网上从没见过的人你没法去要身份证,人家就是拍了你信吗?而且也不可能谁都愿意把微信号给网上陌生的你吧!这时候,信任网就派上了用场。

问题

但是,gnupg的使用很麻烦

不是说他生成凭证之类的麻烦,而是这种电子凭证你自己管理起来很麻烦

更别提电子的可复制性

这种网上的身份证如何防止偷窃?

真出问题了怎么办?

要知道,别人拿到你的凭证,是可以冒充你所有与之相关的网上身份的

总之是非常麻烦

解决方案

接下来呢,我将给出一个指导方案,以及傻瓜式的步骤教学

不过事先声明,我并不是密码学专业人士,也不是IT专业人士,更不是gnupg开发相关人士,只是一个end user终端用户。

我给出的方案,仅作为个人经验分享,如果你不信任我,就不要按我的步骤走。

我大篇幅参考了Alex Cabal关于如何生成完美密钥对的文章,建议对比阅读。

但请注意,由于我没有密码狗啊smartcard之类的设备,本文不会包含使用密码狗和智能卡的教学,但如果你有或者在意,应当按照相关文档去配置!

总原则是,日常只使用子密钥来签名加密,主密钥的公钥当作凭证给大家看,私钥则分开存放。

这样当别人获取你日常设备上的密钥时,你可以用分开的那个主要私钥来吊销这些子密钥并生成新的,避免你凭证上别人的签名丢失。否则,你也可以通知别人你的私钥被偷了那些操作不是你弄得,但你将只能从头开始生成新的空白凭证去见朋友,积攒签名(身份担保)。

公私钥系统简介

什么,你不明白公钥私钥是什么?

简单来说,是差不多的两个东西。

可以这么认为,每次生成一对钥匙,也就是两把电子钥匙

它们通过数学上精妙的构造保证被这把钥匙锁上的东西只有用那把钥匙才能打开,反之亦然

就像“鸳鸯锁”一样,这个你也不知道?好吧,正常,因为是我随口编的。

现在你拿着这两把钥匙能干什么呢?

我教你,你把其中一把钥匙藏起来收好,另一把到锁匠那里复制成无数把随意分发

假设我拿到了你分发的一把钥匙

现在你觉得我们能做什么?

如果我想给你发一个私密信息,就把它写在纸上,放进盒子,用随意分发的那把钥匙锁上

好了,现在全世界只有你藏起来的那把钥匙可以打开它

而我如何认为真的只有你能看信息呢,就是基于对生成这两把钥匙相关算法的信任(比如拿着一把计算出另一把应该长啥样需要的成本时间远大于我信息的价值)和只有你拥有那个藏起来的钥匙的信任!

不止于此,你可以用你藏起来的那把钥匙加密一个信息,然后公布加密后的信息,我们大家只要有你随便分发的钥匙就可以查看

你知道这有什么用吗?

我们再次基于两个信任知道那个信息真的是你发出的,由于别人没有你的私密钥匙,所以他们要么只能口胡,要么伪造一个锁上的盒子,但这没有用!

因为当我们拿着你分发的钥匙无法正确打开盒子的时候,就明白这不是你了!

是不是很奇妙,但这一切,都基于你藏起来的那把钥匙没有别人可以使用以及我们手上拿的钥匙真的是你分发的钥匙。

需要准备的器材

请准备好以下物品

  1. 可以正常使用的私有电脑

    推荐使用GNU/Linux操作系统,但其他操作系统也可以(我只提供Linux操作说明,小白建议用最简单易用且中文支持最舒适的Linux Mint发行版跟进本文操作,Windows用户不需要本文所述内容,MacOS用户请自行解决)

    注意,请确保环境安全私密,不要在后台运行任何闭源且带有“过滤”“杀毒”等功能的专有程序,确保没有键盘记录器、监控录像设备开启

    这里的原则是,除了你自己不要信任任何人。

    因为PGP身份的重要性不是你随手注册的网站申请的邮箱可以比拟的,它就是网上的你。不要用它类比身份证或银行卡,PGP比它们都更需要重视,因为一旦失窃你没有任何警察局或当地银行可以请求帮助,你能依靠的只有自己。

    Hold Your Life, in Your Own Hand.

  2. 一个至少8GB的空U盘

    U盘不是空的也没关系,但所有内容都会在安装tails之后丢失,请自行备份

具体步骤及说明

说明中傻瓜式操作仅涵盖Linux Mint Cinnamon,其余自行调整

  1. 安装gnupg(需要联网)

    你需要在电脑上安装GnuPG

    非Linux系统请到GnuPG官网下载页面自行下载安装并确保可以正常使用。Linux系统请先打开终端(应该是一个成为terminal或者console的软件,找不到就在应用里搜)

    Linux Mint Cinnamon: 按super键(一般是有windows标志的键),输入terminal或者console回车,只有一个是对的,弹出文本框表示成功。

    然后尝试gpg是否已经安装,只要输入gp然后按几次Tab键就可以了,按多也没事,如果输出有gpg或者gpg2表明已经安装,可以跳过此步骤,否则请继续。

    Linux Mint Cinnamon: 在文本框中输入gp,然后按2次Tab键,如果按第一次自动补全成gpg或gpg2,或者第二次结果出现gpg或gpg2,表明已经安装,可以跳过此步骤。

    如果没有安装,我们现在安装。这里没啥好说的,就是从系统包管理器安装,可能GNome Store之类的图形化也有,但我没查过就不演示了。

    Linux Mint Cinnamon: 按退格键直到退无可退,输入sudo apt install gnupg回车就可以,然后等待。如果你很久没有用过电脑了,建议先升级系统,通过命令sudo apt update && sudo apt upgrade。

    一般来说gpg是默认安装在发行版里的,如果你的电脑上没有而且你没有明确删过,可能得联系一下。

  2. 制作tail系统U盘

    这一步需要我们按照tails官网的安装说明制作一个tail os的U盘

    tail作为面向洋葱暗网的临时操作系统加上国内无法直连的官网我就不具体介绍了,不过值得注意的是,本篇解决方案不涉及暗网内容,用tail也建议完全在断网环境下使用。

    有人可能要说,不用暗网你用tail干啥,我只想说,难道你用puppy吗?真的,密钥管理这边还就只有tail有较好支持,如果你有几个tail的U盘的话甚至可以一键备份密钥,方便安全,普通pgp用户的最佳选择(不能因为它支持暗网就避尤不及,这种对技术一知半解成天谈虎色变的人建议退网,99.9999%的互联网内容都不在你可以百度到的范围,谷歌也搜不到。)

    你不用真的把自己家路由器关掉,tail启动时自带断网选项,你到时候点上就可以了。

    准确来说,我们要用tail的gnupg钥匙对管理功能,也只需要用这个功能。

    问题在于,tail官网并没有中文翻译,所以我还是给一下安装步骤吧。

    你到了那个页面后,先点绿色的Download按钮或者下面的BT种子链接

    友情提醒:这两个指向的网站目前都不能稳定直连,实在连不上建议按照Alex Cabal关于如何生成完美密钥对的文章操作,不要跟了,后面把tails当gnupg私钥管理盘用的。

    假设你怎么着就是下好了,哎,假设你也验证过完整性了,哎!虽然不知道过程,但结果是就行。

    那么用dd命令if啊of啊看一看给它烧录到U盘上再sync确认一下就可以,也可以用rufus(限Windows)或Etcher(通用)来烧录。

  3. 启动tail

    现在我们把电脑关机,插入U盘,开机,从U盘启动。

    这里从U盘启动要配置uefi选项,也可能是bios,每个机子不一样。

    如果你的设备默认不能启动U盘,那么可能Esc或者F1到F12中某个键在开机时按可以让你选择从U盘启动,具体我也不清楚,自己按自己电脑型号厂商查查吧。

    经过漫长的等待,你应该看到一个蓝色底的英文界面,在Language那里鼠标点击,选择Simplified Chinese简体中文,additional options附加选项关闭网络进入离线模式(默认是联网的),同时开启管理员账户,这里输入两次一样的密码随便,它重启就忘了。然后Create Persistant Storage创建永久存储并确保点亮了GnuPG那一行。

    具体顺序可能不大对,如果有出入请自行辨别。

    最后启动tails,我们走!

    注意,你不用管自动弹出的tor连接助理窗口,第一我们是离线模式横竖上不了网,第二它也帮不上啥忙,直接点叉关掉。

  4. 生成钥匙对

    下面我们要生成一个钥匙环,再添加一个用于签名的副钥匙,最后导出除了主钥匙对的私钥以外的所有钥匙到电脑硬盘上(也就是我们最终导出的钥匙环缺最核心的私钥)。

    打开一个普通终端,方式是按super键然后输入terminal,应该看到了吧。

    不用开那个红色的,暂时用不到。

    在终端输入gpg2 --expert --full-generate-key回车

    接下来你可以一路回车默认值,也可以输入数字回车选择更新更安全但没有计入PGP标准的ECC椭圆曲线算法

    大概这样

     ```
     Please select what kind of key you want:
     (1) RSA and RSA
     (2) DSA and Elgamal
     (3) DSA (sign only)
     (4) RSA (sign only)
     (7) DSA (set your own capabilities)
     (8) RSA (set your own capabilities)
     (9) ECC (sign and encrypt)
     (10) ECC (sign only)
     (11) ECC (set your own capabilities)
     (13) Existing key
     (14) Existing key from card
     Your selection? 9
     Please select which elliptic curve you want:
     (1) Curve 25519
     (2) Curve 448
     (3) NIST P-256
     (4) NIST P-384
     (5) NIST P-521
     (6) Brainpool P-256
     (7) Brainpool P-384
     (8) Brainpool P-512
     (9) secp256k1
     Your selection? 1
     Please specify how long the key should be valid.
     0 = key does not expire
     <n>  = key expires in n days
     <n>w = key expires in n weeks
     <n>m = key expires in n months
     <n>y = key expires in n years
     Key is valid for? (0) 0
     Key does not expire at all
     Is this correct? (y/N) y
    
     GnuPG needs to construct a user ID to identify your key.
    
     Real name: 小明
     Email address: [email protected]
     Comment: 王小明
     You are using the 'utf-8' character set.
     You selected this USER-ID:
     "小明 (王小明) <[email protected]>"
    
     Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? 
     ```

    最后一行的意思是输入N回车重新写Real Name真实姓名,C重新写Comment备注,E重新写Email address邮箱地址,O确认正确生成凭证,Q回车取消操作退出。

    确认无误我们就可以输入O回车,很快命令运行完成。

    中途它会要你设定password密码,请设定一个强密码,我建议使用diceware方法生成一个passphrase口令然后记住它,而不是说“我在生日后随便输了5个字符,没有人可以攻破它”之类的傻话

    由于这个密码是别人拿到你的凭证后能保护你身份的唯一屏障,请把它当作银行卡密码对待,没有二重认证(就是给你发短信问验证码或浏览器人脸识别)的那种!

    现在我们有了钥匙环还要做什么呢?

    输入gpg2 --edit-key [email protected]回车,我们要给这个主密钥再添加一个签名密钥(默认已经有一个加密密钥了,所以我们只要创建一个用于签名的)

    这里邮箱地址你得写自己的明白不?

    接下来输入addkey回车

    请选择写着“签名”或者sign的行,它会产生一个用于签名的密钥

    中间会弹输密码,你得输入之前设定的password密码

    结束后输入save回车

    好,现在可以关闭终端了。

    下面为了方便起见,我们通过KDE社区出品的Kleopatra继续操作

    打开那个像带红帽子小人头的应用

    在右侧选择my certificates我的证书

    右键单击你刚才创建的凭证并选择details详细内容

    将第2、3个密钥导出,一般第一个的primary主要栏是打勾的

    总之你要把不是主要的钥匙的secret key私钥导出,就导出到默认目录就可以

    要输两遍密码,输吧。

    然后关闭详细内容窗口,点击export key把主公钥导出到刚才那个目录

    接下来关闭Kleopatra,打开蓝色的文件应用

    进入刚才那个目录,右键空白处点击open terminal here在此处打开终端

    输入tar -cf keys.tar <子密钥1的私钥完整文件名> <子密钥2的私钥完整文件名> <主公钥完整文件名>回车

    记得替换,文件名很长,按Tab自动补全就好

    它会产生一个keys.tar文件

    当然你把keys.tar换成其他文件名也行,无所谓的

    接下来我们要加密这个文件

    输入gpg2 --symmetric keys.tar回车

    按照提示设置密码

    这里千万注意,这个密码你能整多复杂就弄多复杂,因为我们只会用一次,但被它加密的内容可能被放在FBI的手里审视无数次!

    开个玩笑,但请按我的步骤继续,原因之后解释

    完成后会生成keys.tar.gpg文件

    现在按super键输disk回车

    在Disk Utility磁盘工具中挂载你的电脑硬盘

    点那个播放键就可以了

    会提示输入管理员密码,就是启动tail时设置的那个

    挂载完成后你应当能在蓝色文件应用的other locations+计算机上其他位置看到你的硬盘

    接下来把keys.tar.gpg复制或移动到你硬盘上自己顺手的位置

    细心的同学可能想到用一个空闲U盘中转也行,那是当然,总之我们目的是电脑正常使用时能拿到这个keys.tar.gpg嘛。

    只复制这个加密后的gpg文件,千万不要把那两个明文私钥文件或者没加密的tar文件弄到硬盘上!

    完成后点击右上角然后shut down关机

    在电脑断电后拔出U盘

    这个U盘现在要保存好,它在你给别人的凭证签名,吊销被盗取的副钥匙,生成新的钥匙甚至改变凭证上的照片时都需要使用

    鉴于U盘读写次数比硬盘少得多,之后可能需要备份,这是很简单的,你只需要再弄一个不少于8G的空U盘

    然后用tail自带的clone复制以及persistant storage backup备份工具完成

    这里我并没有尝试过只是理论表述,所以我们就不深入细节了,如果不是这样的欢迎告知(有一种需要屯U盘的预感呢……)

  5. 导入钥匙对

    现在让我们把U盘收好放在一边,将电脑正常开机。

    下面我们需要开一个ramfs(仅存在于内存的文件系统),把keys.tar.gpg移动到ramfs里并解密,将里面的三个文件导入GnuPG,最后设置对这个钥匙对的信任为ultimate trust始终信任。

    我完全不知道在Linux之外的系统上如何实现这个,而且我完全参照Alex Cabal关于如何生成完美密钥对的文章来开ramfs。

    所以其他系统,你懂的,自己琢磨吧。

    注意我们可能得给这个ramfs开一个稍大一些的空间,按Alex的size=1m目前可能够,但未来不一定,万一你哪天电脑上这个钥匙对坏了要重新导入整个而且你凭证上一堆签名加多个子钥匙是吧?

    打开一个终端运行

     ```bash
     mkdir /tmp/gpg
     sudo mount -t ramfs -o size=1M ramfs /tmp/gpg
     sudo chown $(logname):$(logname) /tmp/gpg
     ```

    运行完就可以关闭这个终端,以免后面弄混

    好的,抄完Alex的作业,我们下面步骤会略有不同

    值得注意的是,在后续步骤中,你可能需要用gpg2代替gpg

    只有gpg没有gpg2的朋友可以通过gpg --version查看,如果版本是2.x.y那么就是正确的。

    我们开始

    首先,打开文件应用,找到/tmp/gpg文件夹和keys.tar.gpg

    然后,把keys.tar.gpg移动到/tmp/gpg文件夹里

    现在右键这个文件夹空白处打开打开终端,输入gpg --decrypt keys.tar.gpg | tar -x回车,在对话框输入刚才说好只用一次的密码就可以

    好了,你应该能在/tmp/gpg文件夹下找到刚才那三个钥匙文件

    注意,克制自己再检查一遍的冲动,不要打开它们,不要去点它们,更不要想着把内容抄在纸上!要备份就再买一个8GB的U盘做tail备份!

    接下来我们要导入这三个钥匙文件到电脑的gpg配置中去

    输入gpg --import <子密钥1的私钥完整文件名> <子密钥2的私钥完整文件名> <主公钥完整文件名>回车

    在导入成功后,我们将这个钥匙对设置为无条件信任,因为这是我们自己的钥匙,总没有人连自己都怀疑吧,哈哈。

    输入gpg --edit-key [email protected]回车,然后输入trust回车,看看哪个数字对应的行有ultimate trust或者中文的类似等价选上回车就可以

    选择后输入y回车表示同意

    示例

     ```
     Please decide how far you trust this user to correctly verify other users' keys
     (by looking at passports, checking fingerprints from different sources, etc.)
    
     1 = I don't know or won't say
     2 = I do NOT trust
     3 = I trust marginally
     4 = I trust fully
     5 = I trust ultimately
     m = back to the main menu
    
     Your decision? 5
     Do you really want to set this key to ultimate trust? (y/N) y
     ```

    然后输入save回车完成。

  6. 上传公钥到公开的服务器

    现在我们要把公钥上传到keys.openpgp.org

    在终端输入gpg --export [email protected] | curl -T - https://keys.openpgp.org回车

    用浏览器打开它返回的验证链接。

    然后在你邮箱里点击它发送的另一个验证链接。

    完成后别人就可以通过邮箱地址搜索或下载你的公钥了。

    你可以把自己公钥的指纹尽可能的告知天下,以免别人下到冒充者的公钥却以为是你。

    这个指纹可以认为对每个凭证而言是独一无二的,你可以理解成身份证号码,不包含个人信息的那种。

    怎么查看指纹呢?

    输入gpg --fingerprint [email protected]回车

    你可能会看到这样的输出

     ```
     pub   ed25519 2025-04-29 [SC]
           EB85 BB5F A33A 75E1 5E94 4E63 F231 550C 4F47 E38E
     uid           [ultimate] 小明 (王小明) <[email protected]>
     sub   cv25519 2025-04-29 [E]
     sub   ed25519 2025-04-29 [S]
     ```

    看见第二行四个四个一组的东西没有

    在这个例子中,小明的指纹就是EB85 BB5F A33A 75E1 5E94 4E63 F231 550C 4F47 E38E

    你不输入空格也行,只是这样方便他人用肉眼或者屏幕阅读器来比对嘛。

    你的指纹肯定不是这个,自己大致类比着去找一下吧。

到这里,六步,我们已经配置好可以日常使用的PGP密钥了。

但有些注意事项还是要提一下。

注意

现在,电脑上的钥匙对是没有最重要的私钥的

所以你想吊销凭证之类的操作只能进tail,改好之后再走一遍导出步骤

但是呢,一般你不用每次都完整导出,你可以只导出修改后的主公钥

gpg在import导入时会自动合并属于同一个钥匙对的内容

签名之类的由于要使用你的主私钥,所以也是需要进tail的

不过这种事很少发生,即便你就是社牛天天给人认证跑各种会议交换凭证

也可以集中找一个时间签名。

鉴于篇幅原因,和我本身没有经历,就不展开说了。

有个bug得小心,虽然没有私钥也可以修改照片,但你不要这么做,会弄坏你的凭证,结果是只能手动重新完整导入。

后记

总体来说,确实不方便

但你懂的,自立根生就是这样。

这篇文章只是帮助你弄一个2025年的gnupg完美配置(这里说的完美,不是最安全,只是你手头只有U盘和电脑的个人认为的最佳实践。目前最安全就是硬件密码,也就是密码狗之类的!)

没有包含如何使用,比如日常的签名,加密,他人公钥的管理等等。

我写这些的目的,就是因为相关资源太少,英文都只有大体相同的寥寥几篇,更别说简中圈了。

希望能帮助到你,陌生人:)