在 GPG 中使用智能卡(安全令牌)

安装必要的软件环境

$ sudo apt-get install haveged gnupg2 gnupg-agent libpth20 pinentry-curses libccid pcscd scdaemon libksba8 paperkey opensc

创建密钥

创建过程中,如果要重来,可以直接删除的配置目录: rm -r ~/.gnupg

更安全的配置

根据 Using GPG with Smart Cards介绍,这个配置可带来更高的安全性。

$ mkdir ~/.gnupg
$ cat > ~/.gnupg/gpg.conf << !
no-emit-version
no-comments
keyid-format 0xlong
with-fingerprint
use-agent
personal-cipher-preferences AES256 AES192 AES CAST5
personal-digest-preferences SHA512 SHA384 SHA256 SHA224
cert-digest-algo SHA512
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
!

生成密钥

如果你要将密钥放在智能卡中使用,建议先阅读“进阶操作-密钥续期”章节,理解后再决定密钥过期时间的配置,是否要如我示例那样的配置。

以完整配置方式创建。

$ gpg2 --full-gen-key

主密钥仅用于签名子密码,不用于加密和签名操作,保证安全。

gpg (GnuPG) 2.1.11; Copyright (C) 2016 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.

请选择您要使用的密钥种类:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (仅用于签名)
(4) RSA (仅用于签名)
您的选择? 4

密钥长度选择4096位更安全。但如果像我要将一个主密钥通用于 GPG 和 PGP 的,只能选2048,因为PGP只支持2048。

RSA 密钥长度应在 1024 位与 4096 位之间。
您想要用多大的密钥尺寸?(2048) 
您所要求的密钥尺寸是 2048 位

主密钥不会过期。

请设定这把密钥的有效期限。
       0 = 密钥永不过期
    <n>  = 密钥在 n 天后过期
    <n>w = 密钥在 n 周后过期
    <n>m = 密钥在 n 月后过期
    <n>y = 密钥在 n 年后过期
密钥的有效期限是?(0) 
密钥永远不会过期
以上正确吗?(y/n) y

输入一些信息。

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

真实姓名: fake name
电子邮件地址: fake@fake.com
注释: 演示用途
You are using the 'utf-8' character set.
您选定了这个用户标识:
    “fake name (演示用途) <fake@fake.com>”

更改姓名(N)、注释(C)、电子邮件地址(E)或确定(O)/退出(Q)? o
我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动
鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。
gpg: /home/jebbs/.gnupg/trustdb.gpg:建立了信任度数据库
gpg: 密钥 34DBFFCB 被标记为绝对信任
gpg: directory '/home/jebbs/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/jebbs/.gnupg/openpgp-revocs.d/1D109D9DC3C7A6FCE20104726F55A1A134DBFFCB.rev'
公钥和私钥已经生成并经签名。

gpg: 正在检查信任度数据库
gpg: marginals needed: 3  completes needed: 1  trust model: PGP
gpg: 深度:0 有效性:  1 已签名:  0 信任度:0-,0q,0n,0m,0f,1u
请注意这把密钥还不能用来加密,您必须先用“--edit-key”指令
生成用于加密的子钥。
pub   rsa2048/34DBFFCB 2017-01-18 [S]
    密钥指纹 = 1D10 9D9D C3C7 A6FC E201  0472 6F55 A1A1 34DB FFCB
uid         [ 绝对 ] fake name (演示用途) <fake@fake.com>

查看创建的密钥

$ gpg2 --list-keys

/home/jebbs/.gnupg/pubring.kbx
------------------------------
pub   rsa2048/34DBFFCB 2017-01-18 [SC]
uid         [ 绝对 ] fake name (演示用途) <fake@fake.com>

添加用户标识

进入编辑。

$ gpg2 --edit-key 34DBFFCB 
gpg (GnuPG) 2.1.11; Copyright (C) 2016 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.

私钥可用。

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
[ 绝对 ] (1). fake name (演示用途) <fake@fake.com>

添加一个“fake2@fake.com”标识。此步骤可重复。

gpg> adduid
真实姓名: fake name
电子邮件地址: fake2@fake.com
注释: 演示用途
You are using the 'utf-8' character set.
您选定了这个用户标识:
    “fake name (演示用途) <fake2@fake.com>”

