测试环境为 mac

gpg –version gpg (GnuPG) 2.2.11 libgcrypt 1.8.4 Copyright © 2018 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: /tmp/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

概念

  • 密码: 用来保护私钥的.这样子, 即使你的 ~/.gnupg 目录被泄漏了, 还有一层密码保护
  • 主密钥 : 一般是你调用 gpg --full-gen-key 命令生成的那个密钥.
  • 子密钥 : subkey, 跟主密钥几乎没有差别, 除了它是隶属于 主密钥 的. 注意, 子密钥是可以单独用来加解密的. 只是它要隶属于主密钥来管理.
  • 密钥的能力
    • [S] : 表示用于签名
    • [E] : 表示用于加密
    • [A] : 表示用于身份认证
    • [C] : 用于认证其他的密钥. 带有这个的, 一般是 主密钥 这个密钥的数字, 就是你的身份.

安装

mac
brew install gnupg

ubuntu
一般默认已经有安装了
sudo apt-get install gnupg
sudo apt-get install gnupg2

配置

目录位置使用 $GNUPGHOME 来指定. 默认情况下没有设置, 会使用 $HOME , 这时目录为 ~/.gnupg . 注意, 该目录的权限应该为 700 , 目录里的文件权限应该为 600

修改的两种方式

  • gpg --homedir path/to/config/dir
  • 或设置 $GNUPGHOME 环境变量

默认的配置文件为 ~/.gnupg/gpg.conf~/.gnupg/dirmngr.conf

创建密钥对

$ export GNUPGHOME=/tmp/gnupg
$ mkdir /tmp/gnupg
$ chmod 700 /tmp/gnupg
$ gpg --full-gen-key

gpg (GnuPG) 2.2.11; Copyright (C) 2018 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: keybox '/tmp/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? (2048) 4096 # 密钥是多少 bit 的
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

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

Real name: emacsist # 名字
Email address: emacsist@qq.com # 邮箱地址
Comment: me # 注释
You selected this USER-ID:
    "emacsist (me) <emacsist@qq.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O #英文O, ok 的意思

注意, 中途会有再输入密码的, 这次输入的密码, 是用来保护私钥的. 后面每次用到私钥的时候, 它都会让你再输入这个保护私钥的密码来使用私钥.

列出可用公钥服务器

gpg-connect-agent --dirmngr 'keyserver --hosttable'

公钥

查看

$ gpg --list-keys
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
/tmp/gnupg/pubring.kbx
----------------------
pub   rsa4096 2019-01-01 [SC]
      98BF8A387D565D6C528EF316A66AD6F72204E772
uid           [ultimate] emacsist (me) <emacsist@qq.com>
sub   rsa4096 2019-01-01 [E]

导出

gpg --output /tmp/emacsist.pub.key --armor --export emacsist

导入

gpg --import /tmp/emacsist.pub.key

公钥服务器

上传自己的公钥

gpg --keyserver wwwkeys.uk.pgp.net --send-keys 98BF8A387D565D6C528EF316A66AD6F72204E772

后面那个 98BF8A387D565D6C528EF316A66AD6F72204E772gpg --list-keys 列出的那个 pub 对应的一串数字.

从公钥服务器搜索

gpg --keyserver wwwkeys.uk.pgp.net --search-keys 98BF8A387D565D6C528EF316A66AD6F72204E772

如果上面上传成功了, 然后我们搜索
$ gpg --keyserver wwwkeys.uk.pgp.net --search-keys 98BF8A387D565D6C528EF316A66AD6F72204E772
gpg: data source: http://wwwkeys.uk.pgp.net:11371
(1)	emacsist (me) <emacsist@qq.com>
	  4096 bit RSA key A66AD6F72204E772, created: 2019-01-01
Keys 1-1 of 1 for "98BF8A387D565D6C528EF316A66AD6F72204E772".  Enter number(s), N)ext, or Q)uit >

从公钥服务器导入

gpg --keyserver wwwkeys.uk.pgp.net --recv-keys 98BF8A387D565D6C528EF316A66AD6F72204E772

示例
$ gpg --keyserver wwwkeys.uk.pgp.net --recv-keys 98BF8A387D565D6C528EF316A66AD6F72204E772
gpg: key A66AD6F72204E772: "emacsist (me) <emacsist@qq.com>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1

上面显示是 `not changed` , 因为这是我自己的.如果是导入其他人的话, 就会报告成功了.这只是当作演示.

私钥

查看

$ gpg --list-secret-keys
....

备份

可以完整备份你的 ~/.gnupg 目录

cp -rp ~/.gnupg /your/usb/gnupg-backup

验证备份目录是否可以正常工作
gpg --homedir=/your/usb/gnupg-backup --list-key

subkey 子密钥

添加subkey

gpg --edit-key emacsist
进入程序后, 然后再输入  `addkey` 回车.

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? 6
RSA keys may be between 1024 and 4096 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)
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y

列出所有

$ gpg -K
/tmp/gnupg/pubring.kbx
----------------------
sec   rsa4096 2019-01-01 [SC]
      98BF8A387D565D6C528EF316A66AD6F72204E772
uid           [ultimate] emacsist (me) <emacsist@qq.com>
ssb   rsa4096 2019-01-01 [E]
ssb   rsa2048 2019-01-01 [E]

