runsisi's

technical notes

操作 GPG 密钥对

2019-04-13 runsisi#gpg

注意本文仅针对 gpg2,gpg1 的使用与此类似,但在命令输出上可能存在一些不同。

在 Ubuntu18.04 下,/usr/bin/gpg2 是指向 /usr/bin/gpg 的符号链接:

~$ ll /usr/bin/gpg2
lrwxrwxrwx 1 root root 3 Jan 10 21:07 /usr/bin/gpg2 -> gpg*
~$ gpg --version
gpg (GnuPG) 2.2.4
libgcrypt 1.8.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/runsisi/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

如果需要使用 gpg1 可以显式进行安装:

~$ sudo apt install gnupg1
Reading package lists... Done
Building dependency tree       
Reading state information... Done
...
~$ gpg1 --version
gpg (GnuPG) 1.4.22
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: ~/.gnupg
Supported algorithms:
Pubkey: RSA, RSA-E, RSA-S, ELG-E, DSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

gpg 文件

gpg1/gpg2 的文件默认都存放在 ~/.gnupg/ 目录下,可以通过环境变量 GNUPGHOME 或命令行选项 --homedir 进行显式指定;

gpg1 的公钥保存在 ~/.gnupg/pubring.gpg 中,私钥保存在 ~/.gnupg/secring.gpg 中;

gpg2 的公钥保存在 ~/.gnupg/pubring.kbx 中,私钥保存在 ~.gnupg/private-keys-v1.d/ 目录下;

gpg2 支持对 gpg1 密钥的操作;

配置文件为 ~/.gnupg/gpg.conf,支持命令行中的所有长选项,去掉 -- 前缀即可;

创建 gpg 密钥对

--gen-key, --generate-key

~$ gpg --gen-key
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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.

gpg: directory '/home/runsisi/.gnupg' created
gpg: keybox '/home/runsisi/.gnupg/pubring.kbx' created
Note: Use "gpg --full-generate-key" for a full featured key generation dialog.

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

Real name: runsisi
Email address: runsisi@hust.edu.cn
You selected this USER-ID:
    "runsisi <runsisi@hust.edu.cn>"

Change (N)ame, (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.
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/runsisi/.gnupg/trustdb.gpg: trustdb created
gpg: key B6D4491D45E0A945 marked as ultimately trusted
gpg: directory '/home/runsisi/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/runsisi/.gnupg/openpgp-revocs.d/97A12DC8EA8FDFCE5B95ABFDB6D4491D45E0A945.rev'
public and secret key created and signed.

pub   rsa3072 2019-04-13 [SC] [expires: 2021-04-12]
      97A12DC8EA8FDFCE5B95ABFDB6D4491D45E0A945
uid                      runsisi <runsisi@hust.edu.cn>
sub   rsa3072 2019-04-13 [E] [expires: 2021-04-12]

这里 gpg2 与 gpg1 的不同点在于,gpg2 默认会以简化的方式生成密钥对,用户只用填写用户名和邮箱地址,gpg2 如果要实现与 gpg1 相同的效果,即定制新生成的密钥对,可以使用选项 --full-gen-key, --full-generate-key

~$ gpg --full-gen-key
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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.

gpg: directory '/home/runsisi/.gnupg' created
gpg: keybox '/home/runsisi/.gnupg/pubring.kbx' created
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)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 
Requested keysize is 3072 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) 1y
Key expires at Sun 12 Apr 2020 10:27:30 AM CST
Is this correct? (y/N) y

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

Real name: runsisi
Email address: runsisi@hust.edu.cn
Comment: https://runsisi.com/
You selected this USER-ID:
    "runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>"

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.
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/runsisi/.gnupg/trustdb.gpg: trustdb created
gpg: key 1AA13362F3363106 marked as ultimately trusted
gpg: directory '/home/runsisi/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/runsisi/.gnupg/openpgp-revocs.d/457B18262C79C9A84813F36D1AA13362F3363106.rev'
public and secret key created and signed.

pub   rsa3072 2019-04-13 [SC] [expires: 2020-04-12]
      457B18262C79C9A84813F36D1AA13362F3363106
uid                      runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>
sub   rsa3072 2019-04-13 [E] [expires: 2020-04-12]

列出密钥

列出公钥:-k, --list-keys

列出私钥:-K, --list-secret-keys

gpg2 有一个很让人费解的显示问题,即在显示 key 时默认不显示 key 的 id:

~$ gpg -k
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2021-04-12
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072 2019-04-13 [SC] [expires: 2021-04-12]
      E1D30EAD59D37D2A35997E9897DB5E40D3BBC728
uid           [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072 2019-04-13 [E] [expires: 2021-04-12]

可以在命令行上加上 --keyid-format 选项指定显示格式:

~$ gpg -k --keyid-format short
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/D3BBC728 2019-04-13 [SC] [expires: 2021-04-12]
      E1D30EAD59D37D2A35997E9897DB5E40D3BBC728
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/A70AB032 2019-04-13 [E] [expires: 2021-04-12]

或者在配置文件中进行配置:

~$ cat ~/.gnupg/gpg.conf
keyid-format short
~$ gpg -k
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/D3BBC728 2019-04-13 [SC] [expires: 2021-04-12]
      E1D30EAD59D37D2A35997E9897DB5E40D3BBC728
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/A70AB032 2019-04-13 [E] [expires: 2021-04-12]

~$ gpg -K
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
sec   rsa3072/D3BBC728 2019-04-13 [SC] [expires: 2021-04-12]
      E1D30EAD59D37D2A35997E9897DB5E40D3BBC728
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
ssb   rsa3072/A70AB032 2019-04-13 [E] [expires: 2021-04-12]

此外,如果加上 --with-keygrip 参数,将显示私钥的 grip 信息(类似于私钥文件 id):

~$ gpg -k --with-keygrip
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/461A17E3 2019-04-13 [SC] [expires: 2021-04-12]
      49EDCB80BEBA29A28594FCA919786F86461A17E3
      Keygrip = FC39E3A6865397B8CBEAA4457D51C9974DCB16DA
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/878D403A 2019-04-13 [E] [expires: 2021-04-12]
      Keygrip = 0E637E42DB533D24E742DE50D36D43264578671B

~$ gpg -K --with-keygrip
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
sec   rsa3072/461A17E3 2019-04-13 [SC] [expires: 2021-04-12]
      49EDCB80BEBA29A28594FCA919786F86461A17E3
      Keygrip = FC39E3A6865397B8CBEAA4457D51C9974DCB16DA
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
ssb   rsa3072/878D403A 2019-04-13 [E] [expires: 2021-04-12]
      Keygrip = 0E637E42DB533D24E742DE50D36D43264578671B

~$ ll ~/.gnupg/private-keys-v1.d/
total 16
drwx------ 2 runsisi runsisi 4096 Apr 13 13:46 ./
drwx------ 4 runsisi runsisi 4096 Apr 13 13:51 ../
-rw------- 1 runsisi runsisi 1623 Apr 13 13:46 0E637E42DB533D24E742DE50D36D43264578671B.key
-rw------- 1 runsisi runsisi 1623 Apr 13 13:46 FC39E3A6865397B8CBEAA4457D51C9974DCB16DA.key

注意 gpg 中的 key 实际上是一组密钥对(public/private keypair),key id 实际上就是密钥对的 id,因此 --list-keys--list-secret-keys 中 id 相同的公钥和私钥组成一组密钥对。

创建子密钥对

gpg 默认创建的密钥包含两组密钥对,pub/sec 对应主密钥对(primary/master key),sub/ssb 对应子密钥对(subkey),其中主密钥对用于签名和密钥管理(SC),子密钥对用于加密(E)。

E = encrypt/decrypt (decrypt a message you received encrypted for you to read)
S = sign (sign data. For example a file or to send signed e-mail)
C = certify (sign another key, establishing a trust-relation)
A = authentication (log in to SSH with a PGP key; this is relatively new usage)

主密钥对类似于身份证,由于过于重要而不适合日常使用,因此,需要基于它创建子密钥对用于日常使用。

~$ gpg --edit-key A70AB032
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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  rsa3072/D3BBC728
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/A70AB032
     created: 2019-04-13  expires: 2021-04-12  usage: E   
[ultimate] (1). runsisi <runsisi@hust.edu.cn>

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)
Your selection? 3
DSA keys may be between 1024 and 3072 bits long.
What keysize do you want? (2048) 
Requested keysize is 2048 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) 2y
Key expires at Mon 12 Apr 2021 12:56:10 PM CST
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.
gpg: WARNING: some OpenPGP programs can't handle a DSA key with this digest size

sec  rsa3072/D3BBC728
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/A70AB032
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/F8B6E5FE
     created: 2019-04-13  expires: 2021-04-12  usage: S   
