概述
本文主要讲解通过运用HASH
算法,给用户的密码进行加密的各种方案。
对于网络传输数据(隐私数据)和 本地保存数据(隐私数据)都有一个原则,不能明文,一定是加密后的数据。最常见的就是用户的账户密码。
用户在设置密码的时候各类App
很可能是同一个密码,如果泄露问题会很严重。
密码加密策略
对于用户的密码,我们可以采用以下策略:
1. RSA
用rsa
加密网络上数据泄露的可能性低,相对来说比较安全,但是服务端的数据库中保存的是用户的真实密码(明文密码),那如果数据库泄露,所有用户密码将泄露。
所以应该有一个原则,服务端不能保存用户的明文密码,最好是开发者都不知道密码。所以用hash
再合适不过了。
2.HASH
这里有个问题是由于HASH
值相同,那么可以通过保存HASH
值找到明文。如果保存足够多常用密码的HASH
值那么通过对照一样能找到明文。
有一个网站cmd5可以直接查询:
就相当于暴力破解了,直接查表就能得到明文了。
这个网站支持的方式和数据很多,所以直接
hash
显示仍然是不安全的。
3.hash+salt
比如:
static NSString *kSaltKey = @"Hotpot";
NSString *pwd = @"123456";
pwd = [pwd stringByAppendingString:kSaltKey].md5String;
NSLog(@"%@",pwd);
这样通过查表一般就很难还原了。早期这个加盐是在注册时服务端直接将加盐后的密码哈希值保存在数据库中。这个方式对开发者依赖太大了,开发者依然知道salt
,泄露salt
后依然可以还原。
4.hmac
NSString *pwd = @"123456";
pwd = [pwd hmacMD5StringWithKey:@"Hotpot"];
NSLog(@"%@",pwd);
这里的key
和salt
有什么区别呢?本质上没有区别(hmac
两次md5
),这个key
由服务器提供(一个账号一个key
)。
这个时候整个流程如下:
- 注册的时候客户端发请求给服务端,服务端判断账号存不存在,不存在的时候服务端生成一个
key
和账号绑定在一起。 - 服务端将
key
给到客户端,客户端将密码
和key
通过hmac
计算得到hash
值返回到服务端。服务端保存这个hash
值。 - 客户端登录的时候拿这个
key
(本地,一般存储在keychain
)和密码计算得到hash
值登录。
这个时候有个问题,如果用户换了手机(没有key
了)怎么处理呢?
在换手机后先从服务端请求key
(RSA
加密),这里一般会涉及到授权(旧手机,短信,人脸等),没有key
不是认证手机不让登录。请求key
需要授权确定用户是账号的主人才给key
。
5.hmac+时间戳
虽然hmac
一般情况下获取不到明文密码了,但是仍然可以获取hamc(密码+key)
的值。如果直接用这个hash
值和服务端交互呢?
这个时候就可以用hash + 时间戳
来解决了:
hmac+时间戳
与hmac
区别:
- 加密逻辑不变,不过多了一个时间戳
- 服务端验证逻辑变了
整个过程如下:
- 客户端将
hash
值和时间戳
md5后发送给服务端。 - 服务端拿本地时间和数据库中存储的
hash
值做hash
与客户端发送的值做比对。 - 如果验证失败则拿上一分钟的时间再次验证。
这里给了1分钟
的容错。hash
值有效值时间为1分59秒
(这个时间可以自定义)。
这个时候hash
值就和时间绑定了,就相对安全了,每次加密结果不同受时间影响。
总结
-
RSA
:泄露可能想低,但是开发者知道密码,数据库有泄露可能。 -
HASH
:可能被暴力破解(查表) -
hash+salt
:盐可能泄露(这里为固定盐) -
HMAC
:比较好的方案,问题是加密后的数据有可能被截获 -
HASH+时间戳
:保证每次加密结果受时间影响,相对比较安全