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

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