GnuPG

-
-
2024-08-14

What?

概述

GnuPG 是完整实现了 RFC4880(即PGP)所定义的 OpenPGP 标准的自由软件。GnuPG 可以加密和签名你的数据和通讯信息,包含一个通用的密钥管理系统以及用于各种公钥目录的访问模块。GnuPG,简称 GPG,是一个易于与其它程序整合的命令行工具,拥有很多前端程序和函数库。GnuPG 还支持 S/MIME 和 Secure Shell (ssh)。

基本原理

非对称加密(Asymmetric Encryption),简言之就是用公钥加密、用私钥解密,这两个字符串通过算法可以互相推导,但推导的难度不同。私钥推导公钥非常简单、公钥推导私钥非常困难。理论上来说密钥长度越长,推导难度越大。也就是说你用的密钥足够长,就没有人能从公钥推导出私钥,你就是那个公钥的唯一主人。

PGP就是利用非对称加密原理,来加密、认证的。

为了安全的使用 PGP,一般采取 C + A + E + S 的方式使用

  • S, Sign, 表示可以用来签名
  • C, Certify, 表示可以用来验证签名
  • E, Encrypt, 表示可以用来加密
  • A, Authentication, 表示可以用来认证

用不同的密钥对做不同的功能,再用主密钥给他们签名,形成一个信任链。这样就实现了一个主密钥、多个子密钥的功能。

多了这层签名验证,我们就可以灵活的管理子密钥,包括签名、吊销、有效期等。

安装

GPG有两种安装方式。可以下载源码,自己编译安装。

# 解压源码包
# 进入工作目录 
./configure
make
make install

也可以安装编译好的二进制包。

# Debian / Ubuntu 环境
sudo apt-get install gnupg
# Fedora / Centos 环境
yum install gnupg
#  Arch / Manjaro 环境
sudo pacman -Syu

安装完成后,键入下面的命令:

gpg --help

如果屏幕显示GPG的帮助,就表示安装成功。

配置

这里截取自ArchlinuxWIKI指在Archlinux下的配置,其他系统可能不同

主目录

GnuPG 套件将密钥环和私钥存储在 GnuPG 主目录,并从中读取配置。默认路径为 ~/.gnupg。有两种方法可以改变主目录的路径:

  • 设置 $GNUPGHOME 环境变量
  • 使用 --homedir 参数,如 $ gpg --homedir /path/to/dir [1]

默认情况下,主目录的权限设置为 700,其包含的文件的权限设置为 600。只有目录的所有者有权读取、写入和访问文件。这是出于安全目的,不应更改。如果此目录或其中的任何文件不遵循此安全措施,您将收到有关不安全文件和主目录权限的警告。

配置文件

GnuPG 的所有行为都可以通过命令行参数进行配置。对于您希望成为默认参数的参数,可以将它们添加到相应的配置文件中:

  • gpg 检查 gnupg_home/gpg.conf(用户)和 /etc/gnupg/gpg.conf(全局)。由于 gpg 是 GnuPG 的主要入口点,因此大部分感兴趣的配置都在这里。请参阅 GPG 选项获取可能的选项。
  • dirmngr会检查gnupg_home/dirmngr.conf/etc/gnupg/dirmngr.conf两个配置文件。dirmngr是由 gpg 内部调用的程序,用于访问 PGP 密钥服务器。请参阅Dirmngr 选项以了解可能的选项。

这两个配置文件涵盖了常见用例,但GnuPG套件中还有更多带有自己选项的辅助程序。请参阅GnuPG 手册获取详细列表。

创建所需的文件,并按照#主目录中讨论的方法设置其权限为600

在这些文件中添加任何你想要的长选项。不要写两个破折号,只需写选项的名称和所需的参数。例如,要始终使GnuPG在特定路径上使用密钥环,就像使用gpg --no-default-keyring --keyring keyring-path ...调用它一样:

gnupg_home/gpg.conf (或 /etc/gnupg/gpg.conf)
--------------------------------------------
no-default-keyring
keyring keyring-path