[ultimate] (1). runsisi <runsisi@hust.edu.cn>

gpg> list

sec  rsa3072/D3BBC728
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/A70AB032
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/F8B6E5FE
     created: 2019-04-13  expires: 2021-04-12  usage: S   
[ultimate] (1). runsisi <runsisi@hust.edu.cn>

gpg> save
~$ gpg -k
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/D3BBC728 2019-04-13 [SC] [expires: 2021-04-12]
      E1D30EAD59D37D2A35997E9897DB5E40D3BBC728
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/A70AB032 2019-04-13 [E] [expires: 2021-04-12]
sub   dsa2048/F8B6E5FE 2019-04-13 [S] [expires: 2021-04-12]

注意:如果 gpg 命令行参数需要指定密钥对 id,则可以指定主密钥对 id 或任一子密钥对 id,实际效果一样,对于 --export, --export-secret-keys, --export-secret-subkeys 之类的操作,可以在 keyid 之后加上一个叹号(!),用于显式的指定该 key 进行导出(注意:subkey 的导出总会带上 primary key)。

导出密钥

导出公钥:

~$ gpg -k
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/461A17E3 2019-04-13 [SC] [expires: 2021-04-12]
      49EDCB80BEBA29A28594FCA919786F86461A17E3
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/878D403A 2019-04-13 [E] [expires: 2021-04-12]
sub   dsa2048/A6395BAA 2019-04-13 [S] [expires: 2019-05-13]

~$ gpg -o pub -a --export 878D403A

导出全部密钥对的私钥:

~$ gpg -o priv -a --export-secret-keys A6395BAA

仅导出子密钥对的私钥:

~$ gpg -o privsub -a --export-secret-subkeys

导入密钥

~$ rm -rf .gnupg/
~$ gpg --import pub
gpg: directory '/home/runsisi/.gnupg' created
gpg: keybox '/home/runsisi/.gnupg/pubring.kbx' created
gpg: /home/runsisi/.gnupg/trustdb.gpg: trustdb created
gpg: key 19786F86461A17E3: public key "runsisi <runsisi@hust.edu.cn>" imported
gpg: Total number processed: 1
gpg:               imported: 1
~$ echo 'keyid-format short' > ~/.gnupg/gpg.conf
~$ gpg -k
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/461A17E3 2019-04-13 [SC] [expires: 2021-04-12]
      49EDCB80BEBA29A28594FCA919786F86461A17E3
uid         [ unknown] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/878D403A 2019-04-13 [E] [expires: 2021-04-12]
sub   dsa2048/A6395BAA 2019-04-13 [S] [expires: 2019-05-13]

~$ gpg -K
~$ gpg --import privsub
gpg: key 461A17E3: "runsisi <runsisi@hust.edu.cn>" not changed
gpg: To migrate 'secring.gpg', with each smartcard, run: gpg --card-status
gpg: key 461A17E3: secret key imported
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
~$ gpg -k
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/461A17E3 2019-04-13 [SC] [expires: 2021-04-12]
      49EDCB80BEBA29A28594FCA919786F86461A17E3
uid         [ unknown] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/878D403A 2019-04-13 [E] [expires: 2021-04-12]
sub   dsa2048/A6395BAA 2019-04-13 [S] [expires: 2019-05-13]

~$ gpg -K
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
sec#  rsa3072/461A17E3 2019-04-13 [SC] [expires: 2021-04-12]
      49EDCB80BEBA29A28594FCA919786F86461A17E3
uid         [ unknown] runsisi <runsisi@hust.edu.cn>
ssb   rsa3072/878D403A 2019-04-13 [E] [expires: 2021-04-12]
ssb   dsa2048/A6395BAA 2019-04-13 [S] [expires: 2019-05-13]

~$ gpg -k --with-keygrip
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/461A17E3 2019-04-13 [SC] [expires: 2021-04-12]
      49EDCB80BEBA29A28594FCA919786F86461A17E3
      Keygrip = FC39E3A6865397B8CBEAA4457D51C9974DCB16DA
uid         [ unknown] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/878D403A 2019-04-13 [E] [expires: 2021-04-12]
      Keygrip = 0E637E42DB533D24E742DE50D36D43264578671B
sub   dsa2048/A6395BAA 2019-04-13 [S] [expires: 2019-05-13]
      Keygrip = B81CF86A48DDDCD36532830231A06F605F3D536C

