PGP密钥对的两三事

发布于 2024-03-05  139 次阅读


PGP,全称 Pretty Good Privacy,是一个被设计用来加密信息,保护隐私的软件

但因为PGP是商业软件,万能的开源社区搞了一个基于OpenPGP标准的免费开源实现 —— GPG(Gnu PG);在本文里,GPG与PGP是等价的

但请注意,通常 "GPG"/"GnuPG" 仅用于指示一个软件,而GPG遵循OpenPGP标准,其相关概念与产物最好用 "PGP" 描述。例如:

  • PGP 密钥 ✅; GPG 密钥 ❌
  • PGP 签名 ✅; GPG 签名 ❌

GPG Key 管理

概念

在进入正文之前,我们先来了解一下GPG密钥的相关概念

GPG Key基于非对称加密,但不能简单地理解为Private Key/Public Key,它由1个主密钥和多个子密钥组成;GPG Key具有以下信息:

Key IDGPG Key 的唯一标识,值为主公钥的指纹,支持多种格式
UID标识该GPG Key的信息,每个 UID 由 name、email、comment 组成,email 和 comment 可以为空;一个GPG Key可以拥有多个UID
Expire过期时间,可以设置为永不过期
Keys子密钥的集合,允许只存在主密钥

Key 的类型

Key类型全名缩写用途说明
主私钥Secret KeysecSC有且只有一个 主私钥,可以选择一种或多种 Usage
主公钥Public KeypubSC有且只有一个 主公钥,可以选择一种或多种 Usage
子私钥Secret SubkeyssbS/A/E 可以拥有多个子私钥,每个子私钥可以选择一种或多种 Usage
子公钥Public SubkeysubS/A/E 可以拥有多个子公钥,每个子公钥可以选择一种或多种 Usage

Key 的用途

缩写全名用途说明
CCertificating可以用于管理GPG Key,如添加/删除/吊销等操作;主密钥必定具有C
SSigning签名,如文件签名,邮件签名,Git Commit签名;主密钥必定具有S
AAuthenticating身份验证,如SSH登录
EEncrypting加密
关于 C 用途的补充说明:
  • 添加或吊销子密钥的用途
  • 添加、更改或吊销密钥关联的身份(UID)
  • 添加或更改本身或其他子密钥的到期时间
  • 为了网络信任目的为其它密钥签名
  • 只有这个密钥可以进行以上操作

GPG Public Key

公钥(Public Key),顾名思义,是需要对外公开的,GPG公钥具有以下信息:

  • 主公钥与所有子公钥
  • 有效期与吊销信息
  • 所有UID

注意事项:

  • 在导出GPG公钥时,GPG会使用私钥对公钥进行签名,防止公钥被篡改
  • 如果你已经将公钥公布,任何对GPG Key的删除操作将不会生效,因为GPG更新公钥操作是合并新公钥与旧公钥,被删除的子密钥/UID会被恢复,正确的做法应当是吊销子密钥/UID
  • 任何对GPG Key的操作都需要重新发布GPG公钥

创建 GPG Key

生成Primary Key

执行以下命令,以生成主密钥:

$ gpg --full-gen-key
gpg (GnuPG) 2.2.41-unknown; Copyright (C) 2022 g10 Code GmbH
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)
  (14) Existing key from card
Your selection? 1 # 这里我选择RSA and RSA,兼容性最好

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096 # 输入RSA密钥的长度
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) 0 # 选择有效期,根据自己需要选择即可
Key does not expire at all
Is this correct? (y/N) y # 进行确认

GnuPG needs to construct a user ID to identify your key.

# UID部分
Real name: example # 输入你的名字
Email address: [email protected] # 输入你的邮箱
Comment: # 注释,正常情况下留空即可
You selected this USER-ID:
    "example <[email protected]>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
 # 输入“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: revocation certificate stored as '/c/Users/Tanuoxi/.gnupg/openpgp-revocs.d/39A2594E58C3681D10A3D27090A33BCEC0C88DE1.rev'
public and secret key created and signed.

pub   rsa4096 2024-03-05 [SC]
      39A2594E58C3681D10A3D27090A33BCEC0C88DE1
uid                      example <[email protected]>
sub   rsa4096 2024-03-05 [E]

在最后的输出中,可以看到:

  • 生成了一个主密钥和一个用于加密的子密钥
  • 39A2594E58C3681D10A3D27090A33BCEC0C88DE1 为该GPG Key的指纹

添加 Sub Key

进入目标GPG Key的编辑模式

# --expert为高级模式,因为gpg没有Auth Sub Key的预设,需要自行配置
$ gpg --expert --edit-key 39A2594E58C3681D10A3D27090A33BCEC0C88DE1

gpg (GnuPG) 2.2.41-unknown; Copyright (C) 2022 g10 Code GmbH
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.

# 90A33BCEC0C88DE1为主密钥Key ID
sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate


# DA91B926B4C0AB90 为子密钥Key ID
ssb  rsa4096/DA91B926B4C0AB90
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1). example <[email protected]>

gpg>
Sign Sub Key
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? 4 # 选择用于签名的RSA密钥
 
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096 # 输入RSA密钥长度
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) # 设置有效期
Key does not expire at all
Is this correct? (y/N) y # 确认
Really create? (y/N) y   # 再次确认
# 输入主密钥的密码进行认证

gpg> save # 别忘了保存
Encrypt Sub Key
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密钥
 
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096 # 输入RSA密钥长度
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) # 设置有效期
Key does not expire at all
Is this correct? (y/N) y # 确认
Really create? (y/N) y   # 再次确认
# 输入主密钥的密码进行认证