更改姓名(N)、注释(C)、电子邮件地址(E)或确定(O)/退出(Q)? o

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
[ 绝对 ] (1)  fake name (演示用途) <fake@fake.com>
[ 未知 ] (2). fake name (演示用途) <fake2@fake.com>

选中第一个标识,并设为主标识。

gpg> uid 1

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
[ 绝对 ] (1)* fake name (演示用途) <fake@fake.com>
[ 未知 ] (2). fake name (演示用途) <fake2@fake.com>

gpg> primary

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
[ 绝对 ] (1)* fake name (演示用途) <fake@fake.com>
[ 未知 ] (2)  fake name (演示用途) <fake2@fake.com>

保存。

gpg> save

创建子密钥

进入编辑模式。

$ gpg2 --expert --edit-key 34DBFFCB 
gpg (GnuPG) 2.1.11; Copyright (C) 2016 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.

私钥可用。

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
[ 绝对 ] (1). fake name (演示用途) <fake@fake.com>
[ 绝对 ] (2)  fake name (演示用途) <fake2@fake.com>

创建签名密钥

创建一个签名用途的密钥。

gpg> addkey
请选择您要使用的密钥种类:
(3) DSA (仅用于签名)
(4) RSA (仅用于签名)
(5) ElGamal (仅用于加密)
(6) RSA (仅用于加密)
(7) DSA (自定义用途)
(8) RSA (自定义用途)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
您的选择? 4

因为 Yubikey NEO 最大支持 2048 位密钥,这里长度按默认设置。6个月后过期。过期后的密钥还能用于解密和验证,但不能用于加密和签名。

RSA 密钥长度应在 1024 位与 4096 位之间。
您想要用多大的密钥尺寸?(2048) 
您所要求的密钥尺寸是 2048 位
请设定这把密钥的有效期限。
       0 = 密钥永不过期
    <n>  = 密钥在 n 天后过期
    <n>w = 密钥在 n 周后过期
    <n>m = 密钥在 n 月后过期
    <n>y = 密钥在 n 年后过期
密钥的有效期限是?(0) 6m
密钥于 2017年07月17日 星期一 02时34分13秒 PDT 过期
以上正确吗?(y/n) y
真的要建立吗?(y/N) y

完成创建。

我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动
鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
ssb  rsa2048/5768E78E
    创建于:2017-01-18  有效至:2017-07-17  可用于:S   
[ 绝对 ] (1). fake name (演示用途) <fake@fake.com>
[ 绝对 ] (2)  fake name (演示用途) <fake2@fake.com>

创建加密密钥

创建一个加密用途的密钥。

gpg> addkey
请选择您要使用的密钥种类:
(3) DSA (仅用于签名)
(4) RSA (仅用于签名)
(5) ElGamal (仅用于加密)
(6) RSA (仅用于加密)
(7) DSA (自定义用途)
(8) RSA (自定义用途)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
您的选择? 6

因为 Yubikey NEO 最大支持 2048 位密钥,这里长度按默认设置。6个月后过期。过期后的密钥还能用于解密和验证,但不能用户加密和签名。

RSA 密钥长度应在 1024 位与 4096 位之间。
您想要用多大的密钥尺寸?(2048) 
您所要求的密钥尺寸是 2048 位
请设定这把密钥的有效期限。
       0 = 密钥永不过期
    <n>  = 密钥在 n 天后过期
    <n>w = 密钥在 n 周后过期
    <n>m = 密钥在 n 月后过期
    <n>y = 密钥在 n 年后过期
密钥的有效期限是?(0) 6m
密钥于 2017年07月17日 星期一 02时38分47秒 PDT 过期
以上正确吗?(y/n) y
真的要建立吗?(y/N) y

完成创建。

我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动
鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
ssb  rsa2048/5768E78E
    创建于:2017-01-18  有效至:2017-07-17  可用于:S   
ssb  rsa2048/1717A309
    创建于:2017-01-18  有效至:2017-07-17  可用于:E   
[ 绝对 ] (1). fake name (演示用途) <fake@fake.com>
[ 绝对 ] (2)  fake name (演示用途) <fake2@fake.com>

创建授权密钥

对于 PGP 来说,没有这个密钥。

选择自定义用途。

