加密
在登录逻辑中,我们常常需要把用户的密码传给后台,但是这样对于用户是非常不安全的。之前有小伙伴在做登录的时候直接把密码加盐做MD5加密之后传给后台,后台存MD5加密之后的密码。看上去好像比较安全,但是MD5虽然是非对称的散列算法,理论上是不能反查询的,可实际上对于简单的密码(字母+数字)在网上可以很简单的通过反查询得到(www.cmd5.com)
对于加盐,通过砸壳和汇编反编译等手段也很容易拿到(很多的盐的字段名为salt,通过反编译工具直接就能看到)所以这种方法还是存在很大的安全隐患的。
虽然说对于黑客来说基本上没有不能破解的密码,但是难度越大,他们的收益就越小就越安全。
总结一下以上方案危险的地方:
1、盐容易被反编译拿到
2、盐开发人员知道,有信息泄漏的危险
3、MD5通过反查询可以很容易的拿到加密之前的内容
4、甚至直接拦截登录请求字段,并用这些字段模拟登录,可以直接登录
5、有的同学会觉得https 很安全,但是通过逆向工程,可以在数据发送之前就拿到想要的数据(这也是为什么很多大公司的核心代码要求使用c函数,c函数在逆向工程中只能看到函数地址,而oc方法可以看到方法名称)所以,该加密的地方还是要加密的!!!
下面说一下修改之后的加密方案
HMAC + 时间 + 盐
HMAC:原密码+字符串进行MD5加密,加密之后的结果+原密码进行一次MD5计算
具体步骤:
//1、一个字符串key MD5计算
NSString * key = @"mykey";//这个key要和服务器上的key一样(相当于公钥)
NSString * keyStr = [key md5String];
//2、把原密码和之前生成的MD5值进行hmac加密
NSString * hmacStr = [pwd hmacMD5StringWithKey:keyStr];
//3、从服务器获取当前时间(到分钟)的字符串
NSString * timeStr = [self getTimeStr];//这个方法需要用同步请求,不能使用异步请求
//4、第二部产生的hmac值+时间 和第一步产生的md5值进行hamc加密
NSString * hamcAndTimeStr = [hmacStr stringByAppendingString:timeStr];
return [hamcAndTimeStr hmacMD5StringWithKey:keyStr];
这个方案中使用了两次的hmac加密算法,大大增加了破解的难度。而且加入了时间(有效时间2分钟,过期无效)即时黑客拿到请求的数据,模拟请求也容易失效。
在实际开发中,time字段可以用验证码等具有时效性的字段代替
上面用到的加密算法可以直接百度“NSString+Hash”很容易找到
很多应用在应用平时请求的时候要求把token放在请求头中带过去,这里的token也需要做一定的加密处理,不能只用MD5加密就传过去可以参考hmac加密方法。
密码本地化处理
直接将密码存储到本地是不安全的,通过砸壳,逆向工程等都可以拿到对应的数据
所以,将密码等敏感信息存入本地的时候需要做加密处理
推荐方法:使用系统提供的钥匙串功能可以在本地保存密码,系统使用AES的方式对密码进行加密
第三方框架:SSKeychain
//把密码保存到钥匙串中
[SSKeychain setPassword:@"pwdStr" forService:[NSBundle mainBundle].bundleIdentifier account:@"userName"];
//从钥匙串中获取密码
NSString * pwd = [SSKeychain passwordForService:[NSBundle mainBundle].bundleIdentifier account:@"userName"];
这样就可以将用户名对应的密码存入系统的钥匙串中,而且是每个用户名对应的密码都是单独的。
对于用户的敏感信息,也可以通过钥匙串的方式存入本地。