gpg> save # 别忘了保存
Authentication Key
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? 8 # 选择自定义用途的RSA密钥

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? A # 标记该密钥可用于验证身份 

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt Authenticate

   (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 Encrypt Authenticate
Current allowed actions: Encrypt Authenticate

   (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 Encrypt Authenticate
Current allowed actions: Authenticate

   (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 # 输入RSA密钥长度
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) # 设置有效期
Key does not expire at all
Is this correct? (y/N) y # 确认
Really create? (y/N) y   # 再次确认
# 输入主密钥的密码进行认证

gpg> save # 别忘了保存

吊销Sub Key

进入目标GPG Key的编辑模式

# --expert为高级模式,因为gpg没有Auth Sub Key的预设,需要自行配置
$ gpg --expert --edit-key 39A2594E58C3681D10A3D27090A33BCEC0C88DE1

gpg (GnuPG) 2.2.41-unknown; Copyright (C) 2022 g10 Code GmbH
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/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/DA91B926B4C0AB90
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1). example <[email protected]>

gpg> key 1 # 选中目标子密钥

sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa4096/DA91B926B4C0AB90 # 选中状态
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1). example <[email protected]>

gpg> revkey
Do you really want to revoke this subkey? (y/N) y # 确认吊销
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
Your decision? 0 # 选择吊销原因
Enter an optional description; end it with an empty line:
>
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y # 确认吊销

#输入主密钥密码

sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
The following key was revoked on 2024-03-05 by RSA key 90A33BCEC0C88DE1 example <[email protected]> # 已吊销该子密钥
ssb  rsa4096/DA91B926B4C0AB90
     created: 2024-03-05  revoked: 2024-03-05  usage: E
[ultimate] (1). example <[email protected]>

gpg>save #不要忘记保存

删除Sub Key

进入目标GPG Key的编辑模式

# --expert为高级模式,因为gpg没有Auth Sub Key的预设,需要自行配置
$ gpg --expert --edit-key 39A2594E58C3681D10A3D27090A33BCEC0C88DE1

gpg (GnuPG) 2.2.41-unknown; Copyright (C) 2022 g10 Code GmbH
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/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/DA91B926B4C0AB90
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1). example <[email protected]>

gpg> key 1 # 选中目标子密钥

sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa4096/DA91B926B4C0AB90 # 选中状态
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1). example <[email protected]>

gpg> delkey
Do you really want to delete this key? (y/N) y # 确认删除

sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
[ultimate] (1). example <[email protected]>

# 删除成功
gpg> save #不要忘记保存

添加UID

# 进入目标GPG Key的编辑模式
$ gpg --edit-key 39A2594E58C3681D10A3D27090A33BCEC0C88DE1
gpg> add uid
Real name: example # 你的名字
Email address: [email protected] #邮箱
Comment: # 注释
You selected this USER-ID:
    "example <[email protected]>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O # 确认
gpg> save # 保存

UID吊销与删除

# 进入目标GPG Key的编辑模式 
$ gpg --edit-key 39A2594E58C3681D10A3D27090A33BCEC0C88DE1
gpg> uid 2 # 选中 UID

sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/DA91B926B4C0AB90
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1)  example <[email protected]>
[ unknown] (2)* example <[email protected]>

gpg> revuid
Really revoke this user ID? (y/N) y #确认吊销
Please select the reason for the revocation:
  0 = No reason specified
  4 = User ID is no longer valid
  Q = Cancel
(Probably you want to select 4 here)
Your decision? 4 # 选择吊销原因
Enter an optional description; end it with an empty line:
>
Reason for revocation: User ID is no longer valid
(No description given)
Is this okay? (y/N) y # 确认吊销

 
sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/DA91B926B4C0AB90
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1)  example <[email protected]>
[ revoked] (2). example <[email protected]>

gpg> save # 保存

# 删除UID

gpg> uid 2 # 选中UID

sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/DA91B926B4C0AB90
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1). example <[email protected]>
[ revoked] (2)* example <[email protected]>

gpg> deluid # 删除UID
Really remove this user ID? (y/N) y # 确认操作

sec  rsa4096/90A33BCEC0C88DE1
     created: 2024-03-05  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/DA91B926B4C0AB90
     created: 2024-03-05  expires: never       usage: E
[ultimate] (1). example <[email protected]>

gpg> save # 保存

导入,导出与删除

导出

# 导出GPG Key公钥
gpg --output publicKey.asc --armor --export 你的GPG Key指纹
# 导出GPG Key主密钥及所有子密钥的私钥
gpg --output allPrivateKey.asc --armor --export-secret-keys 你的GPG Key指纹
# 导出GPG Key所有子密钥的私钥
gpg --output subPrivateKey.asc --armor --export-secret-subkeys 你的GPG Key指纹

导入

gpg --import 导出的文件

删除

# 删除私钥
gpg --delete-secret-keys UID 或 子秘钥 KeyID 或 主密钥 KeyID
# 删除公钥
# 注意,如果目标密钥存在对应的私钥,需要先删除私钥
gpg --delete-keys UID 或 子秘钥 KeyID 或 主密钥 KeyID

Git commit 签名配置

Git 配置

注意,用于签名的GPG Key密钥需要具有 S

# 设置用于签名的Key ID
git config --global user.signingkey Key ID
# 全局开启Commit签名
git config --global commit.gpgsign true

Github 配置

# 获取目标Key的公钥
gpg --armor --export 你的GPG Key指纹

gpg --armor --export 你的GPG Key指纹 输出的文本粘贴至Github 的GPG配置项即可

End.

参考文章


世界上本没有博客,直到有了程序员