YYFileHash

作者: Mr卿 | 来源:发表于2017-12-14 11:50 被阅读12次

这个是对文件进行hash

我们这里主要看加密算法,这里有十个加密算法。md2 md4 md5 sha1 sha224 sha256 sha384 sha512 crc32 adler32

前面八个都是用的系统的init update final 函数进行运算的。而后面两个是自己定义的api 为了配合定义的宏定义init_hash(Type,Init,Update,Final,Length)

这里有几个c数组。

int hash_type_total = 10; 
 void *ctx[hash_type_total];

int(*ctx_init[hash_type_total])(void *); 
int(*ctx_update[hash_type_total])(void *, const void *, CC_LONG);
 int(*ctx_final[hash_type_total])(unsigned char *, void *);
 long digist_length[hash_type_total]; 
 unsigned char *digest[hash_type_total];

ctx 数组装的是 void * 类型的指针

ctx_init 数组装的是 int ()(void *) 类型的指针

ctx_update 数组装的是 int ()(void *, const void *, CC_LONG) 类型指针

ctx_final 装的是int()(unsigned char *, void *) 类型的指针

看懂这里再往下看。

到#undef init_hash 行以前就是给这些数组赋值。这些数组保存的是函数指针

这里我们先学习下 md5 用CC_MD5_Init CC_MD5_Update CC_MD5_Final 使用

 NSFileHandle *handle= [NSFileHandle fileHandleForReadingAtPath:path];

 if(handle== nil ) {

 return nil;

}

 CC_MD5_CTX md5;

 CC_MD5_Init(&md5);

 BOOLdone=NO;

 while(!done)

 {

 NSData*fileData= [handle readDataOfLength: 256 ];

 CC_MD5_Update(&md5, [fileData bytes], [fileData length]);

 if( [fileData length] == 0 )done=YES;

}

 unsigned char digest[CC_MD5_DIGEST_LENGTH];

 CC_MD5_Final(digest, &md5);

 NSString*s= [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  digest[0], digest[1],
 digest[2], digest[3],
 digest[4], digest[5],
 digest[6], digest[7],
 digest[8], digest[9],
 digest[10], digest[11],
 digest[12], digest[13],
 digest[14], digest[15]];

这就是用法。我们看看yykit 大神怎么在这个里面干嘛。想要看懂这个函数。要了解c语言文件操作的几个函数。

函数原型:FILE * fopen(const char * path, const char * mode); 就是打开文件

int fseeko(FILE *stream, off_t offset, int fromwhere);

参数:

stream:文件指针

fromwhere:偏移起始位置

offset:偏移量

功能:函数设置文件指针stream的位置。如果执行成功,stream将指向以fromwhere(偏移起始位置:文件头0(SEEK_SET),当前位置1(SEEK_CUR),文件尾2(SEEK_END))为基准,偏移offset(指针偏移量)个字节的位置。如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置。

ftell

函数 ftell 用于得到文件位置指针当前位置相对于文件首的偏移字节数。

size_t****fread (****void********buffer,****size_tsize,****size_tcount,****FILE********stream) ;

buffer

用于接收数据的内存地址

size

要读的每个数据项的字节数,单位是字节

count

要读count个数据项,每个数据项size个字节.

stream

输入流

int feof(FILE *stream);

参数

流 :FILE结构的指针

feof是C语言标准库函数,其原型在stdio.h中,其功能是检测流上的文件结束符,如果文件结束,则返回非0值,否则返回0,文件结束符只能被clearerr()清除。

fd = fopen(path, "rb");

if (!fd) goto cleanup;

if (fseeko(fd, 0, SEEK_END) != 0) goto cleanup;

file_size = ftell(fd);

if (fseeko(fd, 0, SEEK_SET) != 0) goto cleanup;

if (file_size < 0) goto cleanup;

yykit 大神写的这段代码的意思 就是读取文件大小。

if (block) {

while (!done && !stop) {

size_t size = fread(buf, 1, BUF_SIZE, fd);

if (size < BUF_SIZE) {

if (feof(fd)) done = YES; // finish

else { stop = YES; break; } // error

}

for (int i = 0; i < hash_type_total; i++) {

if (ctx[i]) ctx_update[i](ctx[i], buf, (CC_LONG)size);

}

readed += size;

if (!done) {

loop++;

if ((loop % BLOCK_LOOP_FACTOR) == 0) {

block(file_size, readed, &stop);

}

}

}

}

要是配置block 的话。读取文件每次都去 BUF_SIZE =512k大小 将数据更新到update函数中

这里检查loop 次数。要是读取数据大于8M的话就回调一下block。

以md5加密为例最终结构都更新到CC_MD5_Update 函数中。

没有block 就是不用回调而已。用法一样不做介绍

最后就是收集数据了。

ctx_final[i](digest[i], ctx[i]); 已md5 为例。这个地方就是调用CC_MD5_Final()函数

NSUInteger type = 1 << I;

NSData *data = [NSData dataWithBytes:digest[i] length:digist_length[I]];

NSMutableString *str = [NSMutableString string];

unsigned char *bytes = (unsigned char *)data.bytes;

for (NSUInteger d = 0; d < data.length; d++) {

[str appendFormat:@"%02x", bytes[d]];

}

转换成最后的结果。

将结果保存到相关属性里面。

这里我们主要是要看看crc32 和Adler32 类型的算法

crc32 用法

Usage example:

uLong crc = crc32(0L, Z_NULL, 0);

while (read_buffer(buffer, length) != EOF) {

crc = crc32(crc, buffer, length);

}

if (crc != original_crc) error();

yykit大神将其拆解成 init update final 形式

adler32用法和 crc32 用法相同。

我们这里不对每个算法做原理分析和使用场景分析。

原文

相关文章

  • YYFileHash

    这个是对文件进行hash 我们这里主要看加密算法,这里有十个加密算法。md2 md4 md5 sha1 sha22...

网友评论

    本文标题:YYFileHash

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