对称加密和非对称加密
加密方式:
对称加密 | 非对称加密 | |
---|---|---|
原理 | 用一个钥匙去加密数据,解密时也必须使用那把用于加密的钥匙。 | 每个人都有2把钥匙,一个是公钥(可以给任何人),一个是私钥(必须自己拥有)。用公钥加密的数据,只能用私钥解密;用私钥加密的数据,只能用公钥解密。 |
算法种类 | DES,3DES,Blowfish,RC5,IDEA | RSA(加密,数字签名),DSA(只能做数字签名),Elgamal,ECC(椭圆曲线加密算法),Rabin,D-H |
优点 | 加密,解密速度快 | 1,公钥随便分发;2,可以验证是谁发的;3,只需管理自己的公钥和私钥。 |
缺点 | 1,密钥分发困难;2,无法验证是谁发的;3,要管理很多钥匙,每给一个人发,就需要一把和以前不一样的钥匙 | 解密速度和对称加密比,极慢。 |
加密解密所有时间 | 假设使用DES算法,对1G数据,加密需要4分钟,解密需要8分钟,加密后的数据变成2G。 | 假设使用RSA算法,对1G数据,加密需要1分钟,解密需要64小时,加密后的数据还是1G。 |
使用非对称加密,解决加密问题的方法:
-
案例1 :小王有公钥m,私钥n;小李有公钥x,私钥y。现在小王要给小李发送数据,要求加密,而且只有小李才能解密,如何做呢?
小王用小李的公钥x加密数据,然后把加密后的数据发送给小李,小李使用自己的私钥y可以机密,没有私钥y的人无法解密。
-
案例2:在案例1中,小李虽然能解密,但是不知道这个数据到底是不是小王发过来的。那么如何解决呢?
小王先用自己的私钥m加密数据得到data1(m(data)=data1),data1就是小王的数字签名,相当于盖了个章;然后再用小李的公钥x加密data1得到data2(data2=x(data1)),然后把data2发给小李;小李拿到数据后,先使用自己的私钥y解开data2,得到data1,然后再用小王的公钥n,解开data1,得到data。所有就实现了,既把数据加密,而且还能验证身份。
-
案例3:在案例2中,还有2个问题
- 如何得知data没有被篡改过呢,也就是如何得知数据是完整的呢?
- 如果data很大,则解密需要的时间太长了。
需要使用下面介绍的单向散列(数字摘要)的知识。
第一种解决方案:x{data+n{hash(data)}}
小王用hash运算,计算data的出hash值,在用他的私钥加密data的hash值,最后再用小李的公钥加密(data+加密过的hash值)。
- n{hash(data)是为了保证数据来源于小王。
- hash(data)是为了保证数据的完整性,没有被篡改过。
- x{data+n{hash(data)}}是为了只让小李能够解密。
这个解决方案的好处是,小王只加密data的hash值,hash值跟data比,小得多,加快了小李的解密速度。但是,还是用小李的公钥加密了data+hash值,所以小李解密还是慢。
第二种解决方案:key{data+n{hash(data)}}+x(key)
使用对称加密的方式,加密data+data的hash值;用非对称的方式加密对称加密时的密钥。
小李拿到加密数据后,先用自己的私钥y解密x(key),得到对称加密使用的key;再用此key解密key{data+n{hash(data)}},得到data+n{hash(data)},注意,此处是用对称方式解密,所以非常快;再用小王的公钥m解密n{hash(data)}得到,data的hash值(能够解开则说明来源是小王,所以来源没问题),再用同样的散列算法,计算出data的hash值,对比计算出来的hash值和解密得到的hash值是否一样,一样则说明数据没有被篡改过。而且即使别人拿到了加密的数据,由于没有小李的私钥,所以无法解密得到key。
单向散列hash算法(数字摘要)
对一个数据做hash运算,不管这个数据的大小多大,运算后的结果叫hash值,hash值都是固定长度的串。并且有雪崩效果,即使修改一点数据的内容,运算后得出的hash值都面目全非,所以无法从hash值推到出数据。
hash算法:MD5(128bits),sha1(160bits),sha224,sha256,sha384,sha512
hash(data) = digest
计算数据的hash值的命令
sha1sum sha224sum sha256sum sha384sum sha512sum sharesec
检查hash值是否发生变化:--check
[root@localhost ~]# echo 222 > f1
[root@localhost ~]# sha256sum f1 > f1.256
[root@localhost ~]# cat f1.256
8f8eea956d0ea50d6442fdab213326f75bb6f584268b0795ad452faa85db5f9d f1
[root@localhost ~]# sha256sum --check f1.256
f1: OK
[root@localhost ~]# echo 333 > f1
[root@localhost ~]# sha256sum --check f1.256
f1: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
反思yum和rpm安装包时,如何检查包的完整性的呢?如何检测来源的真实性呢?
来源真实性不用检查,因为是从官网和信得过镜像网站下载rpm,或者信得过的yum仓库。
完整性检查使用centos给提供的公钥去解密,得到hash值,然后计算包的hash值,一样的话,说明完整性没有问题。
centos的公钥在哪里呢?/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
使用:rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
导入公钥后,就可验证包的完整性了。
验证包完整性的命令:rpm -V 包名
安装包的时候,把每个安装的文件的hash值都存储起来了,所以可以使用rpm -V去检证。
验证bash,没发现问题,说明没有被修改过。
验证httpd,发现有修改过,修改过的文件也列出来了。
# rpm -V bash
# rpm -V httpd
S.5....T. c /etc/httpd/conf/httpd.conf
对称密钥如何定期更换呢?
我们知道对称密钥的很难分发,可以使用非对称方式,加密对称的密钥。还有没有别的办法?
使用DH(Deffie-Hellman)算法。
有A和B2个人,他们已经互相都有了对称密钥,现在想更换对称密钥。
1,A和B协商使用2个整数a和p,a是整数,p是大的素数
2,A生成隐私数据x,x必须小于p,计算a^x%p,把计算结果发给B(不怕别别人看到)
3,B生成隐私数据y,计算a^y%p,把计算结果发给A(不怕别别人看到)
4,A拿到y,计算[(ay%p)x]%p = a^xy%p
5,B拿到x,计算[(ax%p)y]%p = a^xy%p
6,A和B得到同样的值,就把这个值作为新的对称密钥使用。
使用gpg实现对称加密
-
加密:
gpg -c file
会弹出一个窗口,让你输入密钥,输入2次,并生成file.gpg文件。
-
解密:
gpg -o file -d file.gpg
会弹出一个窗口,让你输入密钥。解密成功的话生成file文件。
使用gpg实现非对称加密
1,在机器A上,使用gpg --list-keys
生成公钥和私钥
如果执行gpg --gen-key出现下面错误:
gpg: problem with the agent: No pinentry
gpg: Key generation canceled.
执行:unset DISPLAY
在centos6上生成时,需要敲键盘很多次,和移动鼠标,目的是生成随机数。
2,查看生成的公钥和私钥
# gpg --list-key laoyao
pub 1024R/70818978 2020-03-01
uid laoyao
sub 1024R/A9CFC54E 2020-03-01
3,导出公钥:
选项-a:导出的公钥是文本格式,不加-a则是二进制格式。
选项-o:把公钥写入到哪个文件。
选项--export:导出公钥。后面可以加名字,不加的话就是导出全部公钥。
注意名字不能加在--export后面。这里的laoyao就是公钥的名字。
# gpg -a --export -o laoyao.key laoyao
4,把公钥发给机器B
# scp laoyao.key root@192.168.56.106:/root
5,在机器B上导入在机器A上生成的公钥
# gpg --import laoyao.key
gpg: key 70818978: public key "laoyao" imported
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
# gpg --list-keys
/root/.gnupg/pubring.gpg
------------------------
pub 1024R/37772C75 2020-03-01
uid aaaaa
sub 1024R/AA509546 2020-03-01
pub 1024R/70818978 2020-03-01
uid laoyao
sub 1024R/A9CFC54E 2020-03-01
6,使用机器A的公钥laoyao,加密机器B上的某个文件
选项-r就是指定使用哪个key加密,加密后生成f1.gpg文件。
# gpg -e -r laoyao f1
gpg: A9CFC54E: There is no assurance this key belongs to the named user
pub 1024R/A9CFC54E 2020-03-01 laoyao
Primary key fingerprint: AEBA F8F6 7C61 5593 63FD F148 A323 ACB1 7081 8978
Subkey fingerprint: DF89 C575 1EAB 9112 5CFC 6C56 E23F C200 A9CF C54E
It is NOT certain that the key belongs to the person named
in the user ID. If you *really* know what you are doing,
you may answer the next question with yes.
Use this key anyway? (y/N) y
# ll f1*
-rw-r--r--. 1 root root 12 Mar 1 16:20 f1
-rw-r--r--. 1 root root 213 Mar 1 16:21 f1.gpg
7,把f1.gpg传给机器A
# scp f1.gpg root@192.168.56.107:/root
8,在机器A上解密:
# gpg -o f1 -d f1.gpg
gpg: encrypted with 1024-bit RSA key, ID A9CFC54E, created 2020-03-01
"laoyao"
[root@localhost ~]# cat f1
aaa
ddd
ddd
- 删除公钥:
gpg --delete-keys BBBBB
- 删除私钥:
gpg --delete-secret-keys BBBBB