~$ ll .gnupg/private-keys-v1.d/
total 16
drwx------ 2 runsisi runsisi 4096 Apr 13 14:26 ./
drwx------ 3 runsisi runsisi 4096 Apr 13 14:26 ../
-rw------- 1 runsisi runsisi 1623 Apr 13 14:26 0E637E42DB533D24E742DE50D36D43264578671B.key
-rw------- 1 runsisi runsisi 1094 Apr 13 14:26 B81CF86A48DDDCD36532830231A06F605F3D536C.key
~$ rm -f .gnupg/private-keys-v1.d/B81CF86A48DDDCD36532830231A06F605F3D536C.key 
~$ gpg -K --with-keygrip
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
sec#  rsa3072/461A17E3 2019-04-13 [SC] [expires: 2021-04-12]
      49EDCB80BEBA29A28594FCA919786F86461A17E3
      Keygrip = FC39E3A6865397B8CBEAA4457D51C9974DCB16DA
uid         [ unknown] runsisi <runsisi@hust.edu.cn>
ssb   rsa3072/878D403A 2019-04-13 [E] [expires: 2021-04-12]
      Keygrip = 0E637E42DB533D24E742DE50D36D43264578671B
ssb#  dsa2048/A6395BAA 2019-04-13 [S] [expires: 2019-05-13]
      Keygrip = B81CF86A48DDDCD36532830231A06F605F3D536C

注意 ssb# 表示该密钥对没有对应的私钥。

注意到 uid 中的 unknown 字段:

~$ gpg --edit-key runsisi@hust.edu.cn
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: unknown       validity: unknown
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/E413E62F
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ unknown] (1). runsisi <runsisi@hust.edu.cn>

gpg> trust
sec  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: unknown       validity: unknown
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/E413E62F
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ unknown] (1). runsisi <runsisi@hust.edu.cn>

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

sec  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: unknown
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/E413E62F
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ unknown] (1). runsisi <runsisi@hust.edu.cn>
Please note that the shown key validity is not necessarily correct
unless you restart the program.

gpg> q
~$ gpg -k
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2021-04-12
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/574A4861 2019-04-13 [SC] [expires: 2021-04-12]
      C8EB6E7EEBA2286C0443FA1B03C6395A574A4861
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/94D17A29 2019-04-13 [E] [expires: 2021-04-12]
sub   dsa2048/E413E62F 2019-04-13 [S] [expires: 2020-04-12]

或者:

~$ gpg --edit-key 94D17A29
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: full          validity: unknown
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/E413E62F
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ unknown] (1). runsisi <runsisi@hust.edu.cn>

gpg> trust
sec  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: full          validity: unknown
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/E413E62F
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ unknown] (1). runsisi <runsisi@hust.edu.cn>

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

sec  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: unknown
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/E413E62F
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ unknown] (1). runsisi <runsisi@hust.edu.cn>
Please note that the shown key validity is not necessarily correct
unless you restart the program.

gpg> q
~$ gpg -k
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2021-04-12
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/574A4861 2019-04-13 [SC] [expires: 2021-04-12]
      C8EB6E7EEBA2286C0443FA1B03C6395A574A4861
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/94D17A29 2019-04-13 [E] [expires: 2021-04-12]
sub   dsa2048/E413E62F 2019-04-13 [S] [expires: 2020-04-12]

设置或延长过期时间

注意过期时间的设置需要指定具体的密钥对,在 gpg 交互终端中通过 key # 命令选择需要设置的密钥对编号,其中 # 从 0 开始编号,ssb* 表示当前选中的密钥对。

~$ gpg -k
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/574A4861 2019-04-13 [SC] [expires: 2021-04-12]
      C8EB6E7EEBA2286C0443FA1B03C6395A574A4861
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/94D17A29 2019-04-13 [E] [expires: 2021-04-12]
sub   dsa2048/E413E62F 2019-04-13 [S] [expires: 2021-04-12]

~$ gpg --edit-key 94D17A29
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  dsa2048/E413E62F
     created: 2019-04-13  expires: 2021-04-12  usage: S   
[ultimate] (1). runsisi <runsisi@hust.edu.cn>

gpg> key 2

sec  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb* dsa2048/E413E62F
     created: 2019-04-13  expires: 2021-04-12  usage: S   
[ultimate] (1). runsisi <runsisi@hust.edu.cn>

