复用现有公私钥,添加到GitHub账户

前言

之前在Linux上使用过Git,生成了绑定GitHub的公私钥、也把两个密钥文件保存在了本地。现在也想要Windows下的Git绑定GitHub,但是不知道如何用同一对公私钥绑定GitHub。

如果不解决,拉取仓库就会有Please make sure you have the correct access rights
and the repository exists.的问题

1
2
3
4
5
6
7
8
9
10
ubuntu@instance:~$ git clone [email protected]:V2RaySSR/Trojan.git
Cloning into 'Trojan'...
The authenticity of host 'github.com (15.164.81.167)' can't be established.
ECDSA key fingerprint is SHA256:p2QAMXNIC1TJYWeIOttrVc98/R1BUFWu3/LiyKgUfQM.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

网上关于绑定GitHub的大多数办法

首先去网上一搜,我看到的几乎所有答案都是只讲如何生成一对新的公私钥,用它绑定GitHub:

(BTW,网上关于GitHub密钥绑定的绝大部分文章都是这样新建密钥,同样的内容重复太多,降低了信息密度,查找起有效解决办法来很难)
难道已经有了密钥就不配用GitHub吗?Windows和Linux的Git各自使用一个ssh密钥和github绑定,非常麻烦,而且每次更换电脑,还要再次生成密钥、添加到github。


后来看到这个帖子,和我是一样的问题。然后我意识到应该指定让SSH客户端使用自己的私钥。

【急】github的密钥重新生成后,怎么连接? (链接已失效)
https://bbs.csdn.net/topics/396066450

其实官方文档中有对现有SSH密钥的描述,其中提到“默认情况下,公钥的文件名是以下之一:id_rsa.pub、id_ecdsa.pub id_ed25519.pub”。然后我打开存放密钥的目录( ~/.ssh),用自己的密钥将原有的密钥替换后,完成绑定(其实这种方法有个前提是,SSH已经生成过一个密钥,后面会细讲)。

原理(重要)

到底是怎么回事当然要弄清楚。
应该可以意识到,代码托管服务器不管是Github服务器也好,还是自建服务器也好,本质都是Git先通过SSH连接本地和服务器,然后Git再对数据进行同步等处理。

既然最终都是SSH连接,那Git连接服务器和我们平时使用SSH连接远程服务器是一样的,SSH部分涉及的内容完全相同,也包括ssh_config、sshd_config等配置文件。

因此,“让Git 和GitHub账户通过现有的SSH公私钥进行绑定”这个问题最终归结到SSH连接的问题。一方面,要让Github服务器记录SSH公钥(这个很简单,在Github账户设置中,把公钥粘贴到对应部分并保存即可),另一方面,要在本地SSH正确配置对应的私钥。

SSH中有一个负责管理私钥的部分,叫做ssh-agent。查阅Linux手册:https://linux.die.net/man/1/ssh-agent,里面有如下描述:

The agent initially does not have any private keys. Keys are added using ssh-add(1). When executed without arguments, ssh-add(1) adds the files ~/.ssh/id_rsa, ~/.ssh/id_dsa and ~/.ssh/identity. If the identity has a passphrase, ssh-add(1) asks for the passphrase (using a small X11 application if running under X11, or from the terminal if running without X). It then sends the identity to the agent. Several identities can be stored in the agent; the agent can automatically use any of these identities. ssh-add -l displays the identities currently held by the agent.

大意是讲:agent一开始并没有任何私钥,可以通过命令ssh-add添加指定的私钥,如果有密码短语(passphrase)则需要验证。agent可以存储多个密钥,并且会自动选择使用哪个,ssh-add -l可以显示目前agent用的哪个密钥。

重点是加粗的部分,因为一开始并没有私钥,所以有2种方式

1.使用ssh-keygen生成一对新密钥;

2.使用ssh-add命令向agent指定使用哪个私钥。

所以为什么上面说用自己的密钥替换原有密钥的前提是:SSH已经生成过一个密钥。经过实测, 直接把私钥放在一台没有使用过ssh的新机器的默认目录下是不行的,因为ssh-agent开始是空的,并没有默认密钥,这种情况要么ssh-keygen生成一个默认密钥再替换、要么使用ssh-add显式指定自己的密钥。

