阅读 778

iOS逆向 hash理论

欢迎阅读iOS逆向系列(按序阅读食用效果更加)

一、hash

1. 什么是hash?

Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值

简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数

2. hash的特点

  • 算法是公开的
  • 对相同数据的运算结果是一样的
  • 对不同数据的运算结果是定长的,默认是128位,32个字符
  • 无法进行逆运算(取决于hash的底层原理——单方向映射)
  • 信息指纹,常用来作数据识别

既然hash的运算结果是定长的,那么必然会出现多个数据的hash相同的情况,这被叫做散列碰撞

3. hash的用途

  • 用户密码的加密
    • hash算法是一个单向函数。它可以将任何大小的数据转化为定长的“指纹”,并且无法被反向计算。另外,即使数据源只改动了一丁点,哈希的结果也会完全不同
  • 数字签名(将在本文第三章讲到)
  • 搜索引擎
    • “中国”、“浙江”、“广厦”这三个词无论排列顺序怎么变化,搜索的结果都是一样的,因为这是将这三个词的128位hash值进行相加,结果都是一样的
  • 版权
    • 如百度云的秒传功能,你在百度云上传一份文件,百度云会先判断网盘上是否有和它一样的hash值,如果有的话,再判断文件类型、二进制前后两百位是否一样..(具体咱也不清楚)等等。如果都满足的话认为是同一份数据实现秒传

又如接下来的操作: 一张图片名为“001.png”的图片用终端命令md5 001.png"输出的hash值为

MD5 (001.png) = 794f38b127db2e24e23a59d1fcb7a700
复制代码

修改名字+后缀名为“md5 002.mp3”,终端命令md5 002.mp3"输出的hash值为

MD5 (002.mp3) = 794f38b127db2e24e23a59d1fcb7a700
复制代码

修改回“001.png”,Ctrl+C Ctrl+V复制一份图片,命名为“002.png”,终端命令md5 002.png"

MD5 (002.png) = 794f38b127db2e24e23a59d1fcb7a700
复制代码

将图片打包成“001.zip”,终端命令md5 001.png.zip

MD5 (001.png.zip) = eca9687c64a1a62154582186214a97be
复制代码

上述操作得出几个结论: ① 修改文件名或后缀名不会改变其二进制(hash值),后缀名其实是给操作系统看的——让操作系统判断用什么软件打开它 ② 复制粘贴的本质是对二进制的复制粘贴 ③ 只有压缩操作才会改变二进制

由于hash运算的不可逆,让它在很多领域都大放异彩

二、 hash在加密用户密码中的方案

1. 明文请求

如果直接用明文传输密码,黑客能直接抓取到网络请求,用户密码会“一丝不挂”的出现在黑客面前;又如果使用RSA加密传输,客户端加密服务器解密,岂不是美滋滋?但是用户密码还是会明文保存在服务器端,这样是很不安全的!!! 互联网有两个原则:① 网络传输不允许明文传递用户隐私信息;② 本地不允许明文保存用户隐私信息

2. 直接MD5加密/多次MD5加密

那么直接使用MD5加密用户密码呢?或许很多小型外包就是这么处理的,但这种方案也是很不全的,因为hash算法是不可逆的。只要穷举千千万万种hash算法的结果,然后再进行反向查询,用户的密码也会轻而易举会拿到,比如www.cmd5.com/这个网站

那我们再尝试尝试多次MD5呢?其实也是一样的,CMD5这个网站可以选择类型进行反向查询,多次嵌套并不管用

3. 加固定盐

加盐是什么意思呢?就是在用户的明文密码后面加一点“作料”——一串奇奇怪怪的字符串,然后再做hash运算,比如“123456da.gjio1ra”再做MD5运算发送给服务器。 这种方案的用户密码不能简单快速的破译出明文密码,但是也能通过暴力破译。与之同时带来一系列的危害:破译出明文密码,也就知道了盐,因为盐是写死的,那么所有用户的密码也都可以轻而易举的破译出来,所以在这种方案中对“盐”的保护尤为重要。其次,各个客户端、服务器都知道“盐”的具体内容,那公司能保证所有开发工程师离职了不透露出去吗?我们做开发的应该做到尽善尽美,不能让这些人为因素影响我们的app安全! 既然写死“盐”不行,那么我们可以用动态盐来解决问题

4. HMAC

HMAC是使用一个密钥加密,并且做两次散列运算,得到一个hash值。它是一种方案,不是加密算法。在实际开发中HMAC的密钥来自于服务器,是随机的,每个账号各不相同 接下来通过多种登录情况理一下登录逻辑:

① 注册

a. 用户在客户端填写好账号、密码等信息后点击注册,开始注册请求,并将账号Feng发送给服务器

b. 服务器对账号Feng进行校验,如果可用的话,随机生成一个密钥key发送给客户端

c. 客户端对进行HMAC,再将账号+密码发送给服务器,服务器将账号Feng+密钥key+密码hmac一一对应保存。然后返回注册成功的请求结果,客户端就能将密钥key存储起来了

