[MD5]_[Windows-macOS]_[计算文件的MD5]

本文介绍了如何在Windows和macOS环境下使用系统自带库或API计算文件的MD5值,以此来校验文件的完整性和唯一性。文章提供了具体的代码示例,并详细解释了每个步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

场景

1.MD5是比较简单的文件ID, 大部分情况在安全系数要求不高时可以用它来校验文件唯一性. 比如下载文件后进行 md5计算看文件是否完整.

2.对字符串进行md5也是一样的.

例子

1.下边是使用系统自带的库或API来完成计算文件的md5, 第3方库 libgcrypt也可以做到, 就是编译比较麻烦.

Windows


#include <Wincrypt.h>

std::string AssUtil::CalcFileMD5(const char* path)
{
    DWORD dwStatus = 0;
    BOOL bResult = FALSE;
    HCRYPTPROV hProv = 0;
    HCRYPTHASH hHash = 0;
    HANDLE hFile = NULL;
    BYTE rgbFile[BUFSIZE];
    DWORD cbRead = 0;
    BYTE rgbHash[MD5LEN];
    DWORD cbHash = 0;
    CHAR rgbDigits[] = "0123456789abcdef";
    wchar_t* filename = BASUtilityString::ConvertUtf8ToUnicode(path);
    BASWrapMalloc wm(filename);
    // Logic to check usage goes here.

    hFile = CreateFile(filename,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_SEQUENTIAL_SCAN,
        NULL);

    if (INVALID_HANDLE_VALUE == hFile)
    {
        dwStatus = GetLastError();
        printf("Error opening file %s\nError: %d\n", filename, 
            dwStatus); 
        return "";
    }
    BASWrapHandle<CloseHandle> wh_file(hFile);
    // Get handle to the crypto provider
    if (!CryptAcquireContext(&hProv,
        NULL,
        NULL,
        PROV_RSA_FULL,
        CRYPT_VERIFYCONTEXT))
    {
        dwStatus = GetLastError();
        printf("CryptAcquireContext failed: %d\n", dwStatus); 
        return "";
    }
    auto my_hProv = [](HCRYPTPROV* hProv1){CryptReleaseContext(*hProv1, 0);};
    std::unique_ptr<HCRYPTPROV,decltype(my_hProv)> p1(&hProv,my_hProv);
    if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
    {
        dwStatus = GetLastError();
        printf("CryptAcquireContext failed: %d\n", dwStatus); 
        return "";
    }

    auto my_hHash = [](HCRYPTHASH* hHash){CryptDestroyHash(*hHash);};
    std::unique_ptr<HCRYPTHASH,decltype(my_hHash)> p2(&hHash,my_hHash);

    while (bResult = ReadFile(hFile, rgbFile, BUFSIZE, 
        &cbRead, NULL))
    {
        if (0 == cbRead)
        {
            break;
        }

        if (!CryptHashData(hHash, rgbFile, cbRead, 0))
        {
            dwStatus = GetLastError();
            printf("CryptHashData failed: %d\n", dwStatus); 
            return "";
        }
    }

    if (!bResult)
    {
        dwStatus = GetLastError();
        printf("ReadFile failed: %d\n", dwStatus); 
        return "";
    }

    cbHash = MD5LEN;
    std::string result;
    if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
    {
        printf("MD5 hash of file %s is: ", filename);
        for (DWORD i = 0; i < cbHash; i++)
        {
            printf("%c%c", rgbDigits[rgbHash[i] >> 4],rgbDigits[rgbHash[i] & 0xf]);
            result.append(1,rgbDigits[rgbHash[i] >> 4]);
            result.append(1,rgbDigits[rgbHash[i] & 0xf]);
        }
        printf("\n");
    }
    else
    {
        dwStatus = GetLastError();
        printf("CryptGetHashParam failed: %d\n", dwStatus); 
    }
    return result;
}

macOS


#include <CommonCrypto/CommonDigest.h>

std::string AssUtil::CalcFileMD5(const char* path)
{
    unsigned char digest[CC_MD5_DIGEST_LENGTH];

    CC_MD5_CTX ctx;
    CC_MD5_Init(&ctx);

    char buf[1024];
    FILE* file = fopen(path, "rb");
    while (!feof(file)) {
        auto readed = fread(buf, 1, 1024, file);
        CC_MD5_Update(&ctx,buf,(CC_LONG)readed);
    }
    fclose(file);
    CC_MD5_Final(digest,&ctx);

    std::string result;
    for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++){
        android::base::StringAppendF(&result,"%02x", digest[i]);
    }
    //std::cout << result << std::endl;
    return result;
}

参考

md5-algorithm-in-objective-c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白行微

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值