另外,pacman 在包签名验证方面使用了一组不同的配置文件。有关详细信息,请参阅Pacman/Package signing

新用户的默认选项

要给新建用户设定一些默认选项,把配置文件放到 /etc/skel/.gnupg/。系统创建新用户时,就会把文件复制到 GnuPG 目录。还有一个 addgnupghome 命令可以为已有用户创建新 GnuPG 主目录:

# addgnupghome user1 user2

此命令会检查 /home/user1/.gnupg//home/user2/.gnupg/,并从 skeleton 目录复制文件过去。具有已存在的 GnuPG 主目录的用户只需跳过即可。

使用

注意:

  • 如果需要一个 user-id,可以使用 key ID、指纹、用户名或电邮地址的部分等替代,GnuPG 对此的处理很灵活。
  • 如果需要一个 key-id,可以给命令加上 --keyid-format=long 选项来查询。例如,如果想要查看主密匙,可以使用gpg --list-secret-keys --keyid-format=long user-id命令,key-id 是和 sec 同一行的十六进制散列值。

 

创建密钥对

用下面命令创建一个密钥对:

$ gpg --full-gen-key

使用 --expert 选项可以选择其它的加密算法,尤其是较新的ECC(椭圆曲线加密)

命令执行后会需要用户回答一些问题,大部分用户应该需要的是:

  • 用于签名和加密密钥的默认ECC(签名和加密) 。
  • 默认Curve25519使用Curve25519Ed25519
  • 安全密码,可在安全#选择安全密码中找到一些指南。
  • 默认的密钥长度,即 3072。增大长度到 4096“成本极高,但获益很少”。这个帖子说明了为何 GPG 不默认使用 RSA-4096
  • 过期日期。大部分用户可以选择一年。这样即使无法访问密钥环,用户也知道密钥已经过期。如果有需要,可以不重新签发密钥就延长过期时间。
  • 用户名和电子邮件。可以给同样的密钥不同的身份,比如给同一个密钥关联多个电子邮件。
  • 不填写可选注释。注释字段并没有被很好地定义,作用有限。
  • 一个安全的密钥口令。可参考如何选择安全的密码

注意: 任何导入密钥的人都可以看到这里的用户名和电子邮件地址。

提示:较简单的 --gen-key 选项对密钥类型、密钥长度、过期时间均使用默认值,仅询问姓名和电邮地址。

查看密钥

查看公钥:

$ gpg --list-keys

查看私钥:

