前言
本篇文章,将继续讲解密码学算法的另一个算法 👉 HASH
算法。
一、加密策略
在讲解HASH之前,我们来分析一下加密的策略
。
我们都知道,对于网络传输数据(隐私数据)
和 本地保存数据(隐私数据)
都有一个原则 👉 不能明文,一定是加密后的数据
。最常见的就是用户的账户密码
。对于用户的密码,我们可以采用以下策略👇
- RSA
用rsa加密
网络上数据泄露的可能性低
,相对来说比较安全
,但是服务端的数据库中保存的是用户的真实密码(明文密码)
,那如果数据库泄露
,所有用户密码将泄露
。
所以应该有一个原则 👉 服务端不能保存用户的明文密码,最好是开发者都不知道密码
。这时用hash
再合适不过了。
- HASH
HASH
也有个问题 👉 是由于HASH
计算后值相同
,那么可以通过保存HASH值
找到明文
。如果保存足够多
常用密码的HASH值
,那么就能通过对照(映射)
一样能找到明文
。
例如,有一个网站cmd5可以直接查询👇
这就是暴力破解
了,直接查表
就能得到明文
了。并且这个网站支持的方式和数据很多,所以直接hash显示仍然是不安全的
。
- HASH+salt
static NSString *kSaltKey = @"LGPerson";
NSString *pwd = @"123456";
pwd = [pwd stringByAppendingString:kSaltKey].md5String;
NSLog(@"%@",pwd);
通过加盐
,在注册时服务端直接将加盐后的密码哈希值
保存在数据库
中。这个方式对开发者依赖
太大了,开发者
知道salt
,泄露salt
后依然可以还原
。
- hmac
NSString *pwd = @"123456";
pwd = [pwd hmacMD5StringWithKey:@"LGPerson"];
NSLog(@"%@",pwd);
这里的key
和salt
有什么区别呢?本质上没有区别
(hmac两次md5),这个key
由服务器提供
👉 一个账号一个key
。
此时流程👇
- 注册的时候客户端发请求给服务端,
服务端
判断账号存不存在
,不存在
的时候服务端
生成一个key和账号绑定
在一起。 - 服务端将
key
给到客户端,客户端将密码和key
通过hmac计算
得到hash值
返回到服务端。服务端保存
这个hash值
。 - 客户端登录的时候拿这个
key(本地,一般存储在keychain)
和密码
计算得到hash值
登录。
整个过程如下图👇
此时,又有问题来了 👉 如果用户换了手机(没有key
)怎么处理呢?
在换手机后先从服务端请求key
(RSA加密),这里一般会涉及到授权
(旧手机短信,人脸等),没有key
则不是认证手机不让登录
。请求key
需要授权
(确定用户是账号的主人)才给key
。
- hmac+时间戳
虽然hmac
一般情况下获取不到明文密码
了,但是仍然可以获取hamc(密码+key)的值
。如果直接用这个hash值
和服务端交互
呢?是不是也会有风险。此时怎么处理呢?这个时候就可以用hash + 时间戳
来解决了👇
hmac+时间戳
与hmac
区别
-
加密逻辑
不变,不过多了一个时间戳
- 服务端
验证逻辑
变了
此时流程👇
- 客户端将
hash值和时间戳
md5后发送给服务端。 -
服务端
拿本地时间
和数据库中存储的hash值
再做hash运算
,与客户端
发送的值做比对
。 - 如果
验证失败
则拿上一分钟的时间
再次验证。这里给了1分钟
的容错。hash值有效值时间
为1分59秒
(时间可以自定义
)。
这个时候hash值就和时间绑定了,就相对安全了,每次加密结果受时间影响
。
二、HASH
2.1 概述
Hash一般翻译做“散列”,也直接音译为“哈希”,就是把任意长度
的输入通过散列算法
变换成固定长度
的输出,该输出就是散列值
。这种转换是一种压缩映射
,也就是,散列值的空间通常远小于输入的空间,不同的输入
可能会散列成相同的输出
,所以不可能
从散列值来确定唯一
的输入值。
简单的说就是 👉 一种将任意长度的消息压缩到某一固定长度的消息摘要(指纹)的函数。
常见的HASH算法有👇
- MD5
- SHA1、256、512
2.2 特点
- 算法是
公开
的 - 对相同数据运算得到的
结果是一样
的 - 对不同数据运算,如MD5得到的
结果
默认是128位
,32个字符(16进制标识)
。 - 无法逆运算。(那么则
无法做加密
) - 信息摘要,信息指纹,用来做
数据识别
。
为什么无法逆运算?
比如对数据进行MD5运算得到的结果是128位
,也就是能表达的数据是1632种
(有限),那么由于数据(无限)
。这里必然有多个数据拥有同样的hash值(散列碰撞)
。
2.3 用途
- 对用户密码的加密,这个上面说过
- 搜索引擎
比如:iOS Swift
和Swift iOS
搜索出来的结果可能相同。这里词有hash
值,将多个词的hash
值拿到加到一起。 - 版权
任意文件都会生成一个hash
值。上传平台后平台会保存原始文件hash
值。别人下载的文件不是原文件(平台生成)。这个时候平台就可以通过原文件hash
来区分确定版权问题了。 - 网盘
数据识别-hash
- 数字签名
数字签名
接下来重点看看数字签名
。因为国外喜欢用支票
,支票上面的签名能够证明身份
。数字签名顾名思义,就是用于鉴别数字信息
的方法,确认二进制是不是原始机构签发
的。
- 对
二进制数据
计算hash值
。 - 签发方对
hash值
进行rsa加密
。 - 接收方
解密获取hash值
,并且对二进制文件
计算hash值
,hash值相同
则证明是原始
文件。
其中,对hash值进行rsa加密
后的数据,就叫做这个二进制文件的数字签名
。
2.4 终端演示
2.4.1 HASH
md5
// 字符串
md5 -s "LGPerson"
//文件
md5 message.txt
上图返回32个字符
的MD5散列字符串
。
sha1
//字符串
echo -n "LGPerson" | openssl sha1
//文件
openssl sha1 message.txt
上图返回40个字符
的SHA1散列字符串
。
sha256
//字符串
echo -n "LGPerson" | openssl sha256
//文件
openssl sha256 message.txt
SHA256散列字符串
是64个字符
。
sha512
//字符串
echo -n "LGPerson" | openssl sha512
//文件
openssl sha512 message.txt
SHA512散列字符串
是128个字符
。
2.4.2 HMAC
hmac md5
echo -n "LGPerson" | openssl dgst -md5 -hmac "key"
返回32个字符
的HMAC MD5散列字符串
。
hmac sha1
echo -n "LGPerson" | openssl sha1 -hmac "key"
返回40个字符
的HMAC SHA1散列字符串
。
hmac sha256
echo -n "LGPerson" | openssl sha256 -hmac "key"
返回64个字符
的HMAC SHA256散列字符串
。
hmac sha512
echo -n "LGPerson" | openssl sha512 -hmac "key"
返回128个字符
的HMAC SHA256散列字符串
。
读者可自行验证,这里就不再演示了。
2.5 代码演示
iOS中HASH
加密解密框架是CommonCrypto
。
//string
NSString *message = @"LGPerson";
NSString *key = @"key";
NSLog(@"string md5: %@",[message md5String]);
NSLog(@"string sha1: %@",[message sha1String]);
NSLog(@"string sha256: %@",[message sha256String]);
NSLog(@"string sha512: %@",[message sha512String]);
NSLog(@"string hmac md5: %@",[message hmacMD5StringWithKey:key]);
NSLog(@"string hmac sha1: %@",[message hmacSHA1StringWithKey:key]);
NSLog(@"string hmac sha256: %@",[message hmacSHA256StringWithKey:key]);
NSLog(@"string hmac sha512: %@",[message hmacSHA512StringWithKey:key]);
//文件
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"message" ofType:@"txt"];
NSLog(@"file md5: %@",[filePath fileMD5Hash]);
NSLog(@"file sha1: %@",[filePath fileSHA1Hash]);
NSLog(@"file sha256: %@",[filePath fileSHA256Hash]);
NSLog(@"file sha512: %@",[filePath fileSHA512Hash]);
运行👇
示例代码
XFCryptor的NSString+Hash分类
。
总结
-
加密策略
-
RSA
👉 泄露可能性低,但是开发者知道
密码,数据库
有泄露
可能 -
HASH
👉 可能被暴力破解
(查表) -
HASH+salt
👉 盐可能泄露(这里为固定盐
) -
HMAC
👉 比较好的方案,问题是加密后的数据有可能被截获
-
HASH+时间戳
👉 保证每次加密结果受时间
影响,相对比较安全
-
-
HASH
- 特点:
- 算法公开
- 不可逆运算(多对一)
- 相同数据加密结果相同
- 不同长度数据加密结果定长
- 一般用于数据的识别(密码,版权,网盘)
- 用途:
- 密码加密,详见
加密策略
- 搜索引擎
- 版权
- 网盘
- 数字签名
- 算法:HASH+RSA
- 目的:验证数据的完整性不被篡改
- 逻辑:
- 原始数据进行Hash
- 使用RSA机密HASH值(这部分数据就是原始数据的数字签名)
- 将原始数据+数字签名一起发送传递(客户端使用公钥解密验证)
- 密码加密,详见
- 特点:
网友评论