为了更清楚和更明确:
请记住,这里至少涉及 两台 计算机:您的计算机,用于存储各种文件和设置,以及 GitHub 的计算机。 (GitHub 使用多台机器,但它们伪装成单台计算机。)
您的计算机通过 Internet 调用 GitHub,就像拨打电话一样。然后,您的计算机会交出某种形式的凭据。他们的计算机会检查这些凭据,并确定您是否是您自称的人。
-
您交出的凭据取决于如何您拨打电话。如果您使用 https://... 拨打电话,Git 将使用 凭据管理器。每个操作系统都有自己的一组 Git 可以使用的凭证管理器,因此这里的过程在 Windows、MacOS、Linux 等平台上非常不同。如果您使用ssh://... 拨打电话,所有操作系统都共享足够多的通用 SSH 代码库,因此此时它们都以几乎相同的方式进行操作,尽管仍然会出现特定于操作系统的项目。
由于您使用的是 SSH,因此您交出的(单个,但见下文)凭据是您的 公共 ssh 密钥(也使用加密,使用您的私钥 - 请参阅 this Digital Ocean article实例)。您的 ssh 密钥存储在特定于操作系统(且可配置)的位置。在您的特定情况下,它是$HOME/.ssh/id_rsa.pub。末尾不带.pub的名字就是private密钥,这些密钥是成对出现的。
当 GitHub 收到您的密钥时,他们会在一张巨大的表格中查找它,并在其中保存每个人都提供给他们的每一个密钥。您的密钥永远不会匹配其他任何人的密钥。你给他们的钥匙有一个与之相关的用户名,当你给他们那个钥匙的时候。由于只有您拥有此密钥(以及随附的私钥),GitHub 现在可以确定您就是您刚刚声称的身份。
索赔完全是通过这个公钥发生的。如果您不想再声称自己是那个人,请交出一个不同的公钥。 You'll also need to log in to Git, and give them the new or updated public key. 这必须发生在您生成公钥/私钥对之后,并且在您使用ssh 将您的计算机和您的 Git 连接到他们的计算机与他们的 Git 之前。
这里有两件重要的事情需要注意,这会使原本相对简单的画面变得复杂。同样,简化图片是:有一个密钥对。您在 GitHub 上存储来自这一密钥对的公钥。稍后,您的 Git 通过ssh 调用 GitHub。您的ssh 和他们的sshd 交换一些数据。您的 ssh 使用密钥对中的 both 密钥进行加密。他们现在知道您就是您,因为他们可以使用您的公钥副本匹配所有内容,并且只有 您 拥有 private 密钥能够解锁数据。但您可能希望在您的计算机中保留多个密钥对,这会使一切变得复杂。
为不同的接收者提供不同的密钥
常用的base ssh软件可以依次尝试各种key-pairs。有关(许多和复杂的)详细信息,请参阅下面有关多个键的部分。但是,您可以告诉它尝试一个特定的 文件,根据您正在 ssh-ing 的主机选择一个文件,使用 config 文件 ($HOME/.ssh/config)。例如,假设您希望与github.com 的所有连接仅使用存储在文件$HOME/.ssh/id_rsa.github 和$HOME/.ssh/id_rsa.github.pub 中的私钥和公钥对。那么:
Host github.com
IdentitiesOnly yes
IdentityFile ~/.ssh/id_rsa.github
会这样做。第一行 Host github.com 告诉 SSH 以下条目适用于与名为 github.com 的主机的会话。 (此处允许使用全局模式,因此如果您的工作或学校或任何拥有名称匹配 *.example.com 的主机,您可以使用这样的全局模式。)
第二行 IdentitiesOnly yes 覆盖通过 ssh-agent 提供的身份。你可能想也可能不想这样做!如果您使用 ssh-agent 来提供身份,这会故意破坏(至少部分)代理的提议。请参阅下一节中的详细信息。
最后一行 IdentityFile <em>path</em> 设置密钥或密钥对文件的名称。 ssh 将在此处根据需要添加或删除 .pub。 (ssh 版本有一些变化,您可能想要或不想要.pub;使用适合您的。)
ssh(你用来连接服务器的面向用户的命令)和sshd(你的 ssh 连接到的服务器上的命令)都是非常可配置的。有关 ssh 配置选项的完整列表,请参阅the ssh_config manual page。
代理和IdentityFile 条目
在$HOME/.ssh/config 文件的每个主机配置部分,您可以放入多个IdentityFile 行。如果你这样做了,ssh 将提供 每个 密钥,直到一个被接受,或者它用完了提供的密钥。
如果你有 no IdentityFile 行,你的 SSH 有一些内置的默认值。这些从一个 SSH 版本(和操作系统)到另一个略有不同;查看您自己的ssh_config 文档以获取您的 系统列表,但我上面链接的文档说:
对于协议版本 2,默认为 ...~/.ssh/id_rsa 和 ~/.ssh/id_dsa。
(现在,DSA 加密至少已弃用,而且几乎完全不受支持。我认为 ECDSA 加密是目前最喜欢的,尽管加密不是我的领域。)
在没有IdentitiesOnly yes 的情况下,SSH 可能也提供所有您的SSH 代理提供的身份(即密钥)。该代理是一个帮助系统,允许您将密钥从一台计算机(您最信任的一台)传送到另一台计算机,而无需将它们存储在不太受信任的计算机上的文件中。它的工作方式看起来相对简单,大局观:当你的 ssh 联系其他主机H,如果你没有说IdentitiesOnly yes,你的 ssh 联系您的代理并要求 it 提供要尝试的密钥。它将在主机 H 上尝试这些键,一次一个。如果它们都不起作用,它仍然有任何本地存储的文件和/或IdentityFile 条目中列出的文件。
然而,细节很复杂。首先,请注意代理本身分为两部分。 (这些不一定是单独的程序,但通过将每个程序描述为单独的事物来更容易考虑系统。)
两台机器都启动了一个代理。有时您可能会在每台机器上运行多个代理,并且细节再次因操作系统而异——例如,在 MacOS 上,只需登录即可创建一个代理,然后您的所有终端窗口都可以共享该代理。在任何终端窗口中,您运行 ssh less-trusted-machine 并在不太受信任的机器上启动一个新会话,它 也会启动一个代理,或者使用您已经拥有的代理,或者其他什么。
然后你现在在 second 机器上使用 Git。不太受信任的机器的 ssh 注意到有一个代理,并要求它提供密钥。此代理会联系您更受信任的计算机上的代理。您更受信任的机器上的代理会检索密钥并将其移交或不移交,这一切都取决于两个代理和各种 ssh 实例使用的规则。
因此,当您使用代理时,信任度较低的机器拥有(或有权访问)的密钥集取决于更多上的代理em>-trusted 机器可以。所以这就是为什么这张图片很复杂。
如果你根本不使用代理,或者如果在命令行解释器中运行ssh 或让Git 运行ssh,你完全击败了代理, 1 您运行的 ssh 或 Git 运行的 ssh 只能访问您在 $HOME/.ssh/ 或您放置此类密钥的其他操作系统特定位置中拥有的那些身份(密钥对)。当然,它仍然可以访问所有您放在那里的密钥。您的配置中的IdentitiesOnly yes 行现在意味着只使用我在此处列出的文件。这非常简单:您列出文件——或者更确切地说,列出每对文件中的一个,然后将密钥放在文件。
如果您正在使用代理,则您或 Git 运行的 ssh 可以访问其他密钥对。在此处添加IdentitiesOnly 很复杂。它不会阻止您的 ssh 与代理联系——但代理返回的每个密钥都有一个身份。你可以告诉 ssh 你正在运行只使用与我在IdentityFile 部分中指定的文件匹配的身份。这意味着你可以只存储公钥 strong>,而不是公钥和私钥对文件。如果您不太信任这台机器(我一直称它为不太受信任的机器),那么您可以使用代理完全不使用私钥。
最后,无论您在哪台机器上存储了公钥和私钥,都可以加密它们。您现在需要输入密码或密码来解锁它们。这可能会很烦人,但是使用代理,您可以为代理解锁一次,并相信代理会确保它们在内存中的安全。 (多少你可以信任这个代理......好吧,这完全是另一个问题!)
键太多
实际解锁和测试你是否是你声称的人通常发生在sshd,实现ssh的服务器端软件。您的 ssh 调用他们的 sshd 并交出密钥,其中包含所有加密协议等。他们使用密钥对的公钥部分在锁中尝试它,它可以工作......或不工作 - 如果它没有工作,他们可能会为您提供更多尝试。这是可配置的,在服务器上。
现在,假设您正在使用代理并在代理中存储了五十 (50) 个不同的密钥。您的 ssh,无论您在哪台计算机上(无论它是多么受信任),都从代理获取一个密钥并将其提供给 sshd,但这并不好。您的 ssh 从代理获取下一个密钥,并尝试使用该密钥,但它也不是正确的密钥。这就像你在一个钥匙圈上摸索 50 把钥匙,甚至没有看每把钥匙,而是在锁里试一试。过了一会儿,服务器上的 sshd 被反复的故障吓到了:看起来你正试图闯入。
实际允许的尝试次数因一台服务器而异,因为它是可配置的。但是,如果您确实有 lot 键,最好尝试 right 键(仅,或首先)。为此,您需要使用IdentitiesOnly yes 行,无论您是否使用代理:
如果您不使用代理,IdentitiesOnly yes 表示仅使用此处每个IdentityFile 配置条目中列出的公钥/私钥对。 所以你列出了正确的,而且你的 ssh 使用了正确的,它适合锁并且他们的 sshd 喜欢你,一切都很好。
如果您确实使用代理,IdentitiesOnly yes 表示使用与IdentityFile 配置条目或此处的条目中列出的公钥匹配的代理密钥。所以你列出了正确的,你的 ssh 使用了正确的,和以前一样,一切都很好。
如果您使用代理,但只有几个密钥——只有一个或两个,甚至可能多达六个左右,具体取决于您调用的服务器上的 sshd 配置——您不需要 IdentitiesOnly yes 和 IdentityFile 行。但他们不会伤害,只要你做对了。
将所有这些放在一起
您可以(实际上必须)将密钥对文件存储在最受信任的计算机上的某个位置。您也可以加密这些,这样您就必须输入密码或密码才能解锁它们,尽管这可能会很烦人。代理人可以提供帮助。您可能(可能会)需要使用ssh-add 将密钥加载到该代理中。
当您从一台计算机 ssh 到另一台计算机时,您可以将您的代理转发到下一台计算机上的新代理。链中的第二台和任何后续计算机都需要密钥对的 public 密钥,以验证您是您,但如果您设置了代理转发,则它们不需要私钥键。
当您启动 ssh 会话时,此信任链中的每台计算机(您 ssh 从更受信任的计算机进入)都会获取您最初发送的加密数据。他们使用存储的公钥,你已经以某种方式(任何你喜欢/可以的方式)存储在不太受信任的计算机上,看看你是否知道私人钥匙。如果你这样做了,那么你一定是你自己。
-
除了他们喜欢他们的sshd 之外,GitHub 并没有什么不同:它只是一台不太受信任的计算机,你可以“登录”(如 git@github.com)。他们获取您提供给他们的密钥并进行查找 - 但不是只有 一个 密钥供 您 使用,而是 GitHub 上存在的每个帐户都有一个密钥。他们尝试你给他们的钥匙,看看它是否可以在爱丽丝的锁中使用。没有?不能是爱丽丝;在鲍勃的锁里试试。不?试试卡罗尔——等等,直到它解锁弗雷德、丽塔或扎克。当他们获得 有效 存储的 .pub 密钥时,那一定是 你。2
李>
1在 shell 会话中,您会看到一个环境变量 SSH_AUTH_SOCK,它包含您运行 ssh 所使用的路径名on机器联系代理。如果您覆盖或取消设置环境变量,则会破坏代理。
要查看您是否有激活的代理,如果有,它可以访问哪些密钥,请使用ssh-add -l。
2像这样一次尝试一个身份,线性地通过数千或数百万个身份,太慢了,因此 GitHub 必须在内部使用不同的策略。但效果是一样的:您通过您的公钥/私钥对和加密,从您的 ssh 到他们的 sshd,为他们提供了一个身份位串。他们为每个人 使用收集到的授权密钥,并在那一堆中找到唯一的某人,而无论他们找到谁,这就是你。如果他们没有找到任何人,他们会拒绝该密钥,并且您的 ssh 可以继续提供另一个密钥,直到他们在 他们的 sshd 中设置的任何限制。