iOS 超大文件MD5加密,超大文件hmac加密
1、在文件超过1G的时候,不能一次性放入内存之中,但是我们还是需要将这个文件进行md5加密,或者hmac系列的加密
这个时候我们需要用到一个系统的api——update系列的方法
注意:参数path为大文件所在的路径。
//首先声明一个宏定义 #define FileHashDefaultChunkSizeForReadingData 1024*8
//md5 +(NSString*)getFileMD5WithPath:(NSString*)path{ return (__bridge_transfer NSString *)FileMD5HashCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData); } CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,size_t chunkSizeForReadingData) { // Declare needed variables CFStringRef result = NULL; CFReadStreamRef readStream = NULL; // Get the file URL CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)filePath, kCFURLPOSIXPathStyle, (Boolean)false); if (!fileURL) goto done; // Create and open the read stream readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, (CFURLRef)fileURL); if (!readStream) goto done; bool didSucceed = (bool)CFReadStreamOpen(readStream); if (!didSucceed) goto done; // Initialize the hash object CC_MD5_CTX hashObject; CC_MD5_Init(&hashObject); // Make sure chunkSizeForReadingData is valid if (!chunkSizeForReadingData) { chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData; } // Feed the data to the hash object bool hasMoreData = true; while (hasMoreData) { uint8_t buffer[chunkSizeForReadingData]; CFIndex readBytesCount = CFReadStreamRead(readStream,(UInt8 *)buffer,(CFIndex)sizeof(buffer)); if (readBytesCount == -1) break; if (readBytesCount == 0) { hasMoreData = false; continue; } CC_MD5_Update(&hashObject,(const void *)buffer,(CC_LONG)readBytesCount); } // Check if the read operation succeeded didSucceed = !hasMoreData; // Compute the hash digest unsigned char digest[CC_MD5_DIGEST_LENGTH]; CC_MD5_Final(digest, &hashObject); // Abort if the read operation failed if (!didSucceed) goto done; // Compute the string result char hash[2 * sizeof(digest) + 1]; for (size_t i = 0; i < sizeof(digest); ++i) { snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i])); } result = CFStringCreateWithCString(kCFAllocatorDefault,(const char *)hash,kCFStringEncodingUTF8); done: if (readStream) { CFReadStreamClose(readStream); CFRelease(readStream); } if (fileURL) { CFRelease(fileURL); } return result; }
//HMAC
+(NSString*)getFileHMACWithPath:(NSString*)path withKey:(NSString *)key{ return (__bridge_transfer NSString *)FileHMACCreateWithPath((__bridge CFStringRef)path, FileHashDefaultChunkSizeForReadingData,key); } CFStringRef FileHMACCreateWithPath(CFStringRef filePath,size_t chunkSizeForReadingData,NSString* key) { // Declare needed variables CFStringRef result = NULL; CFReadStreamRef readStream = NULL; // Get the file URL CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)filePath, kCFURLPOSIXPathStyle, (Boolean)false); if (!fileURL) goto done; // Create and open the read stream readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, (CFURLRef)fileURL); if (!readStream) goto done; bool didSucceed = (bool)CFReadStreamOpen(readStream); if (!didSucceed) goto done; // Initialize the hash object const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding]; CCHmacContext ctx; CCHmacInit(&ctx, kCCHmacAlgSHA256, cKey, strlen(cKey)); // Make sure chunkSizeForReadingData is valid if (!chunkSizeForReadingData) { chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData; } // Feed the data to the hash object bool hasMoreData = true; while (hasMoreData) { uint8_t buffer[chunkSizeForReadingData]; CFIndex readBytesCount = CFReadStreamRead(readStream,(UInt8 *)buffer,(CFIndex)sizeof(buffer)); if (readBytesCount == -1) break; if (readBytesCount == 0) { hasMoreData = false; continue; } CCHmacUpdate(&ctx, (const void *)buffer,(CC_LONG)readBytesCount); } // Check if the read operation succeeded didSucceed = !hasMoreData; // Compute the hash digest unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH]; CCHmacFinal(&ctx, cHMAC); // Abort if the read operation failed if (!didSucceed) goto done; // Compute the string result char hmac[2 * sizeof(cHMAC) + 1]; for (size_t i = 0; i < sizeof(cHMAC); ++i) { snprintf(hmac + (2 * i), 3, "%02x", (int)(cHMAC[i])); } result = CFStringCreateWithCString(kCFAllocatorDefault,(const char *)hmac,kCFStringEncodingUTF8); done: if (readStream) { CFReadStreamClose(readStream); CFRelease(readStream); } if (fileURL) { CFRelease(fileURL); } return result; }