下面那两个 ssb 就是 subkey. 第一次创建时, 默认也会创建一个 subkey.

导出子私密钥

$ gpg -a --export-secret-subkeys emacsist > /tmp/subkey.gpg
这会导出emacsist所有的 subkey 的私密钥

如果只想导出特定的子私密钥

gpg --output secret-subkeys --export-secret-subkeys 62224FF27AFA8EDD!

62224FF27AFA8EDD! 替换为你的 subkey id, 注意后面的 ! 号.

导入

gpg --import secret-subkeys

吊销 subkey

gpg --edit-key emacsist
选定哪个 key. N 是序号. 如果正确选中的话, 某个 key 会出现 `*` 符号. 默认是选中所有.
gpg>key N
gpg>revkey
gpg>save

删除 subkey

gpg --edit-key emacsist
选定哪个 key. N 是序号. 如果正确选中的话, 某个 key 会出现 `*` 符号. 默认是选中所有.
gpg>key N
gpg>delkey
gpg>save

信任 subkey

gpg --edit-key emacsist
选定哪个 key. N 是序号. 如果正确选中的话, 某个 key 会出现 `*` 符号. 默认是选中所有.
gpg>key N
gpg>trust
gpg>save

加解密

加解

默认情况是使用主密钥来解密的

$ echo "hello world" > test.txt

使用 emacsist 这个用户的公钥来加密. 可以有多个 `--recipient`, 这样子, 他们相应的私钥就可以密钥这些内容
$ gpg --recipient emacsist --encrypt test.txt

以 `*.gpg` 结尾的就是加密后的文件
$ ls test.txt*
test.txt  test.txt.gpg

$ file test.txt.gpg
test.txt.gpg: PGP RSA encrypted session key - keyid: 7D66A4E0 E46E0A72 RSA (Encrypt or Sign) 4096b .

使用指定 subkey

gpg --edit-key emacsist
gpg: WARNING: unsafe permissions on homedir '/Users/emacsist/tmp'
gpg (GnuPG) 2.2.11; Copyright (C) 2018 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/526157F06AC98F09
     created: 2019-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A974FCDBAA825066
     created: 2019-01-01  expires: never       usage: E
ssb  rsa2048/62224FF27AFA8EDD
     created: 2019-01-01  expires: never       usage: E
[ultimate] (1). emacsist (me) <emacsist@qq.com>

ssb rsa2048/62224FF27AFA8EDD 这个是我创建的 subkey

这里指定用这个来加密

gpg -r 0x62224FF27AFA8EDD -e /tmp/hello.txt

注意是 -r 0x62224FF27AFA8EDD

-e 表示加密

-d 表示解密

解密

$ gpg --output decrypt.test.txt --decrypt test.txt.gpg
这时会提示你输入私钥的保护密码, 输入正确后就可以正确解密了

$ cat decrypt.test.txt
hello world

私钥维护

gpg --edit-key emacsist

表示修改 emacsist 的私钥. 进入后, 输入 help 来列出所有子命令. 常用的有

  • passwd : 修改保护私钥的密码
  • clean : 清除过期或无效的
  • expire : 设置过期
  • revoke : 回收

签名

生成签名文件

 $ gpg --output test.txt.sig --sign test.txt
 
 这条命令, 会将签名和原文件合成一个文件输出到 test.txt.sig 文件中

仅生成签名文件

$ gpg --output test.txt.sig --detach-sig test.txt

验证签名

gpg --verify test.txt.sig
这条是验证签名和文件合成一个的

如果是想验证签名文件和原文件的话, 则原文件和签名文件要在同一个目录出现

gpg --verify test.txt.sig

test.txt.sig 和 text.txt 文件要放在一起

安全

备份好 ~/.gnupg 目录后. 再执行以下操作来删除 主密钥 .

列出 keygrip, 看到你的主密钥(带有 `[C]`) 的 keygrip 是多少
$ gpg --with-keygrip --list-key

然后列出 

$ ls -alh ~/.gnupg/private-keys-v1.d

删除主密钥的 KEY 文件. 
$ rm ~/.gnupg/private-keys-v1.d/your-master.key

再列出一次私密钥
$ gpg --list-secret-keys
/tmp/gnupg/pubring.kbx
----------------------
sec#  rsa4096 2019-01-01 [SC]
      98BF8A387D565D6C528EF316A66AD6F72204E772
uid           [ultimate] emacsist (me) <emacsist@qq.com>
ssb   rsa4096 2019-01-01 [E]
ssb   rsa2048 2019-01-01 [E]
可以看到 `[SC]` 那里有个 `#` , 表示不可用了.

最后删除吊销证书 `xxx.rev`
$ cd ~/.gnupg/openpgp-revocs.d
$ rm 你主密钥的key.rev

处理完主密钥后, 之后的加解密都使用特定的 subkey 来操作.

设置免密码超时时间

在配置目录 $GNUPGHOME 下的文件 gpg-agent.conf (如果没有可以创建).

default-cache-ttl 600
maximum-cache-ttl 7200

单位为秒. 然后执行下面的命令kill掉 pgp-agent

gpgconf --kill gpg-agent