在 密码学之RSA加密算法 中,咱们了解了 非对称加密算法 (典型的表明是 RSA算法)的基本原理,而且使用终端简单地体验了一下RSA算法的操做流程。而 Hash算法 和 对称加密算法 也是现代密码学体系中的重要组成部分。接下来,咱们将一一介绍下它们。算法
Hash,通常翻译作散列、哈希,是把任意长度的输入经过Hash算法变成固定长度的输出,该输出就是Hash值(哈希值,或散列值)。这种转换是一种压缩映射,也就是,哈希值的空间一般远小于输入的空间,不一样的输入可能会Hash成相同的输出。简单的说Hash就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。安全
Hash算法也被称为散列算法、哈希算法,虽然被称为算法,但实际上它更像是一种思想。Hash算法没有一个固定的公式,只要符合Hash思想的算法均可以被称为是Hash算法。bash
因为Hash是无限集的数据向有限集的单方向映射,因此不免会出现:对不一样的数据可能获得相同的Hash值,这种现象称为 哈希碰撞,或称 散列碰撞。以下图所示:服务器
黑客攻击的一种方法,就是设法制造【哈希碰撞】,从而破解用户的密码,窃取用户的信息。并发
X个二进制位的Hash值,产生碰撞的可能性是 2X 分之一。如函数
16个二进制位的Hash值,产生碰撞的可能性是 65536 分之一;
32个二进制位的Hash值,产生碰撞的可能性是 4,294,967,296 分之一。post
因而可知,有效地防止哈希碰撞的方法,就是 扩大Hash值的取值空间。固然,更长的哈希值意味着更大的存储空间、更多的计算,这将影响性能和成本。实际应用中,开发者必须作出抉择,在安全与成本之间找到平衡。性能
全部Hash函数都有一个基本特性:若是两个哈希值是不相同的(根据同一函数),那么这两个哈希值的原始输入也是不相同的。这个特性是散列函数具备肯定性的结果。反之则否则,即 若是两个哈希值相同,两个输入值极可能是相同的,但不绝对确定两者必定相等(可能出现哈希碰撞)。网站
Hash函数还有如下一些特色:ui
Hash函数能使对一个数据序列的访问过程更加迅速有效,经过Hash函数,数据元素将被更快地定位。
说到Hash,就不得不提到一些著名的Hash算法。在众多Hash算法中,MD五、SHA一、SHA256能够说是应用最普遍的了,而它们都是以MD4为基础设计的。下面简单介绍一下这几个Hash算法:
MD4是MIT的 Ronald L. Rivest 在1990年设计的,MD是Message Digest(消息摘要)的缩写。它是基于32位操做数的位操做来实现的。
MD5是 Rivest 于1991年对MD4的改进版本。MD5比MD4复杂,速度要慢一点,但更安全,在抗分析和抗差分方面表现更好。
SHA1是由 NIST NSA 设计为同DSA一块儿使用的,它对长度小于2^64的输入,产生长度为160bit的Hash值,所以抗穷举性更好。但在相同的硬件上,SHA1较MD5会稍慢一些。
SHA256是SHA1的后继者,对于任意长度的消息,SHA256都会产生一个256位长的Hash值。与SHA1相比,SHA256的抗穷举性更好,但速度则慢一些。
Hash算法普遍应用于 错误校订、语音识别、信息安全 中,其在信息安全的应用主要体如今如下几个方面:
即校验文件是否被篡改。
因为非对称算法的运算速度较慢,因此在数字签名协议中,先对文件进行运算获得其Hash值(其Hash值又被称为【数字摘要】),而后对数字摘要进行数字签名,在统计上认为与对文件自己进行数字签名是等效的。
以下的鉴权协议又被称做挑战--认证模式:在传输信道是可被侦听,但不可被篡改的状况下,这是一种简单而安全的方法。
注意:
Hash算法加密的对象是 文件的二进制内容,只要文件的二进制内容没发生改变,其Hash值不变。
如,假设有一张文件名为【001.png】的图片,更名为【002.txt】,比较其更名先后md5值是否发生改变;将其压缩后,再试试看
在实际运用中,服务器是不会保存用户密码的,从安全角度考虑,App不会有【找回密码】功能,有的只是【重置密码】。那么,用户注册时,客户端发给服务器的密码是怎样的呢?
接下来,咱们以MD5加密算法为例,探讨一下对密码进行怎样的处理才能使其足够安全。
思考:直接将【e10adc3949ba59abbe56e057f20f883e】做为【密码】发给服务器能够吗?
因为Hash的特色:对相同数据的Hash运算,获得的结果是同样的。所以,只要有足够多的这种明文密文对应关系的数据,利用穷举字符组合的方式,是能够反向查询到原始数据的。实际上,提供这种服务的网站有不少。这里向你们介绍一个做者本身经常使用的:MD5在线加密解密。接下来反向查询一下:
这里可能会有读者有疑问,只要用户将密码设置得足够复杂(多种类型字符混排之类),应该就不会这么简单被反向查询到吧。的确如此,可是密码的安全不该该寄但愿于用户的【自主行为】。
思考,【盐】泄露了怎么办?
密钥K是随机选取的(每一个用户的密钥K都是随机值),能够采用一种强伪随机发生器,而且密钥须要周期性更新。
当用户注册时,将原始密码进行上述【1】或【2】处理后,发给服务器,服务器为该用户生成一个密钥K,将其发给客户端的同时,对用户密码和密钥K再进行MD5运算。客户端会将密钥K保存到本地,之后每次登陆都对密码通过HMAC加密方案处理后,再将结果发给服务器校验。代码以下:
static NSString *salt = @"sdfSD_FHja%(";
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSString *pwd = @"123456";
pwd = [salt stringByAppendingString:pwd].md5String;
NSLog(@"加盐后的密码是:%@", pwd);
// 假设本地保存的密钥K为"Um7f1ltAibSF!$w@8"
NSString *key = @"Um7f1ltAibSF!$w@8";
pwd = [pwd hmacMD5StringWithKey:key];
NSLog(@"如今的密码是:%@", pwd);
}
复制代码
其结果为
反查询一下
注意:
思考:上述对密码的三种处理,均将最终密码发送给服务器,这样作有没有什么隐患?
即在请求登陆以前,能够向服务器请求最新时间(如201910230836,精确到分),再进行相似这样的处理:(HMAC哈希值+"201910230836").md5,将其发送给服务器,服务器再进行校验,若是密码有效期小于2分钟,则先校验当前时间下的值(假设过了1分钟):
(HMAC哈希值+"201910230837").md5
若是不匹配,再校验前1分钟的值:
(HMAC哈希值+"201910230836").md5
毫无疑问,在这种机制下,客户端登陆的密码具备时效性,其有效时间越短安全性越强。
接下来谈一谈Hash在信息安全上的应用。设想一个这样的场景:
假设你要买一件10块钱的商品,你在客户端将订单信息发送给服务端,请求支付;
黑客窃取了你的订单信息,并将金额改为20元,而后发送给服务端;
服务端扣了你20元,同时生成消费信息,并发送给你;
黑客窃取了消费信息,又将金额改为10元,继续发送给你;
你收到了这10元的消费信息。
在这个过程当中,黑客神不知鬼不觉地篡改了你提交的信息,形成了你的损失。那么该如何保护你的信息的完整性呢?这就要用到数字签名技术了。
数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人没法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证实。它是一种相似写在纸上的普通的物理签名,可是使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名一般定义两种互补的运算,一个用于签名,另外一个用于验证。数字签名是 非对称密钥加密技术 与 数字摘要技术 的应用。
- 关于非对称加密算法的介绍,不熟悉的同窗请移步 密码学之RSA加密算法
- 数字摘要是将任意长度的消息变成固定长度的短消息。是否是很熟悉?其实就是Hash。数字摘要就是采用Hash算法将【明文】输出为一串固定长度(如128位)的密文,这一串密文又称为数字指纹。
通常来讲,非对称加密是用来处理短消息的,而相对于较长的消息则显得有些吃力。固然,能够将长的消息分红若干小段,而后再分别签名。不过,这样作很是麻烦,并且会带来数据完整性的问题。比较合理的作法是在 数字签名前对消息先进行数字摘要。
一样是上述的场景,结合数字签名技术以后,其流程以下:
- 当你发起10元的支付订单信息时,客户端用Hash算法(如MD五、SHA1等)将此订单信息加密生成【数字摘要】,同时用服务端的 公钥 对数字摘要进行加密,这个加密后的摘要也就是【数字签名】;
- 客户端将【订单信息】和【数字签名】一块儿发给服务端;
- 服务端收到后,用 私钥 解析数字签名,获得【数字摘要1】,同时,再对【订单信息】用一样的Hash算法(约定好的)加密生成【数字摘要2】,进而匹配数字摘要1和数字摘要2:若是一致,说明订单信息是完整真实的,能够进行扣款;不然说明订单信息被篡改,订单无效。
数字签名是个加密的过程,数字签名验证是个解密的过程。
PS. 咱们使用的支付宝,其支付过程就使用了数字签名技术进行安全验证。
总结:数字签名有两种功效
- 能肯定消息确实是由发送方签名并发出来的,由于别人假冒不了发送方的签名。
- 能肯定消息的完整性。由于数字签名的特色是它表明了文件的特征,文件若是发生改变,数字摘要的值也将发生变化。
使用相同的密钥对信息进行加密和解密,这种加密方式叫作 对称加密。也就是说,就是明文经过密钥加密获得密文,密文经过密钥加密获得明文。
让咱们简单比较一下 非对称加密、Hash 和 对称加密
- 非对称加密用于加密少许数据,加密效率低,可是很是安全。
- Hash用于信息识别,验证信息的真伪和完整性
- 对称加密用于加密大量数据,加密速度快、效率高,可是一旦密钥泄露,密文将毫无安全性可言。
经常使用的对称加密算法有
特色:强度小、速度较快,
特色:强度较DES高一些,速度也快。可是三个密钥不便于管理,所以用得也少。
特色:速度快,安全级别高;
PS. 苹果的钥匙串访问、美国国家安全局等都是用AES。若是你想玩对称加密,也建议用AES。
主要有两种应用模式,即ECB和CBC。
最基本的加密模式,也就是一般理解的加密,相同的明文将永远加密成相同的密文,无初始向量,容易受到密码本重放攻击,通常状况下不多用。
- 明文被加密前要与前面的密文进行异或运算后再加密,所以只要选择不一样的初始向量,相同的密文加密后会造成不一样的密文,这是目前应用最普遍的模式。
- CBC能够有效的保证密文的完整性,若是一个数据块在传递是丢失或改变,后面的数据将没法正常解密。
- 它的主要缺点在于加密过程是串行的,没法被并行化,并且消息必须被填充到块大小的整数倍。
- 常应用于防窃听技术中。
接下来,咱们用终端来玩一玩对称加密算法。操做流程以下:
openssl enc -aes-128-ecb -K 616263 -nosalt -in message.txt -out msg1.bin
复制代码
参数说明:
- enc:表示是对称加密
- -K:密钥K值为616263(其实是abc,即0x610x620x63)
- -nosalt:不加盐(openssl会随机加盐,此处不须要)
- -out:加密后的密文输出到msg1.bin文件中
显而后面的数据块并不受到前面数据块内容改变的影响,充分说明ECB模式是每一块数据进行独立加密。
openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -in message.txt -out msg3.bin
复制代码
参数说明:
- -iv:初始化向量值为0102030405060708(随机取的)
显而后面的数据块受到了前面数据块内容改变的影响,充分说明了CBC能够有效的保证密文的完整性,即若是一个数据块在传递是丢失或改变,后面的数据将没法正常解密。