概述:
gpg采用的是【非对称加密】方式,简单理解就是用公钥加密文件,用私钥解密文件。如果你需要发送加密信息,首先获取接收者的公钥,然后利用该公钥加密后传递,对方利用对应的私钥就可解密。也就是说,公钥是锁,私钥是钥匙。非对称加密方式很好地解决了传递信息的问题。
他人用公钥来加密,自己用私钥来解密
自己用私钥来签名,他人用公钥来验证
简写 | 含义 | |
---|---|---|
key pair | 密钥对(包含两部分) | |
primary key [master key] | 主密钥(包括主公钥,主私钥) | |
public key | pub | |
secret key | sec | 私钥 |
sub-key | sub | 子公钥 |
secret sub-key | ssb | 子私钥 |
key fingerprint | 密钥指纹 |
有些功能是私钥部分的,例如: 认证[C]、签名[S]、解密
删除私钥部分则无法完成操作
有些功能是公钥部分的,例如: 验证签名、加密[E]
删除私钥部分可以完成操作
标识 | 含义 | 作用 |
---|---|---|
S | sign | 签名功能 |
E | encrypt | 加密功能 |
A | authenticate | 身份验证功能,在其他协议中用于身份验证,例如SSH TLS。只能通过 --expert 选项制作具有该功能的子公钥。 |
C | certify | 认证,主密钥必备能力,且只有主密钥具有 |
加密过程中:
别人用你的公钥加密数据后发给你;
这些数据只有你的私钥能解密。
签名过程中:
你先用摘要算法(例如 SHA-256)给数据提取出一个指纹(摘要、哈希值);
你用私钥,把这串哈希值加密,得到一个数字签名,和文件一起发出去;
别人收到文件+签名后,先计算文件的哈希值;
别人用你的公钥,从数字签名中解密出你给的哈希值,和他计算的对比,如果两者一致,那么签名就是有效的。
注意这两个过程中,私钥的作用是相反的:
加密方案中的私钥:用于解密信息
签名方案中的私钥:用于加密信息
GPG 密钥的能力中, [C]、[S]、[A] 均属于签名方案,只有 [E] 是加密方案。
大家可能会奇怪:公私钥是可互换的吗?
是的!数学上来讲,它们是等价的,可以角色互换。
一个加密另一个就能解密。
但是!在具体的算法实现上,两者有很大不同。
我们要保证加密-解密的高效,同时保证抗破解的安全。
实际应用中的私钥与公钥生成,算法设计上是有偏向的。
这也是为什么 GPG 会为密钥分出不同用途,用户方便,算法设计者也方便。
$ gpg --full-generate-key 新版版用 $ gpg --gen-key
回车后,会出现如下文字:
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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?
第一段是版权声明,然后让用户自己选择加密算法。默认选择第一个选项,表示加密和签名都使用RSA算法。
然后,系统就会问你密钥的长度:
RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (3072)
密钥越长越安全,默认是3072位,接着设定密钥的有效期:
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)
回答完上面三个问题以后,系统让你确认:
Is this correct? (y/N)
输入y,系统就要求你提供个人信息:
GnuPG needs to construct a user ID to identify your key. Real name: Email address: Comment:
"真实姓名"填入你姓名的英文写法,"电子邮件地址"填入你的邮件地址,"注释"这一栏可以空着。
然后,你的"用户ID"生成了:
You selected this USER-ID: "psadmin <psadmin@psadmin.com>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?
输入O表示"确定"。
接着,系统会让你设定一个私钥的密码。这是为了防止误操作,或者系统被侵入时有人擅自动用私钥。
然后,系统就开始生成密钥了,这时会要求你做一些随机的举动,以生成一个随机数:
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. 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.
稍后秘钥就生成成功了:
gpg: key 30B117F460FCAF5F marked as ultimately trusted gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/5550D5D614E9CC36F1B731B930B117F460FCAF5F.rev' public and secret key created and signed. pub rsa2048 2022-01-07 [SC] 5550D5D614E9CC36F1B731B930B117F460FCAF5F uid psadmin <psadmin@psadmin.com> sub rsa2048 2022-01-07 [E]
请注意上面的字符串"5550D5D614E9CC36F1B731B930B117F460FCAF5F",这是"用户ID"的Hash字符串,可以用来替代"用户ID"。
这时,最好再生成一张"撤销证书",以备以后密钥作废时,可以请求外部的公钥服务器撤销你的公钥。
$ gpg --gen-revoke [用户ID]
$ gpg --expert --edit-key 9543E7CAC2C14FBA1ADACF575A0C80A216FD94B1 gpg (GnuPG) 2.2.4; Copyright (C) 2017 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. gpg: checking the trustdb gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: depth: 0 valid: 4 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 4u gpg: next trustdb check due at 2023-01-05 sec rsa2048/5A0C80A216FD94B1 created: 2022-01-10 expires: never usage: SC trust: ultimate validity: ultimate ssb rsa2048/5244E5713764B743 created: 2022-01-10 expires: never usage: E [ultimate] (1). zhaoyl <willingtolove@qq.com> 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) (7) DSA (set your own capabilities) (8) RSA (set your own capabilities) (10) ECC (sign only) (11) ECC (set your own capabilities) (12) ECC (encrypt only) (13) Existing key Your selection? 4 RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (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) Key does not expire at all Is this correct? (y/N) y Really create? (y/N) y 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. sec rsa2048/5A0C80A216FD94B1 created: 2022-01-10 expires: never usage: SC trust: ultimate validity: ultimate ssb rsa2048/5244E5713764B743 created: 2022-01-10 expires: never usage: E ssb rsa3072/EA76BD6BA5824067 created: 2022-01-10 expires: never usage: S [ultimate] (1). zhaoyl <willingtolove@qq.com> gpg> save
查看是否创建成功:
$ gpg -k /root/.gnupg/pubring.kbx ------------------------ pub rsa2048 2022-01-10 [SC] 9543E7CAC2C14FBA1ADACF575A0C80A216FD94B1 uid [ultimate] zhaoyl <willingtolove@qq.com> sub rsa2048 2022-01-10 [E] sub rsa3072 2022-01-10 [S] $ gpg -K /root/.gnupg/pubring.kbx ------------------------ sec rsa2048 2022-01-10 [SC] 9543E7CAC2C14FBA1ADACF575A0C80A216FD94B1 uid [ultimate] zhaoyl <willingtolove@qq.com> ssb rsa2048 2022-01-10 [E] ssb rsa3072 2022-01-10 [S]
gpg --expert --edit-key 9543E7CAC2C14FBA1ADACF575A0C80A216FD94B1 gpg (GnuPG) 2.2.4; Copyright (C) 2017 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 rsa2048/5A0C80A216FD94B1 created: 2022-01-10 expires: never usage: SC trust: ultimate validity: ultimate ssb rsa2048/5244E5713764B743 created: 2022-01-10 expires: never usage: E ssb rsa3072/EA76BD6BA5824067 created: 2022-01-10 expires: never usage: S [ultimate] (1). zhaoyl <willingtolove@qq.com> 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) (7) DSA (set your own capabilities) (8) RSA (set your own capabilities) (10) ECC (sign only) (11) ECC (set your own capabilities) (12) ECC (encrypt only) (13) Existing key Your selection? 8 Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Sign Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? s Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Encrypt (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? e Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? a Possible actions for a RSA key: Sign Encrypt Authenticate Current allowed actions: Authenticate (S) Toggle the sign capability (E) Toggle the encrypt capability (A) Toggle the authenticate capability (Q) Finished Your selection? q RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (3072) 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) 0 Key does not expire at all Is this correct? (y/N) y Really create? (y/N) y 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. sec rsa2048/5A0C80A216FD94B1 created: 2022-01-10 expires: never usage: SC trust: ultimate validity: ultimate ssb rsa2048/5244E5713764B743 created: 2022-01-10 expires: never usage: E ssb rsa3072/EA76BD6BA5824067 created: 2022-01-10 expires: never usage: S ssb rsa2048/99A0AD13CDF31B72 created: 2022-01-10 expires: never usage: A [ultimate] (1). zhaoyl <willingtolove@qq.com> gpg> save
查看是否创建成功:
$ gpg -k 5A0C80A216FD94B1 pub rsa2048 2022-01-10 [SC] 9543E7CAC2C14FBA1ADACF575A0C80A216FD94B1 uid [ultimate] zhaoyl <willingtolove@qq.com> sub rsa2048 2022-01-10 [E] sub rsa3072 2022-01-10 [S] sub rsa2048 2022-01-10 [A] $ gpg -K 5A0C80A216FD94B1 sec rsa2048 2022-01-10 [SC] 9543E7CAC2C14FBA1ADACF575A0C80A216FD94B1 uid [ultimate] zhaoyl <willingtolove@qq.com> ssb rsa2048 2022-01-10 [E] ssb rsa3072 2022-01-10 [S] ssb rsa2048 2022-01-10 [A]
$ gpg --list-keys --list-keys:显示所有公钥 --list-secret-key:显示所有私钥
/root/.gnupg/pubring.kbx ------------------------ pub rsa2048 2017-05-21 [SC] E52218E7087897DC6DEA6D6D97DB7443D5EDEB74 uid [ unknown] OpenResty Admin <admin@openresty.com> sub rsa2048 2017-05-21 [E] pub rsa2048 2022-01-07 [SC] 5550D5D614E9CC36F1B731B930B117F460FCAF5F uid [ultimate] psadmin <psadmin@psadmin.com> sub rsa2048 2022-01-07 [E]
第一行显示公钥文件名(pubring.kbx),第二行显示公钥特征(2048位,Hash字符串和生成时间),第三行显示"用户ID",第四行显示私钥特征。
# 先删除私钥部分才能删除公钥部分 $ gpg --delete-secret-keys [用户ID] # 删除私钥 $ gpg --delete-keys [用户ID] # 删除公钥
gpg --expert --edit-key D2673C470EDD2A1EE169781C86A5F36CA4FAD524 gpg (GnuPG) 2.2.4; Copyright (C) 2017 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/86A5F36CA4FAD524 created: 2022-01-10 expires: never usage: SC trust: ultimate validity: ultimate ssb rsa3072/87E977522ACB63C9 created: 2022-01-10 expires: never usage: E ssb rsa2048/6DC53EC22366279E created: 2022-01-10 expires: never usage: S [ultimate] (1). zhaoyl <zhaoyl@qq.com> gpg> key 6DC53EC22366279E sec rsa3072/86A5F36CA4FAD524 created: 2022-01-10 expires: never usage: SC trust: ultimate validity: ultimate ssb rsa3072/87E977522ACB63C9 created: 2022-01-10 expires: never usage: E ssb* rsa2048/6DC53EC22366279E created: 2022-01-10 expires: never usage: S [ultimate] (1). zhaoyl <zhaoyl@qq.com> gpg> delkey 6DC53EC22366279E Do you really want to delete this key? (y/N) y sec rsa3072/86A5F36CA4FAD524 created: 2022-01-10 expires: never usage: SC trust: ultimate validity: ultimate ssb rsa3072/87E977522ACB63C9 created: 2022-01-10 expires: never usage: E [ultimate] (1). zhaoyl <zhaoyl@qq.com> gpg> save
公钥文件(.gnupg/pubring.kbx)以二进制形式储存,armor
参数可以将其转换为ASCII码显示;
$ gpg --armor --output private-key.txt --export-secret-keys [用户ID]
"用户ID"指定哪个用户的公钥,output
参数指定输出文件名(public-key.txt)。
类似地,export-secret-keys
参数可以转换私钥。
$ gpg --armor --output private-key.txt --export-secret-keys [用户ID]
导出公钥到终端:
gpg --export --export-options export-minimal --armor 5550D5D614E9CC36F1B731B930B117F460FCAF5F
公钥服务器是网络上专门储存用户公钥的服务器。
网页上传
可访问下列网址上传公钥:
keys.openpgp.org
keyserver.ubuntu.com
网页上传后,ubuntu和opengpg会进行邮箱验证,可能会被认为是垃圾邮件;
在搜索栏输入0xUID
即可查询公钥信息和下载;
比如输入 0xE52218E7087897DC6DEA6D6D97DB7443D5EDEB74
命令上传
$ gpg --send-keys [用户ID] --keyserver keyring.debian.org
使用上面的命令,你的公钥就被传到了服务器keyring.debian.org,然后通过交换机制,所有的公钥服务器最终都会包含你的公钥。
由于公钥服务器没有检查机制,任何人都可以用你的名义上传公钥,所以没有办法保证服务器上的公钥的可靠性,通过公钥指纹校验。
你可以在网站上公布一个公钥指纹,让其他人核对下载到的公钥是否为真。fingerprint
参数生成公钥指纹。
$ gpg --fingerprint [用户ID]
除了生成自己的密钥,还需要将他人的公钥或者你的私钥密钥输入系统。这时可以使用import
参数。
导入公钥和私钥;
$ gpg --import [密钥文件公钥/私钥]
为了获得他人的公钥,可以让对方直接发给你,或者到公钥服务器上寻找。
$ gpg --keyserver keys.openpgp.org --search-keys [用户ID]
从服务器导入公钥:
$ gpg --keyserver keys.openpgp.org --recv-keys 5550D5D614E9CC36F1B731B930B117F460FCAF5F
正如前面提到的,我们无法保证服务器上的公钥是否可靠,下载后还需要用其他机制验证.
假定有一个文本文件test.txt,怎样对它加密呢?encrypt
参数用于加密,recipient
指定ID来加密
$ gpg --recipient [用户ID] --output test.en.txt --encrypt test.txt$ gpg --recipient 5550D5D614E9CC36F1B731B930B117F460FCAF5F --output test.en.txt --encrypt test.txt
recipient
参数指定接收者的公钥,output
参数指定加密后的文件名,encrypt
参数指定源文件。运行上面的命令后,test.en.txt就是已加密的文件,可以把它发给对方。
对方收到加密文件以后,就用自己的私钥解密。
$ gpg --output test.de.txt --decrypt test.en.txt
decrypt参数指定需要解密的文件,output参数指定解密后生成的文件。运行上面的命令,test.de.txt就是解密后的文件。
有时候,我们不需要对文件进行加密,只需要对文件进行签名,表示这个文件确实是我本人发出的。使用sign
参数来签名。
如果想生成单独的签名文件,与原文件内容分开存放,可以使用detach-sign
参数。
如果想让生成的签名文件内容采用ASCII
码的形式,要加上armor
参数。
gpg --local-user 5550D5D614E9CC36F1B731B930B117F460FCAF5F --armor --detach-sign test.txt
–local-user
指定本地ID进行签名。默认情况下选择最新未被吊销的具有[S]功能的密钥。
如果想同时签名和加密,可以使用下面的命令,产生test.txt.asc文件,这个文件包含被加密文件和签名信息。
$ gpg --local-user [发信者ID] --recipient [接收者ID] --armor --sign --encrypt log.txt $ gpg --local-user 5550D5D614E9CC36F1B731B930B117F460FCAF5F --recipient C38E35B04D86C16BF51A0E5D00C672A21827A648 --armor --sign --output test.en.txt --encrypt test.txt
local-user
参数指定用发信者的私钥签名,recipient
参数指定用接收者的公钥加密,armor
参数表示采用ASCII码形式显示,sign
参数表示需要签名,--output
指定加密后文件的输出路径, encrypt
参数表示指定源文件。
我们收到别人签名后的文件,需要用对方的公钥验证签名是否为真。使用verify
参数来验证。
签名asc
文件和文件本身分离,验证命令如下:
$ gpg --verify test.txt.asc test.txt
举例:使用openresty做个测试。
$ wget https://openresty.org/download/openresty-1.21.4.1rc1.tar.gz $ wget https://openresty.org/download/openresty-1.21.4.1rc1.tar.gz.asc $ gpg --verify openresty-1.21.4.1rc1.tar.gz.asc openresty-1.21.4.1rc1.tar.gz gpg: Signature made Wed 22 Dec 2021 09:49:37 AM CST gpg: using RSA key E52218E7087897DC6DEA6D6D97DB7443D5EDEB74 gpg: Can't check signature: No public key $ gpg --keyserver keyserver.ubuntu.com --recv-keys E52218E7087897DC6DEA6D6D97DB7443D5EDEB74 gpg: /root/.gnupg/trustdb.gpg: trustdb created gpg: key 97DB7443D5EDEB74: public key "OpenResty Admin <admin@openresty.com>" imported gpg: Total number processed: 1 gpg: imported: 1 $ gpg --verify openresty-1.21.4.1rc1.tar.gz.asc openresty-1.21.4.1rc1.tar.gz gpg: Signature made Wed 22 Dec 2021 09:49:37 AM CST gpg: using RSA key E52218E7087897DC6DEA6D6D97DB7443D5EDEB74 gpg: Good signature from "OpenResty Admin <admin@openresty.com>" [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: E522 18E7 0878 97DC 6DEA 6D6D 97DB 7443 D5ED EB74