转自:
https://www.cnblogs.com/mddblog/p/5380556.html
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0015108777177966ef0f4f8510a41b3b8c48cdcf7047b2d000
一、 密码概述
发送者对明文进行加密然后生成密文,接受者再对密文解密得到明文的过程。 现在使用的所有加密算法都是公开的!但是密钥肯定不是公开的。
1 散列(哈希)函数
- 通常有MD5、SHA1、SHA256、SHA512
- 实质是抽取特征码,这样一般不会重复!是的,不同的文本它的哈希结果是有可能相同的,但概率很小。
(举例:比如想要识别一个人,我们可以通过他的指纹来锁定他,指纹出现相同的概率很低吧!在这里,人就相当于数据,而指纹就相当于对人这个数据进行hash后得到的结果) - 对任意大小的一个文件或任意长度的一段数据进行哈希,可以得到定长的字符串结果,例如MD5哈希结果是128位,以32个字符的十六进制格式输出
(md5,其实就是一中算法。将一个字符串,或文件,或压缩包,执行md5后,就可以生成一个固定长度为128bit的串。这个串,基本上是唯一的)
- 还有就是不可逆的,既然是不可逆的,那么当然不是用来加密的,而是签名
哈希值在HMAC身份验证机制中用得比较多
2 对称加密算法
- 有DES、3DES、AES
- 加密和解密使用同一个秘钥,加密解密的速度快
- 适合给大数据进行加密
- 密钥的安全性非常重要
3 非对称加密算法:
RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法),其中 RSA使用最为广泛,Elgamal和ECC也很常用
- 使用
公钥
加密,使用私钥
解密 - 使用
私钥
加密,使用公钥
解密(私钥签名,公钥验签) - 更安全,当然速度会慢下来,如果随着硬件的突破,使用越来越多,特别是支付
1是对数据加密,2是防止伪造客户端数据,对服务器攻击,更重要是防止模拟了客户端,进行支付相关的操作
注意: 公钥是由私钥经一系列不可逆的hash运算等到的.
4 对称加密与非对称加密的区别
就个人理解,最主要的就是密钥的不同,对称加密客户端和服务端使用同一个密钥,非对称加密使用不同的密钥。
客户端的代码是很容易被破解的,IDA、hopper disassembler
工具的使用,使得破解更加简单而且破解后容易阅读,再配合Charles抓取网络包,根据关键字很容易就定位到加密代码,然后获取密钥。
由于对称加密密钥一样,所以解密就轻而易举;但是非对称加密就不会出现这种问题,因为服务端和客户端的密钥不一样,公钥加密私钥解密,加密的公钥也是公开的,而私钥一般放在服务端,黑客一般是拿不到的。
另外就是没有密钥情况下强制暴力破解,非对称加密也要比对称加密花的多的多的时间来破解。一条信息就要花你几年的时间,所以很安全。
二、加密与签名区别(RSA)
- 最大的区别是,加密是可逆的,而签名是不可逆的。
比如对于"Hello world!"
进行加密后得到结果R,还可以使用密钥通过结果R解密得到"Hello world!"
;而对"Hello world!"
进行签名得到结果R,却不能使用密钥通过R获得"Hello world!"
,要不然的话压缩算法要逆天了!比如hash,使用几十个字符就能存储几G几T的数据。。。
- 加密是对数据进行机密性保护,签名主要用于身份验证
比如A对B发送了信息Message;通过加密后,即便C通过网络包截取获得了Message,它也不知道里面的具体内容,只能看到一堆乱码;通过签名,假设D也用相同的加密算法发送了此Message,但是签名错误,那么B通过签名依然拒绝D的Message。
- 以当前使用的比较多的RSA为例举例:
假设A、B双方均拥有一对公私钥(PUB_A
、PRI_A
、PUB_B
、PRI_B
)。
A向B发送Message的整个签名和加密的过程如下:
- A先使用HASH对Message生成一个固定长度的信息摘要
Message_hash_A
- A使用A的私钥
PRI_A
对Message_hash_A
进行签名得到Message_sign
(这里为什么不直接对Message进行签名,而要对Message_hash_A
进行签名呢?因为Message的长度可能很长,而Message_hash_A
的长度则是固定的,这样性能更高,格式也固定,况且hash的结果一般不会出现重复的可能) - A接着使用B的公钥
PUB_B
对信息Message
和信息Message_sign
进行加密得到Message_RSA
,这时A将Message_RSA
发送给B。
当B接收到A的信息Message_RSA
后,获取Message
的步骤如下:
- B用自己的私钥
PRI_B
解密得到明文:Message
和Message_sign
; - 然后B使用A的公钥
PUB_A
解Message_sign
得到Message_hash_A
;同时,B再对Message
使用与A相同的HASH得到Message_hash_B
; - 如果
Message_hash_A
与Message_hash_B
相同,则说明Message
没有被篡改过。
上面的过程中,A知道A的公私钥同时也要知道B的公钥;同理B要知道A的公钥和B的公私钥
关于公私钥再打个比方:公钥
就像一把锁一样将数据锁住;私钥
就像钥匙一样,能将对应的锁打开。
公钥加密,私钥解密的好处是:公钥可以公开,那么无论谁有公钥都可以给你发送信息,而且也只有你才能解密
我们经常使用的Github就是使用了签名的方法,SSH,在本地电脑生成一对公私钥,将公钥传到github,然后使用私钥进行签名,github通过公钥延签后认为你的身份合法。
另外,加密和编码是不一样的,比如ASCII是属于编码,是将0~255与字符一一对应。
A发给B的报文即使被C截获,C对数据进行了篡改,但C没有A的密钥,没办法对篡改后的数据进行签名,B收到报文后,发现签名对不上,就会发现数据被篡改
三 带密哈希 HMAC
1.hmac原理
通过哈希算法,我们可以验证一段数据是否有效,方法就是对比该数据的哈希值,例如,判断用户口令是否正确,我们用保存在数据库中的password_md5
对比计算md5(password)
的结果,如果一致,用户输入的口令就是正确的。
为了防止黑客通过彩虹表根据哈希值反推原始口令,在计算哈希的时候,不能仅针对原始输入计算,需要增加一个salt来使得相同的输入也能得到不同的哈希,这样,大大增加了黑客破解的难度。
如果salt是我们自己随机生成的,通常我们计算MD5时采用md5(message + salt)
。但实际上,把salt看做一个“口令”,加salt的哈希就是:计算一段message的哈希时,根据不通口令计算出不同的哈希。要验证哈希值,必须同时提供正确的口令。
这实际上就是Hmac算法:Keyed-Hashing for Message Authentication。它通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。
和我们自定义的加salt算法不同,Hmac算法针对所有哈希算法都通用,无论是MD5还是SHA-1。采用Hmac替代我们自己的salt算法,可以使程序算法更标准化,也更安全。
Python自带的hmac模块实现了标准的Hmac算法。我们来看看如何使用hmac实现带key的哈希。
我们首先需要准备待计算的原始消息message,随机key,哈希算法,这里采用MD5,使用hmac的代码如下:
import hmac message = b'Hello, world!' key = b'secret' h = hmac.new(key, message, digestmod='MD5') # 如果消息很长,可以多次调用h.update(msg) h.hexdigest() 'fa4ee7d173f2d97ee79022d1a7355bcf'
可见使用hmac和普通hash算法非常类似。hmac输出的长度和原始哈希算法的长度一致。
使用hmac算法比标准hash算法更安全,因为针对相同的message,不同的key会产生不同的hash
2. hmac使用