gpg

Ling Yu
Ling Yu

GPG使用 1

生成密钥对

生成随机数

sudo apt install rng-tools
sudo rngd -r /dev/urandom

生成密钥对

  1. 简单方式
gpg --generate-key or --gen-key
  1. 高级方式
gpg --full-generate-key or --full-gen-key

以下是常见缩写释义

A    =>    Authentication
C    =>    Certify
E    =>    Encrypt
S    =>    Sign
?    =>    Unknown capability
sec  =>    Secret Key
ssb  =>    Secret SuBkey
pub  =>    Public Key
sub  =>    Public Subkey

生成子密钥对

你日常使用应该使用子密钥,主密钥除了签发新的子密钥不要使用。

建议为不同环境,不同用途都单独生成子密钥,互不干扰。

# step 0
gpg --edit-key <id> # 或者key id  
 
# step 1  进入gpg交互界面 
gpg (GnuPG) 2.2.20; Copyright (C) 2020 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/99F583599B7E31F1
     created: 2021-01-11  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE9C71CFED44076
     created: 2021-01-11  expires: never       usage: E
[ultimate] (1). linus <[email protected]>C
 
# step 2  
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)
  (14) Existing key from card
Your selection? 4   
# 根据你的用途选择, 这里生成一个只用于签名的子密钥(sign only)
 
#  后面的选择和主密钥生成的大同小异,按提示操作即可
 
# 生成完毕后
sec  rsa3072/99F583599B7E31F1
     created: 2021-01-11  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/6FE9C71CFED44076
     created: 2021-01-11  expires: never       usage: E
ssb  rsa3072/FDB960B857D397F6
     created: 2021-01-11  expires: never       usage: S
[ultimate] (1). linus <[email protected]>
 
#  last step
gpg>  save  #  记得save, 直接退出的话什么也没有

或者

gpg --expert --edit-key <key ID|Fingerprint|uid>

生成撤销证书

假如你忘了主密钥的密码,或者丢失了对主密钥的控制权(丢失,被夺取),如果没有撤销凭证的话, 除了一个个通知你的朋友们没有任何办法 证明你不再使用这个密钥,这简直是灾难。

# step 0
gpg --gen-revoke -ao   revoke.pgp   linus # uid 或者key id
 
# step 1
sec  rsa3072/99F583599B7E31F1 2021-01-11 linus <[email protected]m>
 
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) 3
 
# 按提示走完流程就可以

生成的revoke.pgp就是撤销凭证, 有了这个撤销凭证,你可以在没有密码的情况下使一个公钥失效,所以一定要妥善保存,而且最好比主密钥多一份。

查看密钥对

查看私钥,参数后面没有指定私钥,则输出所有私钥

gpg --list-secret-keys or -K

查看公钥,参数后面没有指定公钥,则输出所有公钥

gpg --list-keys or --list-public-keys or -k

这样并没有列出子密钥的id, 而且没有打印出指纹信息, 是不安全的。所以在你查看密钥时应该加上 --keyid-format long输出长ID加上 --fingerprint 输出指纹信息

gpg --fingerprint -K --keyid-format long

安全设置

每次都打 --keyid-format long和--fingerprint 很烦对不对, 编辑配置gpg文件, vim ~/.gnupg/gpg.conf

# ~/.gnupg/gpg.conf
keyid-format 0xlong
with-fingerprint

导出,导出密钥对

导出

导出私钥

gpg --export-secret-keys -a <id> > gpg_private_key.asc
gpg --export-secret-keys -a <id> -o gpg_private_key.asc

导出公钥

gpg --export -a <id> > gpg_public_key.asc
gpg --export -a <id> -o gpg_public_key.asc

导出子私钥

# 注意这里最后 要带上“!”, 不然会导出全部子密钥
gpg --export-secret-subkeys -a <id!> > gpg_private_subkey.asc
gpg --export-secret-subkeys -a <id!> -o gpg_private_subkey.asc
# 别忘了同时将你刚刚生成的撤销凭证也备份起来

其中:

-a 为 --armor 的简写,表示密钥以ASCII的形式输出,默认以二进制的形式输出;

-o 为 --output 的简写,指定写入的文件;

导入

导入私钥

gpg --import private.key

导入公钥

gpg --import public.key

命令行输入密码

  1. 直接输入密码
gpg --import --pinentry-mode loopback --batch --passphrase <password>  private.key
  1. 将密码输入到文件里
gpg --import --pinentry-mode loopback --batch --passphrase-file <password-file> private.key

删除密钥对

删除私钥

gpg --delete-secret-keys <id>

删除公钥

gpg --delete-keys <id>

实用技巧

加解密

# 加密:
 