$ gpg --list-secret-keys
# 更简洁的命令:
gpg -k # 列出公钥
gpg -K # 列出私钥
gpg --expert -k --with-keygrip --keyid-format=long 
  • --expert 专家模式,显示更多信息
  • --with-keygrip  显示密钥标识(短,8位16进制数)一般说的密钥ID
  • --keyid-format=long 显示长格式的密钥标志(16位16进制数
pub   ed25519 2024-08-11 [SC]
      B26594963B985E799C7F076C73B071BF5F2F287F
uid             [ 绝对 ] Tsaitang (采唐签名认证✅) <[email protected]>
sub   cv25519 2024-08-11 [E]
sub   ed25519 2024-08-11 [S]
  • sec, SECret key, 表明是私钥
  • uid, 拥有者的信息, 姓名和邮箱
  • ssb, Secret SuBkey, 子私钥
  • pub, PUBlic key, 表明是公钥
  • sub, public SUBkey, 子公钥

导出公钥

GPG 的主要用途是通过公钥加密信息以确保其私密性。你可以分发自己的公钥,而其他人通过该公钥加密发给你的信息。而你的私钥必须始终保密,否则将会威胁信息的私密性。相关内容,请参见公开密钥加密

所以其他人需要有你的公钥才能给你发加密信息。

以下命令可生成公钥的 ASCII 版本(--armor 参数)(例如用于以电子邮件发布):

$ gpg --export --armor --output public-key.asc user-id

此外,还可以通过密钥服务器分发公钥。

提示:

  • 使用 --no-emit-version 可以避免打印版本号,通过配置文件也可以进行此设置。

  • 可以省略 user-id 以导出密钥环内所有的公钥。这可以用来分享多个身份,或是将其导入到另一个程序,比如 Thunderbird

导入公共密钥

要给其他人发送加密信息,或者验证他们的签名,就需要他们的公钥。通过文件 public.key 导入公钥到密钥环:

$ gpg --import public.key.asc

此外,还可以通过#密钥服务器导入公钥。

上传公钥

公钥服务器是网络上专门储存用户公钥的服务器。send-keys参数可以将公钥上传到服务器。

gpg --send-keys [用户ID] # --keyserver hkp://subkeys.pgp.net

使用上面的命令,你的公钥就被传到了服务器subkeys.pgp.net,然后通过交换机制,所有的公钥服务器最终都会包含你的公钥。

由于公钥服务器没有检查机制,任何人都可以用你的名义上传公钥,所以没有办法保证服务器上的公钥的可靠性。通常,你可以在网站上公布一个公钥指纹,让其他人核对下载到的公钥是否为真。fingerprint参数生成公钥指纹。

gpg --fingerprint [用户ID]

### 导入密钥

除了生成自己的密钥,还需要将他人的公钥或者你的其他密钥输入系统。这时可以使用import参数。

gpg --import [密钥文件]

为了获得他人的公钥,可以让对方直接发给你,或者到公钥服务器上寻找。

gpg --keyserver hkp://subkeys.pgp.net --search-keys [用户ID]

正如前面提到的,我们无法保证服务器上的公钥是否可靠,下载后还需要用其他机制验证.

维护

备份你的私钥

用如下命令备份你的私钥。

$ gpg --export-secret-keys --armor --output private-key.asc user-id

请注意,上述命令将要求您输入密钥的密码。这是因为,否则任何获得上述导出文件访问权限的人都可以像您一样对文档进行加密和签名,而无需知道您的密码。

警告:

  • 口令通常是密钥安全方面最薄弱的环节。最好把导出的文件放在另一个系统或者设备里,比如物理保险柜或者加密驱动器中。这是当你遇到设备被盗、磁盘故障等情况时恢复对密钥控制权的唯一安全措施。

  • 这种备份方式有一些安全局限性,这篇文章 https://web.archive.org/web/20210803213236/https://habd.as/post/moving-gpg-keys-privately/ 中有关于用 gpg 备份和导入密钥的更加安全的办法。

用如下命令导入你的私钥备份

$ gpg --import private-key.asc

提示: 你可以用 Paperkey 来把私钥导出为明文文本或条形码,并打印出来存档。

备份你的吊销证书

生成新密钥对的时候会同时生成吊销证书,默认存放在 ~/.gnupg/openpgp-revocs.d/ 下,证书的文件名是对应的密钥的指纹。 你也可以用以下命令手动生成吊销证书:

$ gpg --gen-revoke --armor --output revcert.asc user-id

如果密钥丢失或泄露,此证书可用于 #吊销密钥。如果你无法访问密钥,则无法使用上述命令生成新的吊销证书,那么备份将非常有用。吊销证书很短,你可以把他打印出来然后在需要使用的时候手动输入到电脑里。

警告: 任何能接触到吊销证书的人都可以吊销你的密钥对,而且无法撤消。所以请像保护私钥一样保护你的吊销证书。

编辑你的密钥

运行 gpg --edit-key user-id 命令将会出现一个菜单,该菜单使你能够执行大部分密钥管理相关的任务。

在编辑密钥子菜单中输入 help 命令可以显示完整的命令列表。以下是一些有用的命令:

> passwd       # 修改密码短语
> clean        # 压缩任何不再可用的用户ID(例如已撤销或已过期)
> revkey       # 撤销密钥
> addkey       # 向该密钥添加子密钥
> expire       # 更改密钥过期时间
> adduid       # 添加附加的名称、注释和电子邮件地址
> addphoto     # 向密钥添加照片(必须是JPG格式,推荐大小为240x288,当提示时输入完整路径)

提示:如果你有多个电子邮件账户,你可以使用 adduid 命令将每个账户都添加为一个身份。然后你可以将你最喜欢的账户设置为 primary

导出密钥

如果您计划在多个设备上使用相同的密钥,您可能希望去除主密钥,只保留在较不安全的系统上的最低限度的加密子密钥。

首先,找出您想要导出的子密钥。

$ gpg --list-secret-keys --with-subkey-fingerprint
$ gpg --fingerprint #输出公钥指纹,用来核对公钥的可靠性
$ gpg --armor --output public-key.txt --export [ID]  #导出公钥
$ gpg --armor --output secret-key --export-secret-key [ID] #导出主私钥,注意安全性!!!
$ gpg --armor --output sign-subkey --export-secret-subkeys [ID]!   #导出有[S]标识、签名用子私钥
$ gpg --armor --output encrypt-subkey --export-secret-subkeys [ID]! #导出有[E]标识、加密用子私钥
$ gpg --armor --output authentication-subkey --export-secret-subkeys [ID]! #导出有[A]标识、认证用子私钥
# --armor选项不启用,就会导出二进制格式文件

仅选择要导出的子密钥。

$ gpg -a --export-secret-subkeys [子密钥id]! > /tmp/subkey.gpg

警告: 如果您忘记添加“!”,所有子密钥都将被导出。

为确保只导出子密钥,你可以使用如下命令检查密钥所包含的私钥内容

gpg --list-packets <密钥文件名>

得到形如

# off=0 ctb=94 tag=5 hlen=2 plen=134
:secret key packet:
     	…………
        keyid: A007A5B0CD79555D
# off=136 ctb=b4 tag=13 hlen=2 plen=32
:user ID packet: "Tsaitang <[email protected]>"
# off=170 ctb=88 tag=2 hlen=2 plen=172
:signature packet: algo 22, keyid A007A5B0CD79555D
		…………
# off=344 ctb=9c tag=7 hlen=2 plen=134
:secret sub key packet:
        …………
        keyid: BFD75242E6763BC8
# off=480 ctb=88 tag=2 hlen=2 plen=239
:signature packet: algo 22, keyid A007A5B0CD79555D
        …………

其中:

  • 一个密钥开始于 :secret key packet: 并以 # off= 结束。
  • 密钥的用户 ID 由 :user ID packet: 标识。
  • 密钥的签名由 :signature packet: 标识。

就能判断有几个子密钥了,单子密钥一般只有自己的密钥和主密钥,所以有两个密钥段,keyid就可以证实这一点。

 

 

到此为止,您可以停止了,但最好同时更改密码。将密钥导入临时文件夹。

$ gpg --homedir /tmp/gpg --import /tmp/subkey.gpg
$ gpg --homedir /tmp/gpg --edit-key 用户id
> passwd
> save
$ gpg --homedir /tmp/gpg -a --export-secret-subkeys [子密钥id]! > /tmp/subkey.altpass.gpg

注意: 您会收到一个警告,说明主密钥不可用且密码未更改,但可以安全地忽略,因为子密钥的密码已经更改。

此时,您现在可以在其他设备上使用 /tmp/subkey.altpass.gpg

延长过期日期

警告: 永远不要删除已过期或已吊销的子密钥,除非你有充分的理由。这样做将导致你无法解密使用旧子密钥加密的文件。请从其他用户那里删除已过期或已吊销的密钥以清理你的密钥环。

在你的子密钥上设置一个过期日期是一个好的做法,这样如果你失去了对密钥的访问(例如,你忘记了密码短语),密钥将不会继续被他人无限期地使用。当密钥过期时,延长过期日期相对简单:

$ gpg --edit-key 用户ID
> expire

你将被要求输入一个新的过期日期,以及用于签署新过期日期的你的密钥密码短语。

对于任何其他已过期的子密钥,重复此步骤:

> key 1
> expire

最后,保存更改并退出:

> save

将其更新到密钥服务器。

$ gpg --keyserver keyserver.ubuntu.com --send-keys key-id

注意:--keyserver 参数要在

或者,如果你在多台电脑上使用此密钥,你可以导出带有新签署过期日期的公钥,并在这些计算机上导入它:

$ gpg --export --output pubkey.gpg user-id
$ gpg --import pubkey.gpg

无需重新导出你的私钥或更新你的备份:主密钥本身永不过期,只需要公钥和子密钥上的过期日期的签名。

轮换子密钥

警告: 永远不要删除过期或被撤销的子密钥,除非有充分的理由。这样做将导致您无法解密使用旧子密钥加密的文件。请从其他用户那里删除过期或被撤销的密钥以清理您的密钥环。

或者,如果您希望在子密钥过期后完全停止使用它们,您可以创建新的子密钥。请提前几周进行此操作,以便其他人可以更新他们的密钥环。

提示:您不需要仅因为密钥过期而创建新密钥。您可以延长过期日期,请参阅部分#延长过期日期

创建新的子密钥(对签名和加密密钥都重复此操作)

$ gpg --edit-key user-id
> addkey

回答它询问的以下问题(参见#创建密钥对以获取建议的设置)。

保存更改

> save

将其更新到密钥服务器。

$ gpg --keyserver pgp.mit.edu --send-keys user-id

注意: --keyserver 参数要在操作参数之前,否则会报错。

您还需要导出一份最新的私钥备份。有关如何执行此操作的详细信息,请参见#备份私钥

提示:撤销过期的子密钥是不必要的,而且可能会被认为是不好的做法。如果您不断撤销密钥,可能会导致其他人对您缺乏信心。

吊销密钥

如果密钥被泄露、被取代、不再使用或者您忘记了密码,应该执行密钥撤销操作。这可以通过将密钥与密钥的撤销证书合并来完成。

如果您无法再访问您的密钥对,请首先导入您自己的公钥。 然后,要撤销密钥,请导入保存在撤销证书中的文件:

 $ gpg --import revcert.asc

现在,撤销操作需要公开。使用密钥服务器将撤销的密钥发送到公共 PGP 服务器(如果您以前使用过),否则,将撤销的密钥导出到文件并分发给您的通信伙伴。

加密与签名

 加密

encrypt参数用于加密。

gpg --recipient [用户ID] --output demo.en.txt --encrypt demo.txt

recipient参数指定接收者的公钥,output参数指定加密后的文件名,encrypt参数指定源文件。运行上面的命令后,demo.en.txt就是已加密的文件,可以把它发给对方。

解密

对方收到加密文件以后,就用自己的私钥解密。

gpg --decrypt demo.en.txt --output demo.de.txt

decrypt参数指定需要解密的文件,output参数指定解密后生成的文件。运行上面的命令,demo.de.txt就是解密后的文件。

GPG允许省略decrypt参数。

gpg demo.en.txt

运行上面的命令以后,解密后的文件内容直接显示在标准输出。

 

签名

sign参数用来签名。签名可以验证文件来源,以及是否被修改。

gpg --sign demo.txt

运行上面的命令后,当前目录下生成demo.txt.gpg文件,这就是签名后的文件。这个文件默认采用二进制储存,如果想生成ASCII码的签名文件,可以使用clearsign参数。

gpg --clearsign demo.txt

运行上面的命令后 ,当前目录下生成demo.txt.asc文件,后缀名asc表示该文件是ASCII码形式的。

如果想生成单独的签名文件,与文件内容分开存放,可以使用detach-sign参数。

gpg --detach-sign demo.txt

运行上面的命令后,当前目录下生成一个单独的签名文件demo.txt.sig。该文件是二进制形式的,如果想采用ASCII码形式,要加上armor参数。

gpg --armor --detach-sign demo.txt

 

验证

我们收到别人签名后的文件,需要用对方的公钥验证签名是否为真。verify参数用来验证。

gpg --verify demo.txt.asc demo.txt

 

 签名+加密

如果想同时签名和加密,可以使用下面的命令。

gpg --local-user [发信者ID] --recipient [接收者ID] --armor --sign --encrypt demo.txt
  • local-user参数指定用发信者的私钥签名,
  • recipient参数指定用接收者的公钥加密,
  • armor参数表示采用ASCII码形式显示,
  • sign参数表示需要签名,
  • encrypt参数表示指定源文件。

其他

ssh-auth

生成 认证(A)用子密钥

gpg --expert --edit-key {keyid/uid}                                   ## 使用专家模式, 不然没有认证的选项


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                                                   ## 选8, RSA, 自定义权限

Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt                               ## 这里显示默认有Sign和Encrypt两种权限

   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S                                                   ## 关闭Sign

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                                                   ## 关闭Encrypt

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                                                   ## 开启Authenticate

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? (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) 0                                             ## 有效期
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/xxxxxxxxxxxxxxxx
     created: 2019-01-07  expires: 2021-01-06  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa2048/xxxxxxxxxxxxxxxx
     created: 2019-01-07  expires: 2021-01-06  usage: E
ssb  rsa4096/xxxxxxxxxxxxxxxx
     created: 2019-01-07  expires: 2020-01-07  usage: A
[ultimate] (1). Name <[email protected]>

gpg> save                                                            ## 保存

配置文件

编辑bashrc 文件, 将默认ssh 的agent替换为 gpg-agnet

#  ~/.bashrc

export GPG_TTY=$(tty)
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
echo UPDATESTARTUPTTY | gpg-connect-agent 1> /dev/null

编辑~/.gnupg/gpg-agent.conf文件,增加:

#  ~/.gnupg/gpg-agent.conf
--------------------------
enable-ssh-support

接着:

❯  gpg --expert -k --with-keygrip --keyid-format=long
[keyboxd]
---------
pub   ed25519/A007A5B0CD79555D 2024-08-12 [SC]
      1F7410E551D95CDDD6F890C8A007A5B0CD79555D
      Keygrip = 4988CFC9B1D3AD16C330D6B925B28336075ABCA4
uid                   [ 绝对 ] Tsaitang <[email protected]>
sub   ed25519/BFD75242E6763BC8 2024-08-12 [S]
      Keygrip = 84FE27B53506275AE960C863EC1453D61F68050D
sub   cv25519/19FCB4E968C9091E 2024-08-12 [E]
      Keygrip = E141C6CB26480493F23CD183252D50F4200C4C7D
sub   ed25519/306C2E872F7FDF1B 2024-08-13 [A]
      Keygrip = F7F49609C6E7CCDC8B2508476CB04E9BE89E9A16
sub   rsa3072/DAD3AF17E3B4AE7E 2024-08-13 [SE]
      Keygrip = DE23F9773FA36142B01CBBE0A3E1B226E079E3BE

选择你新加的带有[A]标志的那个新的子密钥的 keygrip , 即DE23F9773FA36142B01CBBE0A3E1B226E079E3BE

加入到~/.gnupg/sshcontrol文件, 运行ssh-add -l, 查看是否已经加入。

然后

gpg --export-ssh-key   [keyid]! 

注意,这里不能用 uid ,不然会提示:

gpg: key "uid" not found: Unusable public key
gpg: export as ssh key failed: Unusable public key

这里只能填子密钥的 key id,这个例子里就是 DE23F9773FA36142B01CBBE0A3E1B226E079E3BE

输出的 ssh public key 放到你的服务器上的~/.ssh/authorized_keys中, 重启shell, 就可以连接了.

gpg密钥对转ssh密钥对

git-commit

 

 

参考:Archlinux WIKI

“您的支持是我持续分享的动力”

微信收款码
微信
支付宝收款码
支付宝

目录