GnuPG是由GNU組織開發的一款免費的加密軟件,採用OpenPGP標準(RFC4880),可用於數據、通信的加密和簽名。本文主要介紹的是GnuPG的簡單使用,如生成公鑰/私鑰對、列出公鑰、顯示公鑰指紋、生成Revoke Key、與keyserver交互、導出公鑰/私鑰、導入公鑰、文件加密/解密、文件簽名及校驗、刪除公鑰/私鑰、吊銷keyserver中的公鑰等。

具體使用實例見


Introduction

以下是WikiPedia對其的介紹

GNU Privacy Guard (GnuPG or GPG) is a free software replacement for Symantec’s PGP cryptographic software suite.

GnuPG is a complete and free implementation of the OpenPGP standard as defined by RFC4880 (also known as PGP). GnuPG allows to encrypt and sign your data and communication, features a versatile key management system as well as access modules for all kinds of public key directories. GnuPG, also known as GPG, is a command line tool with features for easy integration with other applications. A wealth of frontend applications and libraries are available. Version 2 of GnuPG also provides support for S/MIME and Secure Shell (ssh).

Pretty Good Privacy (PGP) is an encryption program that provides cryptographic privacy and authentication for data communication.


Preparation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[email protected]:~$ gpg --version
gpg (GnuPG) 1.4.18
Copyright (C) 2014 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

其中的Cipher可在參數--cipher-algo中指定,NASA的建議是使用
AES256,具體見鏈接

也可在文件~/.gnupg/gpg.conf中添加cipher-algo AES256,可直接執行如下命令

1
[[ `sed -r -n '/^cipher-algo/p' ~/.gnupg/gpg.conf` == '' ]] && sudo sed -i -r '$a\cipher-algo AES256' ~/.gnupg/gpg.conf || sudo sed -i -r '/^cipher-algo/ [email protected]*@cipher-algo [email protected]' ~/.gnupg/gpg.conf

關於--cipher-algo

--cipher-algo name
Use name as cipher algorithm. Running the program with the command –version yields a list of supported algorithms. If this is not used the cipher algorithm is selected from the preferences
stored with the key. In general, you do not want to use this option as it allows you to violate the OpenPGP standard. --per‐sonal-cipher-preferences is the safe way to accomplish the same
thing. – man gpg


Generate A New KeyPair

執行如下命令生成密鑰對(KeyPair)

1
gpg --gen-key

此處的配置信息如下

item value
keypair type 1
keypair size 4096
keypair exipre 1y
Real name sunday
Email [email protected]
Comment sunday test
passphrase ahappyday

具體操作過程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
[email protected]:~$ gpg --gen-key
gpg (GnuPG) 1.4.18; Copyright (C) 2014 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.
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
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) 1y
Key expires at Mon 18 Dec 2017 04:51:26 PM CST
Is this correct? (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) <[email protected]>"
Real name: sunday
Email address: [email protected]
Comment: sunday test
You selected this USER-ID:
"sunday (sunday test) <[email protected]>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.
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.
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 187 more bytes)
.............+++++
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 190 more bytes)
....+++++
gpg: key 26B15903 marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2017-12-18
pub 4096R/26B15903 2016-12-18 [expires: 2017-12-18]
Key fingerprint = 23A6 D526 005F 1A87 94B0 51A1 2411 FE8C 26B1 5903
uid sunday (sunday test) <[email protected]>
sub 4096R/868F064F 2016-12-18 [expires: 2017-12-18]

此處key_ID26B15903

Attentions

注意事項

Entropy Generation

該過程需要大量隨機數資源,如果系統無法提供足夠的隨機數資源,會導致執行過程耗時過長,且會對生成的 密鑰對 的安全性產生影響。可通過安裝rng-toolshaveged解決,具體參見本人Blog Use Haveged & rng-tools To Speed Up Entropy For Random Number Generation On GNU/Linux

The GNOME keyring manager hijacked the GnuPG agent

在某些GNOME版本中,執行gpg --gen-key時會出現如下報錯信息

gpg: WARNING: The GNOME keyring manager hijacked the GnuPG agent.
gpg: WARNING: GnuPG will not work properly - please configure that tool to not interfere with the GnuPG system!

提示GnuPG agentGNOME keyring manager劫持。

解決方案見GnuPG官方的 Problem

在Debian中,執行如下命令

1
2
#此為一行命令
sudo dpkg-divert --local --rename --divert /etc/xdg/autostart/gnome-keyring-gpg.desktop-disable --add /etc/xdg/autostart/gnome-keyring-gpg.desktop

若要復原,執行如下命令

1
sudo dpkg-divert --rename --remove /etc/xdg/autostart/gnome-keyring-gpg.desktop

