GPG 最佳实践

编程
7 min read
poster

上篇文章 加密软件 GPG 上手教程 介绍了 GPG 的基础使用,这篇文章作为上一篇的延续,分享 GPG 最佳实践

创建职责分离主密钥与子秘钥

sitelinks-searchbox

在 GPG 的架构中,

  • 主密钥必须具有[C] 功能,可兼备[S]、[E]、[A]功能中的一项或多项,
  • 子秘钥可具有[S]、[E]、[A]功能中的一项或多项。

为什么要创建职责分离的主密钥与子秘钥呢?

首先子秘钥是一个单独的秘钥对,与主密钥只是从属关系,在功能上是完全独立的,而且子秘钥可以独立于主密钥被吊销。

其次,主密钥非常重要。如果主密钥被盗,别人一旦获得了主密钥的控制权,就能用你的名义做任何事情,比如签署文件,解密信息等。而且吊销主密钥会带来巨大的成本损失——你需要重新建立信任。由于信任网的每个连接都是对主密钥和用户 ID 之间绑定的认可,与子秘钥无关(子秘钥的创建和吊销不会影响主密钥之间的信任关系)。所以,如果在主密钥安全的情况下子秘钥被盗,你只需吊销被盗的子秘钥,并签发新的子秘钥即可。

创建主密钥
gpg --expert --full-gen-key
gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Please select what kind of key you want:
(1) RSA and RSA (default)
(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 and ECC
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(13) Existing key
(14) Existing key from card
Your selection? 8
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? s
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? e
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
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) 3y
Key expires at Sun 23 Mar 2025 04:51:32 GMT
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: alice
Email address: alice@example.com
Comment:
You selected this USER-ID:
"alice <alice@example.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /home/alice/.gnupg/trustdb.gpg: trustdb created
gpg: key A39421B65EF4D2D7 marked as ultimately trusted
gpg: directory '/home/alice/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/alice/.gnupg/openpgp-revocs.d/C105EE41AB5FDFAB2D00F2FFA39421B65EF4D2D7.rev'
public and secret key created and signed.
pub rsa4096 2022-03-24 [C] [expires: 2025-03-23]
C105EE41AB5FDFAB2D00F2FFA39421B65EF4D2D7
uid alice <alice@example.com>
创建加密功能的子秘钥
gpg --expert --edit-key alice@example.com
gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
sec rsa4096/A39421B65EF4D2D7
created: 2022-03-24 expires: 2025-03-23 usage: C
trust: ultimate validity: ultimate
[ultimate] (1). alice <alice@example.com>
gpg> 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? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
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) 3y
Key expires at Sun 23 Mar 2025 04:59:04 GMT
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
sec rsa4096/A39421B65EF4D2D7
created: 2022-03-24 expires: 2025-03-23 usage: C
trust: ultimate validity: ultimate
ssb rsa4096/18832C062E4EBE77
created: 2022-03-24 expires: 2025-03-23 usage: E
[ultimate] (1). alice <alice@example.com>
gpg> save

秘钥创建完成后如下:

gpg --edit-key alice@example.com
gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Secret key is available.
sec rsa4096/A39421B65EF4D2D7
created: 2022-03-24 expires: 2025-03-23 usage: C
trust: ultimate validity: ultimate
ssb rsa4096/18832C062E4EBE77
created: 2022-03-24 expires: 2025-03-23 usage: E
ssb rsa4096/EFE05191993439D6
created: 2022-03-24 expires: 2025-03-23 usage: S
ssb rsa4096/5B4D08C955707D10
created: 2022-03-24 expires: 2025-03-23 usage: A
[ultimate] (1). alice <alice@example.com>

使用主密钥的场景

主密钥只具有[C]功能,只在以下情形时使用主密钥:

  1. 签署其他人密钥或撤销现有签名;
  2. 添加新身份信息或将现有 UID 标记为主 UID;
  3. 创建新子秘钥;
  4. 撤销现有 UID 或子密钥;
  5. 更改 UID 的首选项(例如,使用 setpref);
  6. 更改主密钥或其任何子秘钥的过期日期;
  7. 撤销或生成完整密钥的撤销证书。

备份方案

方案一:单独导出备份文件

# 备份步骤
# step 1: 导出秘钥信息,其中包括所有公钥,私钥,信任网数据库文件,进行备份
gpg --export > public-keys.gpg
gpg --export-secret-keys > private-keys.gpg
gpg --export-ownertrust > ownertrust.asc
# step 2: 导出秘钥吊销凭证,建议单独备份
gpg --armor --gen-revoke [primary key ID] > revocation.asc
# 恢复秘钥
# step 1: 导出公钥,私钥和信任网数据库
gpg --import pgp-public-keys.asc
gpg --import pgp-private-keys.asc
gpg --import-ownertrust pgp-ownertrust.asc
# 如果秘钥泄露,需要吊销秘钥
gpg --import pgp-revocation.asc

方案二:全文件夹备份,加密保存

# 压缩目录,备份文件
tar -zcvf gnupg.tar.gz ~/.gnupg/*
# 恢复秘钥,解压文件
tar -zxvf gnupg.tar.gz

个人喜欢方案二,只要保证备份和解压时的权限是安全的,后者更方便。特殊场合使用时插上 U 盘直接在 U 盘中对秘钥进行操作,由于不涉及到硬盘读写,自然不会在硬盘中留下痕迹。

主密钥离线使用

主密钥和子秘钥职责分离后,用到主密钥的场合非常少。需要主密钥执行某些操作时,插上 U 盘,保证环境权限安全的情况下,解压 gnupg.tar.gz,恢复秘钥即可。

使用时可通过设置环境变量的方式

export GNUPGHOME=/media/yourdrive/path/to/.gnupg
gpg -k

或者使用 --homedir 参数。

gpg --homedir=/media/yourdrive/path/to/.gnupg -k

而日常使用中,涉及到加密、签名和身份认证,使用子秘钥的场合会更多一些。这里的要点是让主密钥的私钥(secret primary key)离线,同时重设新密码来保护子秘钥。使用这种方式,就算新密码被泄露,主私钥(secret primary key)依然保持安全——备份的秘钥仍在旧密码的保护中且主私钥文件没有泄露。

# step 1:导出子私钥,公钥和信任信息
gpg --export-secret-subkeys > private-subkeys.gpg # 注意:是 --export-secret-subkeys 而不是 --export-secret-keys
gpg --export > public-keys.gpg
gpg --export-ownertrust > ownertrust.asc
# step 2: 重新恢复秘钥,目的是让 sec(secret primary key)离线
gpg --import private-subkeys.gpg
gpg --import public-keys.gpg
gpg --import-ownertrust ownertrust.asc
# step 3: 检查是否离线,以 sec 后面带有#为准
gpg -K
/home/alice/.gnupg/pubring.kbx
---------------------------
sec# rsa3072 2022-03-25 [SC]
C105EE41AB5FDFAB2D00F2FFA39421B65EF4D2D7
uid [ultimate] alice <alice@example.com>
ssb rsa3072 2022-03-25 [E]
# step 4: 修改密码,更换为新的密码
gpg --change-passphrase C105EE41AB5FDFAB2D00F2FFA39421B65EF4D2D7

保持更新公钥

定期更新公钥,及时同步对方公钥的过期、撤销信息,避免在对方已撤销公钥的情况下发送加密信息,务必确认公钥的有效性。

参考资料

本文作者:杨奇的博客
版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。
杨奇的博客 微信公众号
微信公众号
杨奇的博客
评论