2017-02-28 18:19:37 +0000   |     web ssh rsa   |   Viewed times   |    

对称加密(Symmetric-key)

1976年以前,所有的加密方法都是同一种朴素的模式:

  1. 我有一段信息: hello ronald,我把所有字母都替换成字母表上的下一个字母,变换成比如说ifmmp spobme,传递给比如说Ronald。
  2. Ronald拿到拿到密文ifmmp spobme,把所有字母替换成字母表上的前一个字母,恢复成明文hello ronald

问题是,我需要告诉Ronald我的加密规则。如果我这个规则被坏人知道了,我和Ronald之间的所有秘密对话都会被破解。

非对称加密

非对称加密有两把钥匙: 公钥-私钥公钥专门用来加密,上锁。私钥用来解密。我可以把公钥给任何人。谁都可以用这个公钥来加密信息,然后传给我。只有握有私钥的我能够解密消息。但反过来行不通,不能用私钥加密然后用公钥解密。这样就算坏人截获了公钥,他也无法用它来解密信息。关于RSA算法公钥-私钥的生成原理,参见阮一峰的两篇博客: [RSA算法原理-Part 1]: http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html [RSA算法原理-Part 2]: http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html

SSH密码登陆

原始的密码登陆不安全的原因,是因为我直接向网站发送我的明文密码,数据包很可能在中间被截获下来。密码就泄露了。

$ ssh user@host

SSH之所以能够保证安全,因为它采用了非对称加密。发送密码之前,先用公钥加密,对方收到密码再用私钥解密。过程是这样的:

  1. 远程主机收到用户的登录请求,把自己的公钥发给用户。
  2. 用户使用这个公钥,将登录密码加密后,发送回来。
  3. 远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。

但这样登陆,容易受到“中间人攻击(Man-in-the-middle attack)”。坏人站在我和信息目的地之间,截获我的登陆请求,把他假冒的公钥发给我。我用这个假冒公钥加密之后,发还给他,他再用他的私钥破译我的密码。

所以用SSH协议登陆时,输入密码之前,会将对方的公钥指纹发给用户。这个公钥指纹是对方公钥通过MD5计算的校验和。一般公布在对方网站上。用户确认公钥正确后,再输入密码。

$ ssh user@host
  The authenticity of host 'host (12.18.429.21)' can't be established.
  RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d.
  Are you sure you want to continue connecting (yes/no)?

当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。

SSH公钥登陆

使用密码登录,每次都必须输入密码,非常麻烦。好在SSH还提供了公钥登录,可以省去输入密码的步骤。

所谓”公钥登录”,原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。

生成RSA秘钥

要生成公钥和私钥前,先到~/.ssh目录下,看看是不是已经有生成好的。

$ cd ~/.ssh
$ ls

如果看到像下面这样,有一对somethingsomething.pub文件(文件名经常是id_dsa),这就是钥匙。id_dsa是私钥,id_dsa.pub是公钥。

authorized_keys2  id_dsa       known_hosts
config            id_dsa.pub

没有的话,用下面命令创建秘钥。

$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

过程中需要根据提示填写一些配置信息,比较重要的是要设一个passphrase。为什么要passphrase?因为理论上一旦我的电脑被别人拿到,因为私钥储存在电脑上,他就可以在我Github上做任何事情。passphrase就是为了多加一层防护。提供私钥的同时,还要输入passphrass。但之后用ssh-agent管理程序托管我们的私钥以后,就可以不用每次都输入passphrase了。(其实好像还是拿到我的电脑就可以为所欲为)。

$ ssh-keygen -t ecdsa -b 521 -C "your_email@example.com"
Generating public/private ecdsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/username/.ssh/id_ecdsa.
Your public key has been saved in /home/username/.ssh/id_ecdsa.pub.
The key fingerprint is:
dd:15:ee:24:20:14:11:01:b8:72:a2:0f:99:4c:79:7f username@localhost-2011-12-22
The keys randomart image is:
+--[ECDSA  521]---+
|     ..oB=.   .  |
|    .    . . . . |
|  .  .      . +  |
| oo.o    . . =   |
|o+.+.   S . . .  |
|=.   . E         |
| o    .          |
|  .              |
|                 |
+-----------------+

最后可以用cat命令查看生成好的秘钥。

$ cat ~/.ssh/id_rsa.pub

公钥长这样,

$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== schacon@agadorlaptop.local

把RSA秘钥托管至ssh-agent程序

因为有passphrase,每次使用私钥都要输入一遍。为了省力,可以把私钥托管到ssh-agent管理程序,它会自动和服务器端对话。 运行以下命令,在后台启动ssh-agent程序。

eval "$(ssh-agent -s)"
# Example: Agent pid 59566

然后运行下面命令,托管我们的私钥,

ssh-add -K ~/.ssh/id_rsa

Github上公开公钥

先复制我们的公钥,

$ pbcopy < ~/.ssh/id_rsa.pub
# Copies the contents of the id_rsa.pub file to your clipboard

然后到Github上的Setting里,输入公钥。

测试秘钥

ssh -T git@github.com

最后得到如下回复,说明公钥设置成功,

Hi helloShen! You've successfully authenticated, but GitHub does not provide shell access.

使用

比如我克隆一个项目到本地,

git clone git@github.com:helloShen/git-practices.git