List Keys On Local Host

執行如下命令查看系統中存在的公鑰

1
2
3
4
5
6
7
8
gpg --list-key [key_ID]
gpg --list-keys [key_ID]
#列出系統中存在的公鑰
gpg --list-public-keys
#列出系統中存在的私鑰
gpg --list-secret-keys

操作過程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[email protected]:~$ gpg --list-keys
/home/flying/.gnupg/pubring.gpg
-------------------------------
pub 4096R/26B15903 2016-12-18 [expires: 2017-12-18]
uid sunday (sunday test) <[email protected]>
sub 4096R/868F064F 2016-12-18 [expires: 2017-12-18]
[email protected]:~$ gpg --list-keys 26B15903
pub 4096R/26B15903 2016-12-18 [expires: 2017-12-18]
uid sunday (sunday test) <[email protected]>
sub 4096R/868F064F 2016-12-18 [expires: 2017-12-18]
pub 4096R/26B15903 2016-12-18 [expires: 2017-12-18]
uid sunday (sunday test) <[email protected]>
sub 4096R/868F064F 2016-12-18 [expires: 2017-12-18]


List FingerPrints

執行如下命令列出所有或指定key的指紋

1
2
3
4
5
# List all keys (or the specified ones) along with their fingerprints
gpg --fingerprint key_ID
#--with-colons Print key listings delimited by colons.
gpg --fingerprint --with-colon key_ID

操作過程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 列出所有key的指紋
[email protected]:~$ gpg --fingerprint
/home/flying/.gnupg/pubring.gpg
-------------------------------
pub 4096R/26B15903 2016-12-18 [expires: 2017-12-18]
Key fingerprint = 23A6 D526 005F 1A87 94B0 51A1 2411 FE8C 26B1 5903
uid sunday (sunday test) <[email protected]>
sub 4096R/868F064F 2016-12-18 [expires: 2017-12-18]
# 通過key_ID查詢指定key的指紋
[email protected]:~$ gpg --fingerprint 26B15903
pub 4096R/26B15903 2016-12-18 [expires: 2017-12-18]
Key fingerprint = 23A6 D526 005F 1A87 94B0 51A1 2411 FE8C 26B1 5903
uid sunday (sunday test) <[email protected]>
sub 4096R/868F064F 2016-12-18 [expires: 2017-12-18]
# 通過個人email查詢指定key的指紋
pub 4096R/26B15903 2016-12-18 [expires: 2017-12-18]
Key fingerprint = 23A6 D526 005F 1A87 94B0 51A1 2411 FE8C 26B1 5903
uid sunday (sunday test) <[email protected]>
sub 4096R/868F064F 2016-12-18 [expires: 2017-12-18]
[email protected]:~$ gpg --fingerprint --with-colon 26B15903
tru::1:1482051689:1513587169:3:1:5
pub:u:4096:1:2411FE8C26B15903:2016-12-18:2017-12-18::u:sunday (sunday test) <[email protected]>::scESC:
fpr:::::::::23A6D526005F1A8794B051A12411FE8C26B15903:
sub:u:4096:1:9750F92A868F064F:2016-12-18:2017-12-18:::::e:


Generate Revoke Key

執行如下命令生成revoke key,可用於吊銷存儲在遠程服務器上的公鑰

1
2
3
4
5
6
#Generate a revocation certificate for the complete key.
gpg --gen-revoke key_ID
#生成文件
gpg --gen-revoke --armor --output=RevocationCertificate.asc key_ID
gpg --output RevocationCertificate.asc --gen-revoke key_ID

