您的位置:首页 > 其它

使用webrtc中的MD5 API计算某个文件的MD5值

2016-11-28 14:47 561 查看
    在未使用webrtc之前,我都是用crypto++来计算文件的MD5值,其中多是使用crypto++API,当时我计算文件的md5值是直接将文件的路径传给了MD5 API函数,返回值就是MD5值字符串了,这样虽然用起来方便但是一旦文件过大或者说有几百M、几G的时候,我发现其计算的时间比较长,造成了很明显的时间延迟,我想那个api是直接将文件的内容整块地读到系统缓存中再一次性地计算整块内容的MD5值吧,后来经过查询,得知另外一种MD5值的计算方法,先前那个是整块读写整块计算MD5,这对机器来说来是个考研万一电脑内存不够文件内容大呢,那就崩溃了!现在的方法是将文件分一块块地读一块块地计算MD5,然后将已得的md5值和新计算的块的md5值进行一次求值运算,这样循环下去直到将文件的内容全部读取和计算完,每块文件内容的size由你自己定,但是不可太小了,太小了,这样反而会降低大文件md5值得计算效率,这里我选择块的默认内容大小为1024字节的大小。下面是一段代码,但是我想将一份有问题的代码摆上来让各位注意一下:

std::string Tian_FileMd5::CaculateFileMd5(std::string filepath, size_t blocksize)
{
struct rtc::MD5Context context;
MD5Init(&context);
char tempStr[PER_BLOCK_SIZE + 1];
ifstream inFile;
inFile.open(filepath.c_str(), ios::_Nocreate | ios::binary | ios::in);
if (!inFile)
LOG(INFO) <<const_cast<char *>(filepath.c_str()) << L"打开失败!" << endl;
inFile.seekg(0, ios::end);
long filesize = inFile.tellg();
inFile.seekg(0, ios::beg);
int currentReadSize = PER_BLOCK_SIZE;
while (!inFile.eof())
{
size_t curseek = inFile.tellg();
if ((filesize - curseek) < PER_BLOCK_SIZE)
{
currentReadSize = filesize - curseek;
}
if (!currentReadSize)
break;
inFile.read(tempStr, currentReadSize);
int readSize = inFile.gcount();
MD5Update(&context, (const uint8_t *)tempStr, readSize);
memset(tempStr, 0, PER_BLOCK_SIZE + 1);
}

//@A@

char digest[16];
MD5Final(&context, (uint8_t *)digest);
char md5string[32];
for (int i = 0; i < 16; ++i)
sprintf(&md5string[i * 2], "%02x", digest[i]);//(unsigned int)
inFile.close();
return string(md5string);
}

    在@A@下面的那句unsigned char digest[16];结果在for循环后得到的数值发现,结果的MD5值中会和使用工具计算出来的值不同,每四个字符中都会连续地出现“ff”,该四位中的其他的连续两位则和工具计算出来的值得对应位相同!这很明显是数据溢出的啊,只是因为digest是“char”类型的数字,“char”是无符号的,占8位,最高位被用来做符号位,可表示的数值范围为-128-127,如果一个数值超过了这个范围,那就会溢出了,就会是-1,那么在转化为十六进制后就是ff,所以在这个地方应该将“char”改为“unsigned
int”,这样计算的结果都在可表达的范围內,“unsigned char”可表示的数值的范围为0~255,问题得到解决!

-------------------------------------------------------------------------------------

   
另外可以证明的是,相对一次性将文件读取到内存的方法,在同样设置了恰当的块的size时,分块计算md5值所花的时间是远远短于整块读取计算的那种方式的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: