【问题标题】:Different md5 sum from same file来自同一文件的不同 md5 总和
【发布时间】:2012-09-26 08:44:52
【问题描述】:

我正在从 iphone 库的视频文件中计算 md5 总和。每次我选择同一个文件时,它都有不同的 md5 总和。我还检查了以字节为单位的数据长度,它保持不变。所以我的问题是——为什么?这是我尝试制作的多种方法中的一些代码。

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{   
    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
    if ([mediaType isEqualToString:@"public.movie"])
    {
        NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
        videoData = [NSData dataWithContentsOfURL:videoURL];
        [videoData retain];
        NSLog(@"VIDEO DATA MD5: %@", [videoData md5]);
        NSLog(@"VIDEO DATA LEN: %d", videoData.length);
    }

    [self dismissModalViewControllerAnimated:YES];
}

Implementation of MD5 Method:

#import <CommonCrypto/CommonDigest.h>

@implementation NSData(MD5)

- (NSString*)MD5
{
  // Create byte array of unsigned chars
  unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];

  // Create 16 byte MD5 hash value, store in buffer
  CC_MD5(self.bytes, self.length, md5Buffer);

  // Convert unsigned char buffer to NSString of hex values
  NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
  for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) 
    [output appendFormat:@"%02x",md5Buffer[i]];

  return output;
}

@end

【问题讨论】:

  • md5的实现是什么?
  • 连续两次获取数据时,调用isEqualToData:返回YES还是NO?我想知道是否没有通过访问文件来更新某些元数据(尤其是“上次访问”之类的内容),以便每次获取文件时都有相同的视频但元数据不同?
  • 你能把代码贴在你做比较的地方吗?您是否可能使用 == 来比较两个字符串,而不是 [string1 isEqualToString:string2]

标签: objective-c ios xcode md5


【解决方案1】:

我可以确认这种行为。无论选择何种哈希函数(我尝试过 MD5、SHA1 和 SHA256),都会发生这种情况。

问题似乎是NSData。我从 完全相同的文件 创建了两个 NSData 实例,然后使用 [data1 isEqualTo:data2] 并返回 true。但是,通过 CC_SHA1 哈希算法运行它们会为每个返回不同的哈希。

要解决此问题,请删除 NSData。相反,使用较低级别的 C API 打开文件。这是 C 中的一个示例。请注意“创建”约定——完成后,您负责释放返回的 char* 缓冲区。使用这种方法每次都会产生一个相同的哈希值。

char* _Nullable createBufferWithContentsOfFileAndReportLength(NSString* _Nonnull fileToScan, long* _Nullable length)
{
    char const *pathToFile = [fileToScan cStringUsingEncoding:NSUTF8StringEncoding];
    
    FILE *file = fopen(pathToFile, "r");
    if (file == NULL) {
        NSLog(@"Unable to open file: %@", fileToScan);
        return NULL;
    }
    
    //
    //  Get the file length.
    //  'fileLength' will be the number of bytes in the file. It will not include a null terminator or EOF. Some UTF8 characters require more than one byte, so we
    //  can't guarantee that fileLength is also the number of characters.
    //  NOTE: We don't use the fseek()/ftell()/rewind approach because it's not secure. See CERT FIO19-C advisory for details.
    //
    int fd = fileno(file);
    if (fd < 0) {
        NSLog(@"Unable to get a file descriptor for: %@", fileToScan);
        fclose(file);
        return NULL;
    }
    struct stat statBuffer;
    if (fstat(fd, &statBuffer) == -1) {
        NSLog(@"Unable to retrieve stats about this file: %@", fileToScan);
        fclose(file);
        return NULL;
    }
    long fileLength = statBuffer.st_size;
    
    char *buffer = malloc(sizeof(char) * (fileLength + 1));     // enough memory to read the entire file, plus a spot for the null terminator
    if (buffer == NULL) {
        NSLog(@"Unable to allocate memory for: %@", fileToScan);
        fclose(file);
        return NULL;
    }
    
    fread(buffer, fileLength, sizeof(char), file);
    buffer[fileLength] = '\0';                              // No +1; this is zero-indexed. If fileLength is 5 characters, the 5th slot in the array needs to be the null terminator.
    fclose(file);

    if (length != NULL) {
        *length = fileLength + 1;
    }
    
    return buffer;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-07
    • 2020-03-17
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多