gpg> expire
Changing expiration time for a subkey.
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) 1y
Key expires at Sun 12 Apr 2020 02:43:09 PM CST
Is this correct? (y/N) y

sec  rsa3072/574A4861
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/94D17A29
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb* dsa2048/E413E62F
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ultimate] (1). runsisi <runsisi@hust.edu.cn>

gpg> save
~$ gpg -k
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2021-04-12
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072/574A4861 2019-04-13 [SC] [expires: 2021-04-12]
      C8EB6E7EEBA2286C0443FA1B03C6395A574A4861
uid         [ultimate] runsisi <runsisi@hust.edu.cn>
sub   rsa3072/94D17A29 2019-04-13 [E] [expires: 2021-04-12]
sub   dsa2048/E413E62F 2019-04-13 [S] [expires: 2020-04-12]

增加 uid

~$ gpg --edit-key 8D77F675
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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.

gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2021-04-12
sec  rsa3072/68CCC50DC7E8A950
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE04FBED2E0CB2D
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  rsa3072/DA3BFDCF8D77F675
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ultimate] (1). runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>

gpg> adduid
Real name: luo.runbing
Email address: luo.runbing@example.com
Comment: https://example.com/
You selected this USER-ID:
    "luo.runbing (https://example.com/) <luo.runbing@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