最终解决方案:

  • 一是可以用自己的密钥文件替换掉agent生成的密钥文件(我用的方法,前提是SSH已经生成过一个密钥);
    这个很简单,将自己的密钥改成和agent记住的密钥相同的名字,然后替换即可。对于SSH来说,它的所有配置、所有进行的工作都没有变,仍然是使用相同的文件(它只记住了路径,对他来说文件是一样的)进行连接。

  • 二是对SSH客户端进行配置,告诉他应该使用的密钥文件而不是默认的密钥文件。这里也包含两种方法:

    1. 通过用户配置文件的设置,要求SSH使用指定密钥进行连接;
      上面CSDN的帖子就是通过配置文件进行设置,指定了使用的密钥。“在.ssh下建立config文件,在里面指定那个服务器用哪个密钥文件”。查阅官方文档可以看到,配置文件中有一项属性叫做IdentityFile,用来指定认证时使用的文件(密钥)。将其指定为自己的密钥即可。(参见文章末尾“其他”部分的SSH配置文件)

    2. 通过命令ssh-add,借助ssh-agent,要求SSH使用指定密钥进行连接
      Github官方的文档中就是这种方法,使用ssh-add命令将自己的密钥添加到ssh-agent中,有时候每次都需要添加一下,不知道为什么。(参见文章末尾“其他”部分的“SSH的ssh-add命令”)

      1
      2
      3
      4
      5
      6
      7
      8
      #启动ssh-agent
      eval $(ssh-agent)

      #列出当前ssh-agent中保存的所有密钥
      ssh-add -l

      #添加指定私钥文件到ssh-agent,文件名为空时默认添加~/.ssh/id_rsa
      ssh-add [file ...]

测试连接

最后,使用ssh -T git@github.com命令测试上述配置是否生效,能否连接到Github。

测试 SSH 连接
https://docs.github.com/cn/github/authenticating-to-github/testing-your-ssh-connection

可能遇到的问题和解决方案

1.ssh-add的连接问题

添加私钥时报错

1
2
ubuntu@instance:~/.ssh$ ssh-add id_rsa
Could not open a connection to your authentication agent.

这种情况是ssh-agent没有启动,解决方法:

1
eval $(ssh-agent)

然后再添加密钥即可:

1
ssh-add #添加默认文件~/.ssh/id_rsa

2.Private key permissions too open

上面问题解决掉之后还有可能遇到如下问题:

1
2
3
4
5
6
7
8
ubuntu@instance:~/000_apps$ ssh -T [email protected]
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0664 for '/home/ubuntu/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/ubuntu/.ssh/id_rsa": bad permissions

原因是其他用户拥有对私钥文件id_rsa的读等权限,有安全性风险。chmod 600 ~/.ssh/id_rsa修改权限即可,参考Private key permissions too open

3.Connection timed out

1
2
3
4
5
6
7
$ git clone [email protected]:githubName/repo.git
Cloning into 'repo'...
ssh: connect to host github.com port 22: Connection timed out
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

并且测试连接同样也是超时

1
2
$ ssh -T [email protected]
ssh: connect to host github.com port 22: Connection timed out

这种情况是网络问题,需要添加设置到SSH配置文件~/.ssh/config,参考这个方法:

https://gist.github.com/Tamal/1cc77f88ef3e900aeae65f0e5e504794

Solution for ‘ssh: connect to host github.com port 22: Connection timed out’ error

4.每次都要执行ssh-add

每次对远程仓库进行操作都会遇到上个问题权限问题,但是测试连接正常。

1
2
3
4
5
6
7
$ git clone [email protected]:githubName/repo.git
Cloning into 'repo'...
ssh: connect to host github.com port 22: Connection timed out
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

这种情况需要执行问题1里面的两条命令,但是git-add命令每次重启后失效,因此每次都要执行。

也可以通过修改git的bashrc文件实现自动添加,在git安装目录下的etc/bash.bashrc 文件中添加问题1里面的两条命令即可。

1
2
eval $(ssh-agent)
ssh-add #添加默认文件~/.ssh/id_rsa

解决Windows下使用github需要每次都要ssh-add的问题

https://blog.csdn.net/EsonJohn/article/details/79134665




参考

SSH配置文件

配置文件有两个,一个是用户配置文件,仅在当前用户下生效,另一个是全局配置文件,对所有用户生效。一般情况下最好只修改用户配置。
不管是Linux还是Windows,SSH的用户配置文件(包含设置文件和公私钥)永远是~/.ssh/config。
具体来说,Windows的用户配置文件在C:\Users\用户名.ssh
Linux的用户配置文件在/home/用户名/.ssh

官方文档对SSH配置文件的说明

ssh_config — OpenSSH client configuration file
https://man.openbsd.org/ssh_config

SSH的ssh-add命令

官方文档对ssh-add命令的说明

ssh-add — adds private key identities to the OpenSSH authentication agent
https://man.openbsd.org/ssh-add.1

官方文档关于现有 SSH 密钥的文档

检查现有 SSH 密钥
https://docs.github.com/cn/github/authenticating-to-github/checking-for-existing-ssh-keys