GunPG是一个开源免费的加密解密的GPG软件,使用命令行,在Windows、Linux、macOS、Android等平台上都有。
如果Mac平台需要可视化的操作方式,那么可以使用GPGTools,是一款收费的商业软件,官网地址是:https://gpgtools.org
继续介绍GunPG,这里先列一下GunPG官网:https://www.gnupg.org,包含各种版本的GunPG以及使用手册。
下载GunPG
使用之前当然是获得GunPG,将其安装在自己的电脑上,方法有两种:官网下载以及命令行下载。
官网下载方法如下:
点击https://www.gnupg.org/download/index.html,进入官网下载界面。有源码、二进制文件以及安装包下载。
一般用户找到下图GnuPG binary releases部分:
Mac用户选择第二个“GunPG for OS X”下载安装即可。其他用户自行按照描述下载所需的版本即可。
Shell命令行下载方法如下:
Mac:brew install gpg
Linux:sudo apt install gnupg
初见GunPG
安装好之可以使用gpg --version
来查看当前版本、简介、安装位置以及支持的加密算法等信息,如下:
gpg (GnuPG) 2.2.27
libgcrypt 1.8.7
Copyright (C) 2021 Free Software Foundation, Inc.
License GNU GPL-3.0-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: /Users/username/.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
如果我们想知道更多但是简洁的信息,就可以使用gpg --help
命令。显示如下:
gpg (GnuPG) 2.2.27
libgcrypt 1.8.7
Copyright (C) 2021 Free Software Foundation, Inc.
License GNU GPL-3.0-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: /Users/username/.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
Syntax: gpg [options] [files]
Sign, check, encrypt or decrypt
Default operation depends on the input data
Commands:
-s, --sign make a signature
--clear-sign make a clear text signature
-b, --detach-sign make a detached signature
-e, --encrypt encrypt data
-c, --symmetric encryption only with symmetric cipher
-d, --decrypt decrypt data (default)
--verify verify a signature
-k, --list-keys list keys
--list-signatures list keys and signatures
--check-signatures list and check key signatures
--fingerprint list keys and fingerprints
-K, --list-secret-keys list secret keys
--generate-key generate a new key pair
--quick-generate-key quickly generate a new key pair
--quick-add-uid quickly add a new user-id
--quick-revoke-uid quickly revoke a user-id
--quick-set-expire quickly set a new expiration date
--full-generate-key full featured key pair generation
--generate-revocation generate a revocation certificate
--delete-keys remove keys from the public keyring
--delete-secret-keys remove keys from the secret keyring
--quick-sign-key quickly sign a key
--quick-lsign-key quickly sign a key locally
--quick-revoke-sig quickly revoke a key signature
--sign-key sign a key
--lsign-key sign a key locally
--edit-key sign or edit a key
--change-passphrase change a passphrase
--export export keys
--send-keys export keys to a keyserver
--receive-keys import keys from a keyserver
--search-keys search for keys on a keyserver
--refresh-keys update all keys from a keyserver
--import import/merge keys
--card-status print the card status
--edit-card change data on a card
--change-pin change a card's PIN
--update-trustdb update the trust database
--print-md print message digests
--server run in server mode
--tofu-policy VALUE set the TOFU policy for a key
Options:
-a, --armor create ascii armored output
-r, --recipient USER-ID encrypt for USER-ID
-u, --local-user USER-ID use USER-ID to sign or decrypt
-z N set compress level to N (0 disables)
--textmode use canonical text mode
-o, --output FILE write output to FILE
-v, --verbose verbose
-n, --dry-run do not make any changes
-i, --interactive prompt before overwriting
--openpgp use strict OpenPGP behavior
(See the man page for a complete listing of all commands and options)
Examples:
-se -r Bob [file] sign and encrypt for user Bob
--clear-sign [file] make a clear text signature
--detach-sign [file] make a detached signature
--list-keys [names] show keys
--fingerprint [names] show fingerprints
Please report bugs to <https://bugs.gnupg.org>.
可以看到上半部分和version显示的一样,后面跟了一些常用的命令、选项的介绍以及例子。
如果想查询gpg相关的完整信息,使用man gpg
查询。GunPG官网也提供了在线的man page:https://www.gnupg.org/documentation/manpage.html,不过与Shell中的man page略有不同。
生成密钥
生成密钥分完整模式和简洁模式。
完整模式的选项是--full-generate-key
简洁模式的选项是--generate-key
或者简写--gen-key
。
我们先来看完整模式:
输入:gpg --full-generate-key
,可以看到返回了(这里以Mac为例):
gpg (GnuPG) 2.2.27; Copyright (C) 2021 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)
(14) Existing key from card
Your selection?
前三段在是版本号等相关信息。
然后这里显示使用哪种密钥类型,一般选择默认,也就是输入1
就可以了。按回车返回如下:
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)
这里显示RSA密钥可以在1024到4096位长度之间。我们想要多长的,一般使用2048或者后面括号里提示的就可以,安全性最高的就是4096了。这里我们输入括号里的3072,按回车返回:
Requested keysize is 3072 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)
第一行显示我们选择3072位长度。
然后让我们设置密钥的有效期,0
表示永不过期,n
表示几天,<n>w
表示几周之后过期,例如2w
就是2周之后过期,<n>m
表示几个月之后过期,<n>y
表示几年之后过期。
这里我们设置1年,输入1y
,可以看到返回了:
Key expires at 四 4/14 21:28:27 2022 CST
Is this correct? (y/N)
第一行显示了密钥过期日期“太平洋时间星期四 2022年4月14日21:28:27”,然后问我们确定吗,我们输入y
确定。可以看到返回:
GnuPG needs to construct a user ID to identify your key.
Real name:
GunPG需要创建用户ID来定义密钥,这里需要我们输入真实姓名,输入完按回车出现:
Email address:
这里需要输入自己的邮箱地址。输入完按回车:
Comment:
这里是让我们备注该密钥,因为可能我们有很多密钥,为了不搞混,我们最好备注一下。我们输入First,假设是第一个。输入完按回车:
You selected this USER-ID:
"Real_Name (First) <Real_Name@xx.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
这里第一段显示我们刚才输入的Real name
、Comment
和Email address
组成的USER-ID
,并且询问我们是否要更改其中哪个部分、确定无误或者退出生成密钥。这里输入o
表示确认无误,继续。
这时候因为我们使用的是Mac,会跳出一个名为“Pinentry Mac”的软件,显示“Please enter the passphrase to protect your new key”,让我们设置一个密码,来保护这个密钥,设置完点击“OK”,可以看到Shell在滚动,并显示一堆信息,我们只需要看最后四行:
pub rsa3072 2021-04-14 [SC] [expires: 2022-04-14]
7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951
uid Real_Name (First) <Real_Name@xx.com>
sub rsa3072 2021-04-14 [E] [expires: 2022-04-14]
生成密钥的时候其实是生成了两对密钥——“primary key”(又被称为“master key(主人密钥)”)和“subkey”。
可以看到,第一行pub
表示主要公钥(public primary key),往右依次是:密钥类型RSA,密钥长度(有的地方叫密钥大小)为3072位,创建日期,过期类型。
第二行是密钥的指纹,是一组哈希值。可以替代User ID
(用户ID),也就是下一行uid
。
第三行就是用户ID了。
第四行sub
表示的是子公钥(public subkey),右边内容和pub几乎一样。
这里其实还生成了私钥,我们下一节和pub和sub的区别一起说。
简洁模式只是比完整模式少了设置密钥类型、密钥长度和过期日期的步骤,这里不再做赘述。
查看钥匙圈(密钥列表)
生成密钥的时候不仅生成公钥,还生成了私钥,但是我们现在只看到了公钥。要查看私钥,输入gpg --list-secret-key
,可以看到返回了:
/Users/username/.gnupg/pubring.kbx
--------------------------------------
sec rsa3072 2021-04-14 [SC] [expires: 2022-04-14]
7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951
uid [ultimate] Real_Name (First) <Real_Name@xx.com>
ssb rsa3072 2021-04-14 [E] [expires: 2022-04-14]
第一行是密钥存储的位置目录。
这里的结构和公钥差不多,这里只说一下sec,ssd的含义和区别,还有和公钥的联系。
sec
表示主要私钥(secret primary key),与pub
是一对密钥,ssb
表示子私钥(secret subkey),与sub
是一对密钥。
“primary key(主要密钥)”(又被称为“master key(主人密钥)”)和“subkey(子密钥)”区别在于:
主要密钥包含了一个或者更多的用户ID(名字和邮箱),而子密钥是主要密钥中一个用户ID注册的密钥。
想要查看存储的所有公钥,输入gpg --list-key
,可以看到返回了:
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
gpg: next trustdb check due at 2022-04-14
/Users/username/.gnupg/pubring.kbx
--------------------------------------
pub rsa3072 2021-04-14 [SC] [expires: 2022-04-14]
7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951
uid [ultimate] Real_Name (First) <Real_Name@xx.com>
sub rsa3072 2021-04-14 [E] [expires: 2022-04-14]
可以看到公钥存储目录为:/Users/username/.gnupg/pubring.kbx
,下面就是我们之前生成的备注为First的密钥。
删除密钥
删除密钥有三个选项:--delete-keys
、--delete-secret-keys
和--delete-secret-and-public-key
。
--delete-keys
表示从公钥钥匙圈上删除密钥,也就是一同删除公钥和对应的私钥。在分批模式(batch mode)下,密钥必须使用指纹表示,或者使用--yes
选项。
--delete-secret-keys
表示从私钥钥匙圈上删除密钥。
--delete-secret-and-public-key
和--delete-keys
一样,但是如果私钥存在的话,会先移除私钥。在分批模式下,密钥必须使用指纹表示。
输出密钥
当我们需要和别人使用一套密钥的时候,我们就需要分享密钥,那么就要将OpenPGP二进制格式存储的公钥输出成ASCII码(也就是字母符号)。
输出公钥的话如下:
gpg --armor --output First_public_key.txt --export 7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951
--armor
选项是将OpenPGP二进制格式存储的文件按ASCII格式输出。--output First_public_key.txt
表示将内容输出为名称为First_public_key.txt的文件。--export 7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951
输出密钥指纹对应密钥的公钥(这里如果知道用户ID也可以写用户ID)。
这里需要注意,不能把--output [密钥指纹/用户ID]
写在最后,不然会输出文件失败,并把转换成的ASCII码打印在终端。
输出私钥的话如下:
gpg --armor --output First_secret_key.txt --export-secret-keys 7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951
不过如果使用的是Mac的话,就需要我们使用之前设置的“Pinentry Mac”的“passphrase”。
输入密钥
我们有时候需要使用别人分享的密钥来加密,这时候我们就需要将别人分享的密钥添加到自己的钥匙圈上。方法如下:
使用nano或者vi等文本编辑软件新建一个后缀为.gpg
的文件,将别人分享的ASCII码明文密钥复制粘贴进去,保存,这里保存完的文件名为other_key.gpg
。然后使用以下命令导入:
gpg --import other_key.gpg
然后我们使用:gpg --list-key
就可以看到我们刚才添加进去的密钥了。
加密(encrypt)和解密(decrypt)
在了解了密钥的一些知识之后,我们要进行我们本来想做的事情——加密和解密文件。
假设我们有一个文件名为before.txt
的文件,这里我们使用以下方式加密文件:
gpg --recipient 7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951 --output after.txt --encrypt before.txt
这里需要注意,格式应该为gpg [options] --encrypt [filename]
,选项--encrypt [filename]
应该放在最后。--recipient
选项后面跟密钥指纹,表示要用什么密钥加密解密文件。--encrypt
表示加密,后面跟需要加密的文件。
解密的话使用以下命令:
gpg after.txt
然后显示:
gpg: WARNING: no command supplied. Trying to guess what you mean ...
gpg: encrypted with 3072-bit RSA key, ID 9F9C425E3B989D0A, created 2021-04-14
"Real_Name (First) <Real_Name@xx.com>"
gpg: after.txt: unknown suffix
Enter new filename [before.txt]: 1.txt
然后提示输入之前“Pinentry Mac”的“passphrase”,接着输入解密之后的文件名,就可以在“1.txt
”文件中看到之前文本文件里的内容。
签名(sign)
有时候我们只需要说明这事我们发送的文件,这就需要对文件签名,表示文件的发送者。
可以使用以下命令签名:
gpg --sign before.txt
然后会生成一个名为before.txt.gpg
文件,也是一个OpenPGP二进制格式文件,不可读,还原成可读文件也不是很方便,不推荐使用。
推荐使用以下方法:
gpg --clearsign before.txt
这样会生成一个before.txt.asc
的文件,使用less命令查看可见:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
nihao
woshini
wohenhao
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCAAdFiEEfai88rt7vWATpNwKHJ2rj07oqVEFAmB3EE8ACgkQHJ2rj07o
qVE+zAv9HBSHZGy1GI3hjqw8om1iea4d63b5TsoAtcSMU4j7e6InYfUEfrOWnC6z
iCcVR2Gad6be4BhR59e7YadGHJdq3LTjOLCV1o+v4RDeot7CCwWnNSKW8Lk+PHMh
nFLuJSv95BHonAxHmL2n0pw7MjXOUgP/qzWjZ5UK1xWcr1rhHS0IDyP3T4f9dyYw
WWdwbixj1MQrfFet4EeQ5uq123123123WjHqjQ95zk9ot+vM1eciy6Yq1PmkkN9e
/w4vW2KgslVdePcXlzE2w1321kCbCFqJhvygNu4XQslOa+Uqf0y/+irD1L2CF5hG4hLK
9aZnwwYIJqIgwu4Y2yo7qxd6B384Vx9h13113N2Uu3LjfXYnWVKhNHxLt0Kmy43Z
fU94zSDHbvnBF+9aYwrB40UwHkxDJ0xof8bxMK6yQHY8BCwu7mbh5kzXUVjfNwee
l4TIVnD6A4WzknPsOlOW+BI+r87GvrmtdcrksvjlK8c55xoegDad4xGqlogegAkI
/mKiX2MD
=r4EJ
-----END PGP SIGNATURE-----
第一部分就是原本的文本,第二部分则是可读的ASCII码签名了。
但是我们要签名的不是文本文件,而是视频图片或者其他非ASCII码文件,这样也还是不可读,那么我们就需要生成单独的签名,将签名分开放置。我们就可以使用以下命令:
gpg --detach-sign test1.MP4
这样会生成一个名为test1.MP4.sig
的签名文件。
如果我们又想加密又想签名,就使用以下命令:
gpg --local-user [签名用的密钥指纹/用户ID] --recipient [加密用的密钥指纹/用户ID] --armor --sign --encrypt [需要加密的文件]
这里我们举个例子:
gpg --local-user 7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951 --recipient 7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951 --armor --sign --encrypt test2.MP4
这时候会生成一个文件名为test2.MP4.asc
。
验证签名
签名有了,怎么验证呢?对不同类型的签名有不同的验证方式,比如说上一节单独生成的test1.MP4.sig
签名文件,我们就可以使用以下命令:
gpg --verify test.MP4.sig
然后我们可以看到终端打印出:
gpg: Signature made 四 4/15 00:21:49 2021 CST
gpg: using RSA key 7DA8BCF2BB7BBD6013A4DC0A1C9DAB8F4EE8A951
gpg: Good signature from "Real_Name (First) <Real_Name@xx.com>" [ultimate]
这样就可以对照验证签名,看出来谁是真正的发送者。
例如上一节我们使用加密并且签名生成的test2.MP4.asc
文件,就需要解密再验证签名,可以直接使用gpg test2.MP4.asc
解密,然后就可以看到解密之后会打印出上文同样的内容,因为虽然这个命令不正确,但是gpg会显示以下内容并且猜测你的意思,挺智能的。
gpg: WARNING: no command supplied. Trying to guess what you mean ...
基础的就这些,更多功能就翻阅man page吧。