# recipient指定接收者的公钥ID
gpg --recipient {keyid/uid} --output encrypt.txt --encrypt input.txt
# 也可以按喜好加上--armor选项等
 
# 我更喜欢用 
gpg  -se  -o  encrypt.txt  -r  {keyid/uid}   input.txt  
# s代表签名  e代表加密
# o是 将结果 输出到文件  encrypt.txt
# r后面跟 接收者的 uid或者 key id, 接收者的公钥必须已经导入过
# input.txt 是你要加密的文件
 
 
# 解密:
gpg --output decrypt.txt --decrypt encrypt.txt 
# 也可以
gpg -d encrypt.txt   # 输出到终端 直接查看

签名

对文件签名

有时候,我们不需要对文件进行加密,只需要对文件进行签名,表示这个文件确实是我本人发出的。使用sign参数来签名。 如果想生成单独的签名文件,与原文件内容分开存放,可以使用detach-sign参数。 如果想让生成的签名文件内容采用ASCII码的形式,要加上armor参数。

gpg --local-user <id> --armor --detach-sign test.txt
gpg --detach-sign --output signed.txt input.txt
gpg --detach-sign --armor --output signed.txt input.txt

签名+加密

如果想同时签名和加密,可以使用下面的命令,产生test.txt.asc文件,这个文件包含被加密文件和签名信息。

gpg --local-user [发信者ID] --recipient [接收者ID] --armor --sign --encrypt log.txt
gpg --local-user <id> --recipient <id> --armor --sign --output test.en.txt --encrypt test.txt

验证签名

我们收到别人签名后的文件,需要用对方的公钥验证签名是否为真。使用verify参数来验证。

签名asc文件和文件本身分离,验证命令如下:

gpg --verify test.txt.asc test.txt

发布 与 交换

公钥的交换是所有非对称加密算法的脆弱点,所谓现代的使用方式,主要体现在密钥的交换和发布上面, 之后会单独来探讨。

阅读并理解本系列之前请不要发布你的公钥到公钥服务器。

撤销

由于PGP没有提供任何将吊销信息通知其他用户的方式,他不能保证没人会使用撤销了的已经变得不安全的密钥。

你丢失的私钥仍然可以被攻击者使用,并用来解密那些没有更新你的公钥的人发送的加密消息。 revoke 子密钥并更新公钥后,若有人用老的公钥加密信息,虽然你仍然可以解密,但是攻击者同样可以,这时候是极度不安全的。

例如:如果A的私人密钥被盗,她将发出一个密钥撤销证书(key revocation certificate),但是由于这个密钥的分发是非正式的且将费大量的时间和口舌,故不能保证密钥环中每一个有A公开密钥的用户都能收到。由于A必须用她的私人密钥签名撤消的证书,所以如果A同时丢失了私人密钥,她就不能撤销密钥。密钥的撤销问题被认为是整个系统最薄弱的环节。

所以在你将密钥撤销后,请将撤销后的公钥发布到你一贯公布公钥的地方, 并尽可能通知其他人。

撤销主密钥

gpg --import gpg-linus.asc                                               # 在一台新的电脑上导入你的公钥
gpg: key 99F583599B7E31F1: "linus <[email protected]>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
 
 
 
gpg --import revoke                                                       # 导入你备份的撤销凭证,直接会导致密钥不可用
 
 
 
gpg: key 99F583599B7E31F1: "linus <[email protected]>" revocation certificate imported
gpg: Total number processed: 1
gpg:    new key revocations: 1
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: depth: 1  valid:   1  signed:   0  trust: 1-, 0q, 0n, 0m, 0f, 0u
gpg: next trustdb check due at 2021-09-29
 
 
 
gpg -k                                                                  # 查看密钥,已经revoke
 
 
pub   rsa3072 2021-01-11 [SC] [revoked: 2021-01-11]
      705358AB85366CAB05C0220F99F583599B7E31F1
uid           [ revoked] linus <[email protected]m>

撤销子密钥

gpg --edit-key linus  
 
gpg >   list  # 列出你所有的子密钥
gpg >   key  {n}  # 选择你要销毁的子密钥的 序号
gpg >   revkey
gpg >   save    # 退出前一定要save, 不然所有更改不会生效

添加多个uid

gpg --edit-key <id>
gpg> adduid
Real name: linus
Email address:
Comment:
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
save

设置主要uid

gpg --edit-key <id>
gpg> uid 1
gpg> primary
gpg> save

GitHub配置

curl https://github.com/web-flow.gpg | gpg --import
# 信任github的gpg密钥
gpg --sign-key 4AEE18F83AFDEB23

Footnotes

  1. https://zhuanlan.zhihu.com/p/344198727