什么是GnuPG?

GPG,全称GNU Privacy Guard,是一种加密技术,它可以用来确保你的文件和通信的安全。GPG是一个自由的、兼容OpenPGP(RFC4880)的公钥加密体系。它没有任何依赖专利或专有实现的算法,这意味着它可以在任何地方自由使用。

GPG不仅提供加密,还提供认证,这意味着你可以用它验证一个文件是否是由特定的人发送的,或者一个程序是否是由特定的公司发布的。这是通过使用公钥和私钥来实现的。公钥用于加密文件或验证签名,而私钥用于解密文件或创建签名。

密钥类型

共有四种类型的密钥,对应的缩写如下:

类型 全名 缩写
主公钥 Public Key pub
子公钥 Public Subkey sub
主私钥 Secret Key sec
子私钥 Secret Subkey ssb

用途(Usage)

每个密钥可以用不同的用途,下表是不同用途的含义:

缩写 全名 用途
C Certificating 认证,如子密钥或证书,类似根证书的作用。
S Signing 签名,如文件数字签名、邮件签名、Git 提交。
A Authenticating 身份验证,如登录。
E Encrypting 加密,如文件和文本。

具有 C 的密钥是主密钥,只有这个密钥可以用于:

  • 添加或撤销子密钥的用途
  • 添加、更改或撤销密钥关联的身份(UID)
  • 添加或更改本身或其他子密钥的到期时间
  • 为了网络信任目的为其它密钥签名

生成密钥

密钥分为根密钥和子密钥, 子密钥通过根密钥生成, 一个根密钥可以生成多个子密钥

生成根密钥(Public Key)

root@484407860d3b:~# gpg --full-gen-key 
gpg (GnuPG) 2.2.19; Copyright (C) 2019 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.

# 选择加密方式, 一般选择RSA 4096
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? 
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 bits
# 密钥过期时间, 0表示永不过期, 2y表示2年后过期
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: testuser 
Email address: test@email.com
Comment: test 
You selected this USER-ID:
    "testuser (test) <test@email.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.
ssssdwWe 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.
qdgpg: key C4AF71D03907D4B1 marked as ultimately trusted
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/E28F3B6D42B3183FD89A390FC4AF71D03907D4B1.rev'
public and secret key created and signed.

# 根密钥 用于签名, 认证(SC)
pub   rsa4096 2024-01-08 [SC]
      E28F3B6D42B3183FD89A390FC4AF71D03907D4B1
uid                      testuser (test) <test@email.com>
# 子密钥, 用于加密(E)
sub   rsa4096 2024-01-08 [E]

生成子密钥(Public Subkey)

root@484407860d3b:~# gpg --expert --edit-key testuser
gpg (GnuPG) 2.2.19; Copyright (C) 2019 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/C4AF71D03907D4B1
     created: 2024-01-08  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/6EEDB0026720F40A
     created: 2024-01-08  expires: never       usage: E   
[ultimate] (1). testuser (test) <test@email.com>

# 添加一个密钥, 推荐Curve 25519算法, 速度快且安全度较高
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? 12
Please select which elliptic curve you want:
   (1) Curve 25519
   (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
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/C4AF71D03907D4B1
     created: 2024-01-08  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/6EEDB0026720F40A
     created: 2024-01-08  expires: never       usage: E   
ssb  cv25519/959AE4E662B00FC1
     created: 2024-01-08  expires: never       usage: E   
[ultimate] (1). testuser (test) <test@email.com>

# 最后save保存这次操作
gpg> save

生成撤销证书

root@484407860d3b:~# gpg --gen-revoke E28F3B6D42B3183FD89A390FC4AF71D03907D4B1

sec  rsa4096/C4AF71D03907D4B1 2024-01-08 testuser (test) <test@email.com>

Create a revocation certificate for this key? (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
(Probably you want to select 1 here)
Your decision? 0
Enter an optional description; end it with an empty line:
> test revoke
> 
Reason for revocation: No reason specified
test revoke
Is this okay? (y/N) y
ASCII armored output forced.
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: This is a revocation certificate

iQJBBCABCgArFiEE4o87bUKzGD/YmjkPxK9x0DkH1LEFAmWbmgANHQB0ZXN0IHJl
dm9rZQAKCRDEr3HQOQfUse9ZD/9Mdq3KGbj/gd8IGK8akpL+ZTEyeZlw6zT2ZnkY
wjNji1mzwO+AjWiSAaapxL8oZt8pkiHLfrqdqd1yVZTNNdJWAG0KO+2spZp5Y/nb
IbiQbmbC5P+rYsIlogFe+u6n5BUBmtzaPzfRQA/3IIHEmfq8DYRXCBTt2UOy22ZX
aJUswms7ZGKwkCmopPaAZ9zrXVnRwN09dOYOp0yVoooHQcouGMUB32vr/ptcUPZo
6ET25N7ovMDw8ie90bqXk3t7/SPCMCGMazwI+BWEfYicEcWUtu1z3F5vFJXXZTCk
8YYaTbe7NatpfFETeIQ6/TFRl92IoMQqQsS9rwfcewVRM1NlN7S9OVDNCpVfKwLI
yaWTnznS9rW7KVqG9HSNHqyz9MX6/sOAu1yVQnhVbY1bWU6WSYpxwXLe88g/LVHK
XqKGw1IudSNrv2cEx+SC5+UNsQA9L39+VoNQqvEWDY8ni2+dtIgx5m3Evl0lNroS
v46E9OnCi/vUYr9qx02ydAJvRDG8tTrkGN2AffYCfOkI5pDUsDsiZL6fYNYO0Dfx
go+TcfZpq3obG/m8y5ZGGMYWo/Xf3HMFaHuyYs3bmRb5gkg51219JoIUJAGjwlgk
l/U0Pc81d5SvUDFphu6DOEGWD5QUopUX0qryRFWYCkS+A1uvU1PB7QTM1bwX0wJh
sVbltQ==
=2h7n
-----END PGP PUBLIC KEY BLOCK-----
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

请将其移至一个你可以隐藏的媒介;如果别人获得了这个证书,他可以使用它使你的密钥变得无法使用。

管理密钥

查看密钥

# 查看公钥
gpg -k
# or
gpg --list-key

# 查看私钥
gpg -K
# or
gpg --list-secret-key

删除密钥

如果公钥有配对私钥, 需要先删除私钥, 然后才能删除公钥

# 删除私钥
gpg --delete-secret-keys [密钥ID]

# 删除公钥
gpg --delete-keys [密钥ID]

导入导出密钥

# 导入
gpg --import key.gpg

# 导出公钥
gpg --armor --output public-key.gpg --export [密钥ID]

# 导出私钥
gpg --armor --output secret-key.gpg --export-secret-keys [密钥ID]

加密与解密

加密文件

# 假定当前目录下有一个待加密的文件test.txt
gpg --recipient [密钥ID] --output test.en.txt --encrypt test.txt
# 此时目录下会生成一个加密后的文件test.en.txt

recipient参数指定接收者的公钥,output参数指定加密后的文件名,encrypt参数指定源文件。

解密文件

# 假定当前目录下有一个被加密的文件test.en.txt
gpg --output test.txt --decrypt test.en.txt
# 此时目录下会生成一个解密后的文件test.txt

参考链接

https://blog.zhanganzhi.com/zh-CN/2022/06/1c71f69657ed/

https://www.ruanyifeng.com/blog/2013/07/gpg.html