这样子一个账号对应一个密钥,大大提高了登录安全性。但是想一下万一用户换了台设备登录,那不是拿不到key了?所以我们还得丰富一下我们的登录逻辑

② 换设备登录

a. 用户在客户端填写好账号、密码等信息后点击登录,客户端现在本地查找账号对应的密钥,如果本地有对应的key直接走c,如果没有的话将账号Feng发送给服务器并请求密钥key

b. 服务器对账号Feng进行查找,将账号对应的密钥key返回给客户端

c. 客户端对明文密码hmac得到密码hmac,将账号Feng+密钥key+密码hmac发送给服务器。如果服务器账号密码匹配成功,客户端将密钥key保存;反之不能保存

③ 设备锁业务

a. 设备B初次登录,并向服务器索要key

b. 服务器询问原设备A是否开始设备锁,如果没开就自定发送key给B;如果开了就向设备A访问权限,A同意了才能发送

c. 服务器对账号Feng进行查找,将账号对应的密钥key返回给客户端

d. 同②-c

5. 防止被抓去网络请求数据——加时间戳

HMAC的加密方案已经相当安全了,但是客户端发送给服务器的密码照样能被截取到,第三方只要账号、密码一匹配就能简简单单登录,所以我们要对网络请求数据进行一些处理,我们采用的方法是加时间戳:

a. 发起登录请求

b. 服务器返回时间戳给客户端

c. 照着(HMAC哈希值+时间戳).MD5进行运算,这里的时间戳不是本地的系统时间,而是发起登录请求时服务器返回给客户端的时间戳(只取到分钟)然后将HMAC密码拼接上时间戳,再次进行MD5发送给服务器

d. 服务器也用同样的算法进行运算,先匹配同一分钟的哈希值,匹配不成功再匹配上一分钟的哈希值

这样做能够让用户的密码随着时间变化而变化,黑客只能在最多两分钟内使用截获到的密码(最少1分01秒,最多1分59秒)

总结:建议用户密码采用先HMAC再时间戳的方案

也有账号动态盐,密码时间戳的方案

三、数字签名

1. 含义

数字签名,就是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。

2. 作用

图文并茂才能更好地阐述观点——xx去银行取十块钱的过程

正常情况下
a. 用户要取10元

b. 银行给了你10元

c. 用户拿到10元

黑客骚扰下
a. 用户要取10元

b. 黑客修改:“用户要取20元”

c. 银行转出20元

d. 黑客拿到10元,用户拿到10元

数字签名后
a. 用户要取10元

b. 黑客想修改成:“用户要取20元”,但修改不了

c. 银行转出20元

d. 用户拿到10元

3. 原理

a. 原始数据HASH加密

b. 使用RSA对HASH值进行加密(数字签名)

c. 将原始数据+数字签名,一起发给服务器验证 黑客没有私钥,不能对其进行解密; 传输过程中,没有密钥传递; hash值判断原始值有无修改

注:加密数字信息叫数字签名,加密代码叫代码签名,加密引用叫应用签名

四、对称加密

1. 含义:明文通过密钥加密得到密文。密文通过密钥解密得到明文

非对称加密被叫做现代加密算法,对称加密算法则叫做传统加密算法

2. 对称加密算法有三种:

  • DES:数据加密标准,因为强度低,所以用得少
  • 3DES:使用三个密钥,对原始数据进行三次加密 对于对称加密算法来说,密钥的保护本就尤为重要,3DES使用三个密钥对密钥保管更加不易
  • AES:高级加密标准 由于AES加密强度高,常用RSA加密AES的密钥

3. 常见的应用模式有两种:

  • ECB:电子密码本模式。每一块数据,独立加密 最基本的加密模式,也就是通常理解的加密,相同的明文将永远加密成相同的密文,无初始向量,容易受到密码本重放攻击,一般情况下很少用
  • CBC:密码分组链接模式。使用一个密钥和一个初始化向量对数据执行加密 明文被加密前要与前面的密文进行异或运算后再加密,因此只要选择不同的初始向量,相同的密文加密后会形成不同的密文,这是目前应用最广泛的模式。CBC加密后的密文是上下文相关的,但明文的错误不会传递到后续分组,但如果一个分组丢失,后面的分组将全部作废(同步错误)。 CBC可以有效的保证密文的完整性,如果一个数据块在传递是丢失或改变,后面的数据将无法正常解密。 为了更生动形象的对比ECB和CBC,我们将用终端演示来比较
  1. 生成一个message.text
123456123456123456
123456123456123456
123456123456123456
123456123456123456
复制代码
  1. 终端命令openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg1.bin 用DES加密,选择ECB应用模式,密钥为616263,不加盐
  2. 修改message.text,最后一组123456->223456
123456123456123456
123456123456123456
123456123456123456
123456123456223456
复制代码
  1. 终端命令xxd msg1.binxxd msg2.bin
    ECB加密结果对比
  2. 同样的操作,选择CBC openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -in message.txt -out msg3.bin openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -in message.txt -out msg4.bin 用DES加密,选择CBC应用模式,初始化向量为0102030405060708,密钥为616263,不加盐
  3. 终端命令xxd msg3.binxxd msg4.bin
    CBC加密结果对比