MD5,想说爱你不容易

2018-04-11  本文已影响0人  天蓬大元

近日工作当中遇到一个问题:文件上传前,需要在本地对文件的二进制流进行MD5加密,然后传给后台进行校验。期间遇到了很多奇葩的问题。

问题一: 对同一个图片进行MD5加密,得到的却是不同的hash值。对应代码如下:

+ (NSString *)fileMD5:(NSData *)fileData
{
    unsigned char result[16];
    CC_MD5(fileData,fileData.length, result);
    NSMutableString *output = [[NSMutableString alloc]init];
    for( int i = 0; i < 16; i++ )
    {
        [output appendFormat:@"%02x", result[i]];
    }
    return output;
}

问题二:对不同的图片进行加密,得到的却是相同的MD5。代码如下:

+ (NSString*)getMD5WithData:(NSData *)data
{
    const char* original_str = (const char *)[data bytes];
    unsigned char digist[CC_MD5_DIGEST_LENGTH];     //CC_MD5_DIGEST_LENGTH = 16
    CC_MD5(original_str, (uint)strlen(original_str), digist);
    NSMutableString* outPutStr = [NSMutableString stringWithCapacity:10];
    for(int  i =0; i<CC_MD5_DIGEST_LENGTH;i++){
        [outPutStr appendFormat:@"%02x",digist[i]];//小写x表示输出的是小写MD5,大写X表示输出的是大写MD5
    }
    return [outPutStr lowercaseString];
}

直到遇到大神,得到了一个锦囊:iOS - 获取文件的SHA1、SHA256,才将这两个问题解决。代码如下:

+ (NSString *)fileMD5:(NSData *)fileData
{
     const char*original_str = (const char *)[fileData bytes];
     unsigned char result[CC_MD5_LENGTH];
     CC_MD5(original_str, (CC_LONG)fileData.length, result);
     NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_LENGTH * 2];
     for( int i = 0; i < CC_MD5_LENGTH; i++ )
     {
         [output appendFormat:@"%02x", result[i]];
     }
     return output;
}

dome如果对你有帮助,请亲给个star。谢谢!!

回想整个问题的解决过程,收获还是蛮多的,在这里记录下来,希望能给大家打座小桥,别再阴沟里翻船。

坑王驾到:关于SHA,你想知道的全在这里

=> #import <CommonCrypto/CommonDigest.h>

一,字符串的MD5和数据流的MD5的不同点

先附上字符串的MD5加密代码:

+ (NSString *)stringMD5:(NSString *)string
{
    const char* original_str = [string UTF8String];
    unsigned char result[CC_MD5_LENGTH];
    CC_MD5(original_str, (CC_LONG)strlen(original_str), result);
    NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_LENGTH * 2];
    for( int i = 0; i < CC_MD5_LENGTH; i++ )
    {
        [output appendFormat:@"%02x", result[i]];
    }
    return output;
}

对比上面关于数据流的代码,我们得出以下伤害:

1,字符串和数据流都在调用同一个函数进行md5加密
extern unsigned char *CC_MD5(const void *data, CC_LONG len, unsigned char *md)
2,针对CC_MD5函数的第一个参数,字符串和数据流分别要进行不同的转换。
3,针对CC_MD5函数的第二个参数,字符串和数据流分别要进行不同的操作。
(在使用 NSString 的时候,
  因为 CC_MD5 是一个C函数,
  而 NSString 提供的 length 函数被处理过后,
  汉字或者一些其他鬼字符的长度和 strlen 计算出来的不一样了,
  于是导致了这样一个大坑。 )
(NSData 去计算 MD5 通常是通过文件或者音频、图片等转化过来的。    
  因此,在 data 中什么都有可能出现。
  如果我没有记错的话,字符'\0'被转化成二进制应该是 0000 00000之类的东西
  这时候,如果你的 NSData 是通过压缩或者其他方式得到的,就很有可能出现一个这样的二进制 .....0000......
  (意思就是 二进制的一串中包含了一些特殊的字符,相当于转化成String被识别成了'\0')
  于是 这时候,你再用strlen计算,就只会计算.....0000这么多了,后面的就完全忽略了
  于是 这样一个潜在的bug就出现了。)

4,针对CC_MD5函数的第三个参数,字符串和数据流终于统一意见了。

iOS 下关于 MD5 的那个坑

分析完不同点,也就差不多建好大家需要的桥了。

然后,想和大家唠唠什么是MD5?为什么要使用MD5进行文件的校验?

二,知其然,然后知其所以然

先来段 百度百科读读。

划重点:我们这里不做原理分析,因为本人的水平有限(其实就是我不会+我太懒)
定义: Message Digest Algorithm MD5为计算机安全领域广泛使用的一种散列函数,
      用以提供消息的完整性保护,确保信息传输完整一致
      (防止信息在传输过程中被篡改)
      是计算机广泛使用的杂凑算法之一(又译[摘要算法][哈希算法])
基础原理:将数据(如汉字)运算为另一固定长度值
特点:
      1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。
      2、容易计算:从原数据计算出MD5值很容易。
      3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。
      4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。
非重点,但你必须知道:MD5加密后的文件被证实可以被破解
不想都知道,怎么可能就这一种杂凑算法呢?
三,其他的加密算法
SHA1,SHA-224,SHA-256,SHA-384,SHA-512

这都是些什么鬼?

SHA1加密算法代码:
        将CC_MD5替换成SHA1即可

这样就可以了?

对!!这货和MD5的用法一模一样。

其他几个鬼呢?

对!!这些货和MD5的用法一模一样。

duang!!除了名字和算法不同,其他都一样

你以为这就完了,哈哈哈,你太天真了。作为一名严谨的程序员,怎么能没有刨根问底的品质呢?

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

往下看,有惊喜

--------------------完-----------------------

上一篇下一篇

猜你喜欢

热点阅读