sec  rsa3072/68CCC50DC7E8A950
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE04FBED2E0CB2D
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  rsa3072/DA3BFDCF8D77F675
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ultimate] (1)  runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>
[ unknown] (2). luo.runbing (https://example.com/) <luo.runbing@example.com>

gpg> uid 2

sec  rsa3072/68CCC50DC7E8A950
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE04FBED2E0CB2D
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  rsa3072/DA3BFDCF8D77F675
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ultimate] (1)  runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>
[ unknown] (2)* luo.runbing (https://example.com/) <luo.runbing@example.com>

gpg> trust
sec  rsa3072/68CCC50DC7E8A950
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE04FBED2E0CB2D
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  rsa3072/DA3BFDCF8D77F675
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ultimate] (1)  runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>
[ unknown] (2)* luo.runbing (https://example.com/) <luo.runbing@example.com>

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

sec  rsa3072/68CCC50DC7E8A950
     created: 2019-04-13  expires: 2021-04-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE04FBED2E0CB2D
     created: 2019-04-13  expires: 2021-04-12  usage: E   
ssb  rsa3072/DA3BFDCF8D77F675
     created: 2019-04-13  expires: 2020-04-12  usage: S   
[ultimate] (1)  runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>
[ unknown] (2)* luo.runbing (https://example.com/) <luo.runbing@example.com>

gpg> q
Save changes? (y/N) y
~$ gpg -k
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2021-04-12
/home/runsisi/.gnupg/pubring.kbx
--------------------------------
pub   rsa3072 2019-04-13 [SC] [expires: 2021-04-12]
      6DF6CFC20424F5CA2BC540E768CCC50DC7E8A950
uid           [ultimate] luo.runbing (https://example.com/) <luo.runbing@example.com>
uid           [ultimate] runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>
sub   rsa3072 2019-04-13 [E] [expires: 2021-04-12]
sub   rsa3072 2019-04-13 [S] [expires: 2020-04-12]

查看 gpg 密钥组成

公钥:

~$ gpg --export D2E0CB2D | gpg --list-packets
# off=0 ctb=99 tag=6 hlen=3 plen=397
:public key packet:
	version 4, algo 1, created 1555140245, expires 0
	pkey[0]: [3072 bits]
	pkey[1]: [17 bits]
	keyid: 68CCC50DC7E8A950
# off=400 ctb=b4 tag=13 hlen=2 plen=52
:user ID packet: "runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>"
# off=454 ctb=89 tag=2 hlen=3 plen=468
:signature packet: algo 1, keyid 68CCC50DC7E8A950
	version 4, created 1555140358, md5len 0, sigclass 0x13
	digest algo 10, begin of digest 5d 49
	hashed subpkt 33 len 21 (issuer fpr v4 6DF6CFC20424F5CA2BC540E768CCC50DC7E8A950)
	hashed subpkt 2 len 4 (sig created 2019-04-13)
	hashed subpkt 27 len 1 (key flags: 03)
	hashed subpkt 9 len 4 (key expires after 2y0d0h0m)
	hashed subpkt 11 len 4 (pref-sym-algos: 9 8 7 2)
	hashed subpkt 21 len 5 (pref-hash-algos: 10 9 8 11 2)
	hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
	hashed subpkt 30 len 1 (features: 01)
	hashed subpkt 23 len 1 (keyserver preferences: 80)
	subpkt 16 len 8 (issuer key ID 68CCC50DC7E8A950)
	data: [3070 bits]
# off=925 ctb=b9 tag=14 hlen=3 plen=397
:public sub key packet:
	version 4, algo 1, created 1555140245, expires 0
	pkey[0]: [3072 bits]
	pkey[1]: [17 bits]
	keyid: 6FE04FBED2E0CB2D
# off=1325 ctb=89 tag=2 hlen=3 plen=444
:signature packet: algo 1, keyid 68CCC50DC7E8A950
	version 4, created 1555140245, md5len 0, sigclass 0x18
	digest algo 10, begin of digest 1f 3b
	hashed subpkt 33 len 21 (issuer fpr v4 6DF6CFC20424F5CA2BC540E768CCC50DC7E8A950)
	hashed subpkt 2 len 4 (sig created 2019-04-13)
	hashed subpkt 27 len 1 (key flags: 0C)
	hashed subpkt 9 len 4 (key expires after 2y0d0h0m)
	subpkt 16 len 8 (issuer key ID 68CCC50DC7E8A950)
	data: [3069 bits]
# off=1772 ctb=b9 tag=14 hlen=3 plen=397
:public sub key packet:
	version 4, algo 1, created 1555140475, expires 0
	pkey[0]: [3072 bits]
	pkey[1]: [17 bits]
	keyid: DA3BFDCF8D77F675
# off=2172 ctb=89 tag=2 hlen=3 plen=882
:signature packet: algo 1, keyid 68CCC50DC7E8A950
	version 4, created 1555140475, md5len 0, sigclass 0x18
	digest algo 10, begin of digest 5e 70
	hashed subpkt 33 len 21 (issuer fpr v4 6DF6CFC20424F5CA2BC540E768CCC50DC7E8A950)
	hashed subpkt 2 len 4 (sig created 2019-04-13)
	hashed subpkt 27 len 1 (key flags: 02)
	hashed subpkt 9 len 4 (key expires after 1y0d0h0m)
	subpkt 16 len 8 (issuer key ID 68CCC50DC7E8A950)
	subpkt 32 len 435 (signature: v4, class 0x19, algo 1, digest algo 10)
	data: [3065 bits]

私钥:

~$ gpg --export-secret-subkeys D2E0CB2D | gpg --list-packets
# off=0 ctb=95 tag=5 hlen=3 plen=405
:secret key packet:
	version 4, algo 1, created 1555140245, expires 0
	pkey[0]: [3072 bits]
	pkey[1]: [17 bits]
	gnu-dummy S2K, algo: 0, simple checksum, hash: 0
	protect IV: 
	keyid: 68CCC50DC7E8A950
# off=408 ctb=b4 tag=13 hlen=2 plen=52
:user ID packet: "runsisi (https://runsisi.com/) <runsisi@hust.edu.cn>"
# off=462 ctb=89 tag=2 hlen=3 plen=468
:signature packet: algo 1, keyid 68CCC50DC7E8A950
	version 4, created 1555140358, md5len 0, sigclass 0x13
	digest algo 10, begin of digest 5d 49
	hashed subpkt 33 len 21 (issuer fpr v4 6DF6CFC20424F5CA2BC540E768CCC50DC7E8A950)
	hashed subpkt 2 len 4 (sig created 2019-04-13)
	hashed subpkt 27 len 1 (key flags: 03)
	hashed subpkt 9 len 4 (key expires after 2y0d0h0m)
	hashed subpkt 11 len 4 (pref-sym-algos: 9 8 7 2)
	hashed subpkt 21 len 5 (pref-hash-algos: 10 9 8 11 2)
	hashed subpkt 22 len 3 (pref-zip-algos: 2 3 1)
	hashed subpkt 30 len 1 (features: 01)
	hashed subpkt 23 len 1 (keyserver preferences: 80)
	subpkt 16 len 8 (issuer key ID 68CCC50DC7E8A950)
	data: [3070 bits]
# off=933 ctb=9d tag=7 hlen=3 plen=1414
:secret sub key packet:
	version 4, algo 1, created 1555140245, expires 0
	pkey[0]: [3072 bits]
	pkey[1]: [17 bits]
	iter+salt S2K, algo: 7, SHA1 protection, hash: 2, salt: 3BC9249E447CF6A6
	protect count: 65011712 (255)
	protect IV:  d0 63 ec fc 81 4f 04 b7 65 d5 94 b4 a3 0e e0 c7
	skey[2]: [v4 protected]
	keyid: 6FE04FBED2E0CB2D
# off=2350 ctb=89 tag=2 hlen=3 plen=444
:signature packet: algo 1, keyid 68CCC50DC7E8A950
	version 4, created 1555140245, md5len 0, sigclass 0x18
	digest algo 10, begin of digest 1f 3b
	hashed subpkt 33 len 21 (issuer fpr v4 6DF6CFC20424F5CA2BC540E768CCC50DC7E8A950)
	hashed subpkt 2 len 4 (sig created 2019-04-13)
	hashed subpkt 27 len 1 (key flags: 0C)
	hashed subpkt 9 len 4 (key expires after 2y0d0h0m)
	subpkt 16 len 8 (issuer key ID 68CCC50DC7E8A950)
	data: [3069 bits]
# off=2797 ctb=9d tag=7 hlen=3 plen=1414
:secret sub key packet:
	version 4, algo 1, created 1555140475, expires 0
	pkey[0]: [3072 bits]
	pkey[1]: [17 bits]
	iter+salt S2K, algo: 7, SHA1 protection, hash: 2, salt: 7A5BE9838C34CB0E
	protect count: 65011712 (255)
	protect IV:  09 e3 3c 3d 9d 91 1a 7c d8 0f d6 75 3e 5d bb 20
	skey[2]: [v4 protected]
	keyid: DA3BFDCF8D77F675
# off=4214 ctb=89 tag=2 hlen=3 plen=882
:signature packet: algo 1, keyid 68CCC50DC7E8A950
	version 4, created 1555140475, md5len 0, sigclass 0x18
	digest algo 10, begin of digest 5e 70
	hashed subpkt 33 len 21 (issuer fpr v4 6DF6CFC20424F5CA2BC540E768CCC50DC7E8A950)
	hashed subpkt 2 len 4 (sig created 2019-04-13)
	hashed subpkt 27 len 1 (key flags: 02)
	hashed subpkt 9 len 4 (key expires after 1y0d0h0m)
	subpkt 16 len 8 (issuer key ID 68CCC50DC7E8A950)
	subpkt 32 len 435 (signature: v4, class 0x19, algo 1, digest algo 10)
	data: [3065 bits]

参考资料

GPG2 (GnuGP 2) Guide

https://docs.releng.linuxfoundation.org/en/latest/gpg.html

GPG(pgp)加解密中文完整教程

http://www.alexgao.com/2009/01/24/gpg/

GPG Tutorial

http://www.futureboy.us/pgp.html

GPG For Humans, Part 1: Why Care About Cryptography?

https://www.paulfurley.com/gpg-for-humans-why-care-about-cryptography/

GPG For Humans, Part 2: Public Key Crypto Primer

https://www.paulfurley.com/gpg-for-humans-public-key-crypto-primer/

GPG For Humans, Part 3: Protecting your Primary Key

https://www.paulfurley.com/gpg-for-humans-protecting-your-primary-key/

GPG For Humans, Part 4: Preparing an Offline Machine

https://www.paulfurley.com/gpg-for-humans-preparing-an-offline-machine/

How to change the expiration date of a GPG key

https://www.g-loaded.eu/2010/11/01/change-expiration-date-gpg-key/

What exactly is a subkey?

https://security.stackexchange.com/questions/76940/what-exactly-is-a-subkey

GPG - why am I encrypting with subkey instead of primary key?

https://serverfault.com/questions/397973/gpg-why-am-i-encrypting-with-subkey-instead-of-primary-key

Using OpenPGP subkeys in Debian development

https://wiki.debian.org/Subkeys

GPG Subkeys

https://oguya.ch/posts/2016-04-01-gpg-subkeys/

Protecting your private master key in GnuPG 2.1 and later

https://rudd-o.com/linux-and-free-software/protecting-your-private-master-key-in-gnupg-2-1-and-later

How to select a specific subkey for signing?

https://lists.gnupg.org/pipermail/gnupg-users/2002-June/013787.html

Anatomy of a GPG Key

https://davesteele.github.io/gpg/2014/09/20/anatomy-of-a-gpg-key/