近日工作当中遇到一个问题:文件上传前,需要在本地对文件的二进制流进行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函数的第三个参数,字符串和数据流终于统一意见了。
分析完不同点,也就差不多建好大家需要的桥了。
然后,想和大家唠唠什么是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的用法一模一样。
其他几个鬼呢?
网友评论