操作過程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
[email protected]:~$ gpg --gen-revoke --armor --output=RevocationCertificate.asc 26B15903
sec 4096R/26B15903 2016-12-18 sunday (sunday test) <[email protected]>
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:
> nothing description
>
Reason for revocation: No reason specified
nothing description
Is this okay? (y/N) y
You need a passphrase to unlock the secret key for
user: "sunday (sunday test) <[email protected]>"
4096-bit RSA key, ID 26B15903, created 2016-12-18
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!
#查看生成的文件內容
[email protected]:~$ cat RevocationCertificate.asc
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
Comment: A revocation certificate should follow
iQIyBCABAgAcBQJYVlSnFR0Abm90aGluZyBkZXNjcmlwdGlvbgAKCRAkEf6MJrFZ
A8PCD/sHTCsV2qJr3/bulQjp7Uoyi9IrKjOSKfJs3gOkDT/OExb1/pMcNN+0k20H
q+aPdfHK2MehJxYxbvkOiUccedaIBMR1pwuWb89oru52nDaqGq2xSrnFg5KaoFjx
zM7s9eATkusRR86YL4r6lmtp4+jzO+t+Rxg/bHbmyzBG+xd66t+BqeX1YsbJvAzj
zlPE/PH9IO+JqQiy7Fpp/5KHDbgyKQJV6DjEo4Iyzr/uory8GG0xMVLtNPwAMqAY
L0v922/qq+RyeRkx/ZtWUzL6wsBrxjx+KZvVQ5/XWz/lFFSY2Pi+ARcVueoUR3dV
XplIviCWJDz5261QF2BLPIPlJaAMJfs8Zwrbf+q6l04wuqH5MB2+wNA4empCmuQm
HW8g+9x6yMNjEBI+NkGHQNRZ4sd6H671Aps7ZYwmrxhYBdzIkvk/W1P85cE46/k9
LwKRl9QdkVGmuaOatHCVcEPbKHf61D410ZtUDaO+E+baDtfP7Tnaognewhkpo/Qg
LpB6f4gkwDSOyflxTWwTngAxXe5C5KXiSSXjosEia0EiVEYNVgZL2hfgiGHiGQ8k
RtpGRp+ASqYk8PFRpmfuoBt26tkxf/1+D0KASs0a157EDRxKK5VHNcJjIrG0XQci
q1+9JqzBHPWALr1nI7bseu+Va+UMPe/dEaTdGj/NV6Fh7Ax+9Q==
=+N+n
-----END PGP PUBLIC KEY BLOCK-----


Communiction With Remote KeyServer

可選擇

1
keys.gnupg.net

此處以MIT的keyserver為例

1
pgp.mit.edu

執行如下命令

1
2
3
4
5
6
7
8
9
10
# Search the keyserver for the given names.
gpg --keyserver pgp.mit.edu --search-keys key_ID
# Send key to keyserver
gpg --keyserver pgp.mit.edu --send-keys key_ID
#fingerprint eg: 23A6 D526 005F 1A87 94B0 51A1 2411 FE8C 26B1 5903
gpg --keyserver pgp.mit.edu --send-keys fingerprint
# Receive key from keyserver
gpg --keyserver pgp.mit.edu --recv-keys key_ID


Exporting Public&Private Key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# export a public key
# 二進制格式存儲
gpg --output gpg-public.key --export key_ID
# http://dev.mysql.com/doc/refman/5.7/en/checking-rpm-signature.html
gpg -a --export key_ID > fileName.asc
# 添加指令-a / --armor,文本形式存儲
gpg -a --output gpg-public.key --export key_ID
#gpg --armor --output gpg-public.key --export key_ID
# export a private key
gpg --output gpg-private.key --export-secret-keys key_ID
#文本形式存儲
gpg --a --output gpg-private.key --export-secret-keys key_ID
#gpg --armor --output gpg-private.key --export-secret-keys key_ID

Importing A Public Key

1
2
3
4
5
# import from file (gpg-public.key)
gpg --import fileName
# Receive key from keyserver
gpg --keyserver pgp.mit.edu --recv-keys key_ID

Encryption & Decryption File

加密時可添加壓縮參數--compress-algo,具體使用,參見
NASA的文檔

執行如下命令進行加密

1
2
3
4
5
#加密
gpg --encrypt --recipient key_ID fileName
#gpg -e -r key_ID fileName
#gpg --encrypt --recipient realname fileName
#gpg -e -r key_ID --compress-algo zlib fileName

加密完成後會在文件所在目錄生成名為fileName.gpg的文件,此文件即為加密後的文件。

1
2
3
#解密
gpg --output newFileName --decrypt fileName.gpg
gpg --o newFileName --d fileName.gpg

如果生成keypair時設置了passphrase,在解密時會要求輸入該passphrase。操作完成後會在文件所在目錄生成指定名稱的文件,此處指定的名稱是newFileName,此即解密後的文件。

如果是要將文件加密後給其他人解密,或是解密其他人給自己的加密文件,首先需要有對應的公鑰,然後在--recipient中指定對應的key_ID或email或realname即可。


File Signature & Verify

1
2
3
4
#生成帶簽名的文件fileName.gpg(二進制形式)
gpg --sign fileName
#驗證文件簽名
gpg --verify fileName.gpg

也可以使用參數--clearsign生成文本形式的帶簽名文件

1
2
#生成帶簽名的文件fileName.asc(文本形式)
gpg --clearsign fileName

但無法直接驗證,會包如下錯誤

1
2
3
4
5
6
7
[email protected]:/tmp$ gpg --verify test.txt.asc
gpg: Signature made Sun 18 Dec 2016 06:47:45 PM CST using RSA key ID 26B15903
gpg: Good signature from "sunday (sunday test) <[email protected]>"
gpg: WARNING: not a detached signature; file 'test.txt' was NOT verified!
[email protected]:/tmp$ gpg --verify test.txt.asc test.txt
gpg: not a detached signature

