美文网首页
08 - Hash算法

08 - Hash算法

作者: 卡布奇诺_95d2 | 来源:发表于2021-04-21 23:16 被阅读0次

    HASH算法简介

    Hash:一般翻译做”散列“,也有直接音译为”哈希“,就是把任意长度的输入通过散列算法变成固定长度的输出,该输出值就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间不同的输入可能会散列成相同的输出,所以不可以从散列值来确定唯一输入值。简单的说,就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

    Hash算法可以将一个数据转换为一个标志,这个标志和源数据的每一个字节都有十分紧密的关系。Hash算法还有一个特点,就是很难找到逆向规律。

    Hash算法是一个广义的算法,也可以认为是一种思想,使用Hash算法可以提高存储空间的利用率,可以提高数据的查询效率,也可以做数字签名来保障数据传递的安全性,所以Hash算法被广泛地应用在互联网中。

    Hash算法也被称为散列算法,虽然被称为算法,但它实际上更是一种思想,Hash算法没有一个固定的公式,只要符合散列思想的算法都可以被称为Hash算法。

    常见的Hash算法:

    • MD5
    • SHA1
    • SHA256
    • SHA512

    Hash算法的特点:

    • 无固定公式,只要符合散列思想即可称为Hash算法
    • 对相同的数据进行Hash运算,得到的结果是相同的
    • 对不同的数据进行Hash运算,得到Hash值长度是相同的,默认为128位
    • 对不同的数据进行Hash运算,得到Hash值可能相同。因此Hash是不可逆的

    Hash使用案例

    密码加密

    准备工作,添加一个NSString的分类Hash,在该分类中,编写相应的Hash算法。

    #import <Foundation/Foundation.h>
    
    @interface NSString (Hash)
    
    //计算MD5散列结果
    - (NSString *)md5String;
    //计算SHA1散列结果
    - (NSString *)sha1String;
    //计算SHA256散列结果
    - (NSString *)sha256String;
    //计算SHA 512散列结果
    - (NSString *)sha512String;
    
    //计算HMAC MD5散列结果
    - (NSString *)hmacMD5StringWithKey:(NSString *)key;
    //计算HMAC SHA1散列结果
    - (NSString *)hmacSHA1StringWithKey:(NSString *)key;
    //计算HMAC SHA256散列结果
    - (NSString *)hmacSHA256StringWithKey:(NSString *)key;
    //计算HMAC SHA512散列结果
    - (NSString *)hmacSHA512StringWithKey:(NSString *)key;
    
    //计算文件的MD5散列结果
    - (NSString *)fileMD5Hash;
    //计算文件的SHA1散列结果
    - (NSString *)fileSHA1Hash;
    //计算文件的SHA256散列结果
    - (NSString *)fileSHA256Hash;
    //计算文件的SHA512散列结果
    - (NSString *)fileSHA512Hash;
    
    @end
    
    • 使用MD5对密码进行加密
    - (void)testMD5{
        self.pwd = @"123456";
        NSLog(@"密码:%@",self.pwd.md5String);
    }
    
    //结果:
    密码:e10adc3949ba59abbe56e057f20f883e
    

    虽然Hash是不可逆的,但是我们知道,同一个数据,生成的Hash一定是相同的。那可以通过不断碰撞的形式(即,不断的尝试源数据,使其MD5值与查询的MD5值相同),找到MD5值为结果的源数据。

    • 使用MD5加盐后再对密码进行加密
    - (void)testMD5Salt{
        self.pwd = @"123456";
        self.pwd = [self.pwd stringByAppendingString:@"LKSJDFLKJ&^&@@"].md5String;
        NSLog(@"密码:%@",self.pwd);
    }
    
    //结果
    密码:2359298f49af5695a4b846e95bdea467
    

    盐和密钥较为相似,若盐被泄露,也会造成较大的安全隐患。另外,加盐的方式对开发者的依赖太高,若开发者带着盐跑路,对公司来说也极痛苦。

    • 使用HMAC对密码进行加密
    - (void)testHmac{
        self.pwd = @"123456";
        self.pwd = [self.pwd hmacMD5StringWithKey:@"huang"];
        NSLog(@"密码:%@",self.pwd);
    }
    
    //结果
    密码:dadb0f2e7c9daf154abe5180755f9c2b
    

    HMAC加密的特点:

    1. 使用一个密钥加密数据做两次散列
    2. 密钥可由服务端提供,服务端可根据每个账号生成一个密钥,再将该密钥传递至客户端
    3. 单一密钥的泄漏只影响一个用户
    4. 单一密钥的更新,也只需要一个用户重新更新即可

    使用HMAC加密流程:

    1. 注册阶段
      1. 将账号传递给服务端
      2. 服务端针对账号随机生成一个密钥,并将密钥返回给客户端
      3. 客户端将密钥存储在本地,如:钥匙串
      4. 注册时,明文密码使用HMAC加密,将密文传递到服务端
    2. 登陆阶段
      1. 如果本地没有密钥,则先向服务器获取密钥,这种情况多发生在更换设备后,新设备未存储密钥。此时也可增加授权流程来获取密钥
      2. 登陆时,明文密码使用HMAC加密后,再将密文传递至服务端

    使用HMAC加密,密码相对安全,但是仍然无法防止攻击,攻击者利用网络监听或者其它方式盗取密文密码后,可直接将密文密码作为整个密码数据,在需要使用密码的时候将其发送给服务器,欺骗系统从而完成身份认证。

    • 使用Hash+时间戳对密码进行加密
      防止重放攻击最有效的办法就是对密文增加时效性,在HMAC加密方式不变的情况,增加时间戳,使密文仅在时间戳范围内有效。
    - (void)testHmacTime{
        self.pwd = @"123456";
        self.pwd = [self.pwd hmacMD5StringWithKey:@"huang"];
        self.pwd = [self.pwd stringByAppendingString:@"202104211811"].md5String;
        NSLog(@"密码:%@",self.pwd);
    }
    
    //结果
    密码:d54b43cbd6f6005547096b526924cdfa
    

    总结:安全性比较:MD5 < MD5+盐 < HMAC < HMAC+时间戳。

    数字签名

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

    数字签名的目的:

    1. 防伪造:私有密钥只有签名者自己知道,所以其它人不可能伪造。
    2. 鉴别身份:由于传统的手工签名一般是双方直接见面,身份自可一清二楚,但在网络环境中,接收方必须能够鉴别发送方所宣称的身份。
    3. 防篡改:对于数字签名,签名与原有文件已经形成一个混合的整体数据,不可能被篡改,从而保证了数据的完整性。
    4. 防重放:对于数字签名,如果采用了对签名报文添加流水号、时间戳技术,可有效防止重放攻击。
    5. 防抵赖:数字签名可以鉴别身份,不可能伪造,那么保存好签名的报文,也就保留了证据,签名者无法抵赖。
    6. 保密性:有了保密性,截收攻击也就失效了,数字签名可以加密要签名的信息,当然如果签名的报文不要求机密性,也可以不加密。

    数字签名的使用:

    • 服务端
      • 对将要传递的数据,生成Hash值。
      • 使用RSA对Hash值进行加密,从而生成签名。
      • 传递数据时,同时传递签名
    • 客户端
      • 使用RSA对签名进行解密,得到服务器端的Hash值
      • 使用相同的算法,对数据生成本地的Hash值
      • 将本地Hash值与服务器Hash值进行比较,若一致则表示本次请求是合法的,否则为非法的。

    其它用途

    在搜索引擎中分词搜索时,几个关键字无论顺序如何,得到的搜索结果都是一致的,这也是Hash值的一个应用场景。

    例如:搜索iOS & Swift

    无论iOS和Swift的顺序如何,只要iOS和Swift的Hash值之和是一样的,则视为相同的搜索词,因此得到的搜索结果是一样的。

    即:iOS.Hash + Swift.Hash = Swift.Hash + iOS.Hash

    版权

    由于数字文件的便捷性,拷贝传播十分方便,但是一些涉及利益的传播性质,往往会侵犯数字文件版权的归属问题。此时就可以使用Hash。

    文件的Hash值,和文件名、后缀名无关,只取决于文件的二进制数据。正版与盗版的区别也在于它们的Hash值不同。

    数据识别

    网盘的数据识别,例如秒传功能,如果上传文件的Hash值在服务器上存在,无需重复上传。

    还有对于一些违规的文件,修改文件名、后缀名也会被识别出来,这种情况只能修改文件的二进制数据。

    对于文件计算Hash值,是不是也耗费服务器资源呢?

    其实,Hash去重也是分粒度的,有文件去重,块去重,字节去重,粒度越细的准确率越高,相应的耗费服务器资源肯定也要多。

    终端命令

    散列函数

    • 计算MD5散列结果
    md5 -s "123456"
    
    //结果为:32个字符的MD5散列字符串
    MD5 ("123456") = e10adc3949ba59abbe56e057f20f883e
    
    • 计算SHA1散列结果
    echo -n "123456" | openssl sha1
    
    //结果为:40个字符的SHA1散列字符串
    7c4a8d09ca3762af61e59520943dc26494f8941b
    
    • 计算SHA256散列结果
    echo -n "123456" | openssl sha256
    
    //结果为:64个字符的SHA256散列字符串
    8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
    
    • 计算SHA512散列结果
    echo -n "123456" | openssl sha512
    
    //结果为:128个字符的SHA512散列字符串
    ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413
    

    HMAC散列函数

    • 计算HMAC MD5散列结果
    echo -n "123456" | openssl dgst -md5 -hmac "huang"
    
    //结果为:32个字符的HMAC MD5散列字符串
    dadb0f2e7c9daf154abe5180755f9c2b
    
    • 计算HMAC SHA1散列结果
    echo -n "123456" | openssl sha1 -hmac "huang"
    
    //结果为:40个字符的HMAC SHA1散列字符串
    60340b9064d4b48fb021eb7bead73c1441909b0f
    
    • 计算HMAC SHA256散列结果
    echo -n "123456" | openssl sha256 -hmac "huang"
    
    //结果为:64个字符的HMAC SHA256散列字符串
    24dd68b307f9a05218d2fbcf3276fb829429c716b2e4fc87049dedcc6d6d79af
    
    • 计算HMAC SHA512散列结果
    echo -n "123456" | openssl sha512 -hmac "huang"
    
    //结果为:128个字符的HMAC SHA512散列字符串
    cf410ed80b9347ee7a33f28bc49745d32640d65e4c2e478b9b27b5392942a1dbb53e1e3f8b0cd9f356efa30307ac235a87482526dc4e480a5bb4be069018bc05
    

    文件散列函数

    //1. 创建文件file.txt
    vim file.txt
    //输入文件内容为:123456
    
    //2. 计算文件的MD5散列结果
    md5 file.txt
    //得到32个字符的MD5散列字符串
    MD5 (file.txt) = f447b20a7fcbf53a5d5be013ea0b15af
    
    //3. 计算文件的SHA1散列结果
    openssl sha1 file.txt
    //得到40个字符的SHA1散列字符串
    SHA1(file.txt)= c4f9375f9834b4e7f0a528cc65c055702bf5f24a
    
    //4. 计算文件的SHA256散列结果
    openssl sha256 file.txt
    //得到64个字符的SHA256散列字符串
    SHA256(file.txt)= e150a1ec81e8e93e1eae2c3a77e66ec6dbd6a3b460f89c1d08aecf422ee401a0
    
    //5. 计算文件的SHA512散列结果
    openssl sha512 file.txt
    //得到128个字符的SHA512散列字符串
    SHA512(file.txt)= 1caced6fca2237153d65adfb0f3dbe33b9375e9eb6df17c379f80cd37deb6e6a70159c7e898576db568b871ca1c2ffd1a2cc3205f1b50be5396096335fc29c40
    

    总结

    • Hash的特点:
    1. 无固定公式,只要符合散列思想即可。
    2. 对相同的数据进行运算,得到的结果相同。
    3. 对不同的数据进行运算,得到结果的数据长度相同。
    4. 对不同的数据进行运算,得到的结果可能相同。
    5. Hash算法不可逆。
    • Hash的用途
    1. 用作密码加密
    2. 用作数字签名
    3. 用于搜索引擎中的多关键字搜索
    4. 用于版权归属问题解决
    5. 用于数据识别
    • 加密密码的方式
    1. MD5(存在安全隐患,密码可通过碰撞后破解)
    2. MD5+盐(存在安全隐患,盐被泄漏后密码可被破解)
    3. HMAC(安全性较高,但可被重放攻击)
    4. HMAC+时间戳(安全性较高,防止重放攻击)

    相关文章

      网友评论

          本文标题:08 - Hash算法

          本文链接:https://www.haomeiwen.com/subject/gnbzlltx.html