gpg> addkey
请选择您要使用的密钥种类:
(3) DSA (仅用于签名)
(4) RSA (仅用于签名)
(5) ElGamal (仅用于加密)
(6) RSA (仅用于加密)
(7) DSA (自定义用途)
(8) RSA (自定义用途)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
您的选择? 8

切换为仅认证用途。

RSA 密钥可能的操作: 签名 加密 认证 
目前允许的操作: 签名 加密 

(S) 选择是否用于签名
(E) 选择是否用于加密
(A) 选择是否用于认证
(Q) 已完成

您的选择? s

RSA 密钥可能的操作: 签名 加密 认证 
目前允许的操作: 加密 

(S) 选择是否用于签名
(E) 选择是否用于加密
(A) 选择是否用于认证
(Q) 已完成

您的选择? e

RSA 密钥可能的操作: 签名 加密 认证 
目前允许的操作: 

(S) 选择是否用于签名
(E) 选择是否用于加密
(A) 选择是否用于认证
(Q) 已完成

您的选择? a

RSA 密钥可能的操作: 签名 加密 认证 
目前允许的操作: 认证 

(S) 选择是否用于签名
(E) 选择是否用于加密
(A) 选择是否用于认证
(Q) 已完成

您的选择? q

长度与过期时间与上方的相同。

RSA 密钥长度应在 1024 位与 4096 位之间。
您想要用多大的密钥尺寸?(2048) 
您所要求的密钥尺寸是 2048 位
请设定这把密钥的有效期限。
       0 = 密钥永不过期
    <n>  = 密钥在 n 天后过期
    <n>w = 密钥在 n 周后过期
    <n>m = 密钥在 n 月后过期
    <n>y = 密钥在 n 年后过期
密钥的有效期限是?(0) 6m
密钥于 2017年07月17日 星期一 02时43分01秒 PDT 过期
以上正确吗?(y/n) y
真的要建立吗?(y/N) y

完成创建。

我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动
鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
ssb  rsa2048/5768E78E
    创建于:2017-01-18  有效至:2017-07-17  可用于:S   
ssb  rsa2048/1717A309
    创建于:2017-01-18  有效至:2017-07-17  可用于:E   
ssb  rsa2048/A1894B03
    创建于:2017-01-18  有效至:2017-07-17  可用于:A   
[ 绝对 ] (1). fake name (演示用途) <fake@fake.com>
[ 绝对 ] (2)  fake name (演示用途) <fake2@fake.com>

保存退出。

gpg> save

创建吊销凭证

$ gpg2 --gen-revoke 34DBFFCB

sec  rsa2048/34DBFFCB 2017-01-18 fake name (演示用途) <fake@fake.com>

要为这把密钥建立一份吊销证书吗?(y/N) y
请选择吊销的原因:
0 = 未指定原因
1 = 密钥已泄漏
2 = 密钥被替换
3 = 密钥不再使用
Q = 取消
(也许您会想要在这里选择 1)
您的决定是什么? 1
请输入描述(可选);以空白行结束:
> 
吊销原因:密钥已泄漏
(不给定描述)
这样可以吗? (y/N) y
已强行使用 ASCII 封装过的输出。
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
Comment: This is a revocation certificate

iQEfBCABCAAJBQJYfznKAh0CAAoJEG9VoaE02//LCEwH/i3X+hVaSqnYOjBCa2iv
NwKvEp1M0cIbEF7vYP9lHLU6HjzA/y9RSbzjuijkz8JPyvgtOOg+TP9nubDb97zd
TysSHNA6rkI87f/j+HIa73rFUQJ9i6WgyjkeyHKGYIxAV9sSgECveBOzusozAmG5
TrOhUb7q3oOQTqHUV8aTVA9oggHuRHMyA6r17aWOXlyDrSzVtrEU5eZAHDoEHOwp
P+NfQzSl+jmTgtPzWLzdcmJpS21LW2YvxBFOXZa4s9dLcpub2y8vRmtGimIypVxG
ImT7Cvgu34An0WO06n0QE4UcOX9nW4RiqiTKzUj/JCnbOC9jUm7YOTZ11j35C1/y
7wg=
=xBse
-----END PGP PUBLIC KEY BLOCK-----
已建立吊销证书。