可通過參數--detach-sign生成獨立的簽名文件fileName.sig

1
2
3
4
5
6
7
8
9
10
#二進制形式fileName.sig
gpg --detach-sign fileName
#驗證
gpg --verify fileName.sig fileName
#文本形式fileName.asc
gpg -a --detach-sign fileName
#驗證
gpg --verify fileName.asc fileName

操作過程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#二進制形式
[email protected]:~$ gpg --detach-sign /tmp/test.txt
You need a passphrase to unlock the secret key for
user: "sunday (sunday test) <[email protected]>"
4096-bit RSA key, ID 26B15903, created 2016-12-18
[email protected]:~$ gpg --verify /tmp/test.txt.sig /tmp/test.txt
gpg: Signature made Sun 18 Dec 2016 07:02:23 PM CST using RSA key ID 26B15903
gpg: Good signature from "sunday (sunday test) <[email protected]>"
[email protected]:~$ rm -f /tmp/test.txt.sig
#文本形式
[email protected]tacker:~$ gpg -a --detach-sign /tmp/test.txt
You need a passphrase to unlock the secret key for
user: "sunday (sunday test) <[email protected]>"
4096-bit RSA key, ID 26B15903, created 2016-12-18
[email protected]:~$ gpg --verify /tmp/test.txt.asc /tmp/test.txt
gpg: Signature made Sun 18 Dec 2016 07:03:04 PM CST using RSA key ID 26B15903
gpg: Good signature from "sunday (sunday test) <[email protected]>"


Deleting Key From Host

刪除key,注意,需先刪除私鑰,再刪除公鑰,否則會報錯

1
2
3
4
5
6
7
8
#刪除私鑰
gpg --delete-secret-keys key_ID
#刪除公鑰
gpg --delete-keys key_ID
#同時刪除公鑰、私鑰
gpg --delete-secret-and-public-keys key_ID

出現報錯的操作過程

1
2
3
4
5
6
7
8
[email protected]:~$ gpg --delete-keys 26B15903
gpg (GnuPG) 1.4.18; Copyright (C) 2014 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: there is a secret key for public key "26B15903"!
gpg: use option "--delete-secret-keys" to delete it first.


Revoke Public Key From Remote Server

如果要revoke遠程keyserver上的公鑰,執行如下操作

  1. 下載公鑰
  2. 導入revoke key
  3. 將導入revoke key的公鑰再次上傳

操作命令

1
2
3
4
5
6
7
8
9
#導入公鑰
gpg --import fileName
#gpg --keyserver pgp.mit.edu --recv-keys key_ID
#導入revoke key
gpg --import RevocationCertificate.asc
#再次提交到kerserver
gpg --keyserver pgp.mit.edu --send-keys key_ID

操作過程如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[email protected]:~$ gpg --import RevocationCertificate.asc
gpg: key 26B15903: no public key - can't apply revocation certificate
gpg: Total number processed: 1
[email protected]:~$ gpg --keyserver pgp.mit.edu --recv-keys 26B15903
gpg: requesting key 26B15903 from hkp server pgp.mit.edu
gpg: key 26B15903: public key "sunday (sunday test) <[email protected]>" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
[email protected]:~$ gpg --import RevocationCertificate.asc
gpg: key 26B15903: "sunday (sunday test) <[email protected]>" revocation certificate imported
gpg: Total number processed: 1
gpg: new key revocations: 1
gpg: no ultimately trusted keys found
[email protected]:~$ gpg --keyserver pgp.mit.edu --send-keys 26B15903
gpg: sending key 26B15903 to hkp server pgp.mit.edu
[email protected]:~$ gpg --keyserver pgp.mit.edu --search-keys 26B15903
gpg: searching for "26B15903" from hkp server pgp.mit.edu
(1) sunday (sunday test) <[email protected]>
4096 bit RSA key 26B15903, created: 2016-12-18, expires: 2017-12-18 (revoked)
Keys 1-1 of 1 for "26B15903". Enter number(s), N)ext, or Q)uit > 1
gpg: requesting key 26B15903 from hkp server pgp.mit.edu
gpg: key 26B15903: "sunday (sunday test) <[email protected]>" not changed
gpg: Total number processed: 1
gpg: unchanged: 1

References


Change Logs

  • 2016.12.18 19:54 Sun Asia/Shanghai
    • 初稿完成
  • 2017.01.11 15:51 Wed Asia/Shanghai
    • 添加隨機數資源生成方法、GNOME keyring manager劫持GnuPG agent的解決方案