Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出(散列碰撞),所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。Hash算法包括:md5,sha1,sha256…等。
Hash的特点
- 算法是公开的
- 对相同数据的运算,结果一样
- 不能逆运算
- 信息摘要,可称为信息指纹,用于做数据识别
Hash的用途
- 保存用户密码
- 搜索引擎
- 版权
- 数字签名
关于用户密码的设计
对一个互联网平台来说,用户的密码安全是非常重要的,泄漏用户的密码需要负相应的法律责任。一个用户的密码可能是通用的,微信,QQ,抖音等等,可能使用的都是相同的手机号+密码的形式,一旦一个平台的密码被泄漏,那么可能所有平台的密码都泄漏了,所以关于密码安全,有一个原则:不能存储明文,最好开发人员都不知道密码是什么。
保存密码就可以使用hash。服务端保存密码的hash值,用户登录时,将密码的hash值发送给服务器,服务器通过比对来判断密码是否正确。下面用md5来举例,如果密码只做一次md5,那么还是不够安全,有一个网站 www.cmd5.com 记录了很多哈希值,用来查找对比…那么,我们想到加盐(password+salt).md5,但是这样所有用户都使用一个盐,也不安全。
HMAC
给每一个用户一个key,注册时候动态分配给这个账号,保存在手机中。当切换手机时,需要授权(向服务器请求key),key更换比较方便。为了防止数据在发送过程中被截取,可以添加时间戳 ((HMAC哈希)+ 202105162012).md5发送给服务器,假如此时正好到下一分钟202105162013,服务器验证当前时间的,和上一分钟的。
数字签名原理
客户端与服务器数据交换的时候,数据可能会被拦截和修改,如果不经过验证直接使用,那么数据的安全性则没办法保证。数字签名的原理就是:客户端中保存一个公钥,服务器保存私钥。客户端向服务器发送数据时,使用约定好的方法,算出数据的hash,再将hash使用公钥加密,将数据与加密后的hash一同传给服务器,服务器接到数据后进行验证,先使用私钥解密hash,若解密失败证明hash被换了,不使用数据。若解密成功,使用约定的算法算出数据的hash,对比这两个hash,如果相同,则证明数据没有被修改。经过RSA加密过的hash就是数字签名。
代码签名
简单的代码签名
最初,苹果希望所有app只能从AppStore下载,从其他渠道下载的app不能安装到手机。苹果在AppStore中保存私钥,在iOS设备中保存公钥。AppStore中的私钥对代码签名,手机中的公钥对代码验证,成功之后可以在手机中运行。
苹果双层签名
- 在Mac系统中生成非对称加密算法的一对公钥\私钥(你的Xcode帮你代办了).这里称为公钥M 私钥M . M = Mac
- 苹果自己有固定的一对公私钥,跟之前App Store原理一样,私钥在苹果后台,公钥在每个iOS系统中.这里称为公钥A , 私钥A. A=Apple
- 把公钥M 以及一些你开发者的信息,传到苹果后台(这个就是CSR文件),用苹果后台里的私钥 A 去签名公钥M。得到一份数据包含了公钥M 以及其签名,把这份数据称为证书。
- 在开发时,编译完一个 APP 后,用本地的私钥 M(今后你导出的P12) 对这个 APP 进行签名,同时把第三步得到的证书一起打包进 APP 里,安装到手机上。
- 在安装时,iOS 系统取得证书,通过系统内置的公钥 A,去验证证书的数字签名是否正确。
- 验证证书后确保了公钥 M 是苹果认证过的,再用私钥 M 去验证 APP 的签名,这里就间接验证了这个 APP 安装行为是否经过苹果官方允许。(这里只验证安装行为,不验证APP 是否被改动,因为开发阶段 APP 内容总是不断变化的,苹果不需要管。)