请把这个文件转移到一个可隐藏起来的介质(如软盘)上;如果坏人能够取得这
份证书的话,那么他就能让您的密钥无法继续使用。把这份凭证打印出来再藏
到安全的地方也是很好的方法,以免您的保存媒体损毁而无法读取。但是千万
小心:您的机器上的打印系统可能会在打印过程中把这些数据临时在某个其他
人也能够看得到的地方!

最后的结果

$ gpg2 --list-keys
/home/jebbs/.gnupg/pubring.kbx
------------------------------
pub   rsa2048/34DBFFCB 2017-01-18 [SC]
uid         [ 绝对 ] fake name (演示用途) <fake@fake.com>
uid         [ 绝对 ] fake name (演示用途) <fake2@fake.com>
sub   rsa2048/5768E78E 2017-01-18 [S] [有效至:2017-07-17]
sub   rsa2048/1717A309 2017-01-18 [E] [有效至:2017-07-17]
sub   rsa2048/A1894B03 2017-01-18 [A] [有效至:2017-07-17]

备份密钥

最简单的办法是备份整个gpg数据目录。

$ tar -czf /path/to/gnupg.tgz ~/.gnupg

备份私钥.

$ gpg2 -a --export-secret-key  34DBFFCB >> /path/to/34DBFFCB.master.key
$ gpg2 -a --export-secret-subkeys  34DBFFCB >> /path/to/34DBFFCB.sub.key

以上文件一定要小心保存,避免泄露!

导入密钥

$ gpg2 -a --import *.asc
$ gpg2 --list-keys

进阶操作

密钥续期

密钥过期后,还能用于解密和验证,但不能用于加密和签名。这时有两个选择,更换密钥或续期。

对于一般场景(能够存储无限的密钥),更换密钥是更合理的做法。具体步骤可参考前述创建子密钥的过程。但要注意过期的密钥不可删除,因为还需要用他们来解密之前加密过的文件。

对于将密码放在智能卡中的用户,更换密钥就有些麻烦了。往往一个智能卡中只能存储一套密钥,更换了之后安全性是有保障,但对于旧文件,就无法用智能卡解密和验证了。

如果要为过期的密钥续期。可如下操作。

进入编辑。

$ gpg2 --expert --edit-key 34DBFFCB 

选中已过期的密钥。

gpg> key 1

修改过期设置。

gpg> expire
将要变更子钥的使用期限。
请设定这把密钥的有效期限。
       0 = 密钥永不过期
    <n>  = 密钥在 n 天后过期
    <n>w = 密钥在 n 周后过期
    <n>m = 密钥在 n 月后过期
    <n>y = 密钥在 n 年后过期
密钥的有效期限是?(0) 6m
密钥于 2017年07月17日 星期一 18时39分32秒 PDT 过期
以上正确吗?(y/n) y

使用智能卡

如果在虚拟机下编辑智能卡,需要打开虚拟机配置(.vmx)文件,加入以下两行:

usb.generic.allowHID = “TRUE”

usb.generic.allowLastHID = “TRUE”

设置智能卡

编辑智能卡。

$ gpg2 --card-edit

启用管理员命令。

gpg/card> admin

修改智能卡密码

gpg/card> passwd

设置姓名、性别、语言。更多属性可查看 help。

gpg/card> name
gpg/card> sex
gpg/card> lang

结束编辑。

gpg/card> list
gpg/card> quit

将密钥放入智能卡

查看密钥清单。

gpg> list

sec  rsa2048/34DBFFCB
    创建于:2017-01-18  有效至:永不过期       可用于:SC  
    信任度:绝对        有效性:绝对
ssb  rsa2048/5768E78E
    创建于:2017-01-18  有效至:2017-07-17  可用于:S   
ssb  rsa2048/1717A309
    创建于:2017-01-18  有效至:2017-07-17  可用于:E   
ssb  rsa2048/A1894B03
    创建于:2017-01-18  有效至:2017-07-17  可用于:A   
[ 绝对 ] (1). fake name (演示用途) <fake@fake.com>
[ 绝对 ] (2)  fake name (演示用途) <fake2@fake.com>

选中密钥、放入智能卡、取消选中密钥。

gpg> key 1
gpg> keytocard
gpg> key 1
gpg> key 2
gpg> keytocard
gpg> key 2
gpg> key 3
gpg> keytocard

保存。

gpg> save

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注