2012-11-06 28 views
5

Benim C++ uygulamasının şu anda OpenSSL tarafından yapıldığı MD5 hash değerini hesaplaması gerekiyor ve WinAPI'yi kullanmak için onu taşımak istiyorum - dış kütüphanelerde bağımlılığı önlemek için.Compute MD5 hash değeri C++ ile WinAPI

HCRYPTPROV hCryptProv = NULL; 
HCRYPTHASH hHash = NULL; 
HCRYPTHASH hHexHash = NULL; 
HASH HA1; 
HASHHEX HA1HEX; 
DWORD data = HASHLEN; 

// Get a handle to a cryptography provider context. 
if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) 
{ 
    goto err; 
} 

// Acquire a hash object handle. 
if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) 
{ 
    goto err; 
} 

CryptHashData(hHash, (const BYTE *)str, strlen(str), 0); 

şimdi, tuhaf bir şey somtimes iyi çalıştığını ancak diğer zamanlarda hata NTE_BAD_KEYSET ile CryptAcquireContext dönüş göre bu MSDN:
Bu kodu yazdım

anahtar konteyner yapamadım açılmak Bu hatanın yaygın bir nedeni, anahtar kabın mevcut olmamasıdır. Anahtar kapsayıcı oluşturmak için CRYPT_NEWKEYSET bayrağını kullanarak CryptAcquireContext öğesini çağırın. Bu hata kodu, mevcut bir anahtar kabına erişimin reddedildiğini de gösterebilir. Kapsayıcıya erişim hakları CryptSetProvParam kullanılarak anahtar kümesi oluşturucu tarafından verilebilir.

Blockquote

Şimdi sorularım şunlardır:

Ben CryptSetProvParam edip etmediklerini sorun
  1. , bu exceactly ne yapar? Basit uygulama işletim sistemi ayarlarını değiştirecek normal mi?
  2. MD5'te C++ pencerelerinde hesap yapmak için daha az zor bir yol var mı?

Birisi bana ne yapacağı konusunda iyi bir tavsiyede bulunabiliyorsa bunu inceleyeceğim.

Onlarınki:
Teşekkür

+1

Kamu adanmış bir uygulama [burada bulunabilir] (http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5). –

+0

teşekkürler, ama şimdilik kendimi uygulamamayı tercih ediyorum. – RRR

+3

Kendiniz uygulamıyorsunuz. Sadece md5.c ve md5.h'yi projenize bırakın ve işlevleri çağırın. –

cevap

6

Yani, onların koduna baktığımızda http://msdn.microsoft.com/en-us/library/aa382380%28VS.85%29.aspx

de istediğini yapar bir örnek buldum, görüyorum fark, bu çizgi CryptAcquireContext (& hCryptProv, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)

mla, NULL, NULL: NULL, NULL, CryptAcquireContext (& hCryptProv, PROV_RSA _FULL, 0)

Yani, bu bayrak üzerinde okuma, ben bu bilgileri bulmak:

CRYPT_VERIFYCONTEXT: Bu seçenek kısa ömürlü anahtarları kullanan uygulamalar veya kalıcı erişimi gerektirmeyen uygulamalar için tasarlanmıştır Yalnızca karmaşayı, şifrelemeyi ve dijital imza doğrulamasını gerçekleştiren uygulamalar gibi özel anahtarlar. Yalnızca imzalar oluşturan veya mesajların şifresini çözen uygulamaların özel bir anahtara erişmesi gerekir. Çoğu durumda, bu bayrak ayarlanmalıdır.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa379886%28v=vs.85%29.aspx

Yani, sen gerekmez bilgilere erişmek için çalışıyoruz benziyor ve istek reddedilir. Bu yüzden en iyi seçenek, Windows'a bu bayrağı ekleyerek o bilgiye ihtiyacınız olmadığını söylemektir.

3

PROV_RSA_AES ve 'u kullanmayı seviyorum, çünkü karmaların çoğu destekleniyor.İşte

çalışan bir örnektir:

#include <Wincrypt.h> 

enum HashType 
{ 
    HashSha1, HashMd5, HashSha256 
}; 

std::string GetHashText(const void * data, const size_t data_size, HashType hashType) 
{ 
    HCRYPTPROV hProv = NULL; 

    if (! CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { 
    return ""; 
    } 

    BOOL hash_ok = FALSE; 
    HCRYPTPROV hHash = NULL; 
    switch (hashType) { 
    case HashSha1 : hash_ok = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash); break; 
    case HashMd5 : hash_ok = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash); break; 
    case HashSha256 : hash_ok = CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash); break; 
    } 

    if (! hash_ok) { 
    CryptReleaseContext(hProv, 0); 
    return ""; 
    } 

    if (! CryptHashData(hHash, static_cast<const BYTE *>(data), data_size, 0)) { 
    CryptDestroyHash(hHash); 
    CryptReleaseContext(hProv, 0); 
    return ""; 
    } 

    DWORD cbHashSize = 0, dwCount = sizeof(DWORD); 
    if(! CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&cbHashSize, &dwCount, 0)) { 
    CryptDestroyHash(hHash); 
    CryptReleaseContext(hProv, 0); 
    return ""; 
    } 

    std::vector<BYTE> buffer(cbHashSize); 
    if (! CryptGetHashParam(hHash, HP_HASHVAL, reinterpret_cast<BYTE*>(&buffer[0]), &cbHashSize, 0)) { 
    CryptDestroyHash(hHash); 
    CryptReleaseContext(hProv, 0); 
    return ""; 
    } 

    std::ostringstream oss; 

    for (std::vector<BYTE>::const_iterator iter = buffer.begin(); iter != buffer.end(); ++iter) { 
    oss.fill('0'); 
    oss.width(2); 
    oss << std::hex << static_cast<const int>(*iter); 
    } 

    CryptDestroyHash(hHash); 
    CryptReleaseContext(hProv, 0); 
    return oss.str(); 
} 
1

Bu link

var ama yardımcı olabilecek umut yanımda bu işlevi çalıştırmak için bazı değişiklikler yaptı

char* HashMD5(char* data, DWORD *result) 
{ 
    DWORD dwStatus = 0; 
    DWORD cbHash = 16; 
    int i = 0; 
    HCRYPTPROV cryptProv; 
    HCRYPTHASH cryptHash; 
    BYTE hash[16]; 
    char *hex = "abcdef"; 
    char *strHash; 
    strHash = (char*)malloc(500); 
    memset(strHash, '\0', 500); 
    if (!CryptAcquireContext(&cryptProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 
    { 
     dwStatus = GetLastError(); 
     printf("CryptAcquireContext failed: %d\n", dwStatus); 
     *result = dwStatus; 
     return NULL; 
    } 
    if (!CryptCreateHash(cryptProv, CALG_MD5, 0, 0, &cryptHash)) 
    { 
     dwStatus = GetLastError(); 
     printf("CryptCreateHash failed: %d\n", dwStatus); 
     CryptReleaseContext(cryptProv, 0); 
     *result = dwStatus; 
     return NULL; 
    } 
    if (!CryptHashData(cryptHash, (BYTE*)data, strlen(data), 0)) 
    { 
     dwStatus = GetLastError(); 
     printf("CryptHashData failed: %d\n", dwStatus); 
     CryptReleaseContext(cryptProv, 0); 
     CryptDestroyHash(cryptHash); 
     *result = dwStatus; 
     return NULL; 
    } 
    if (!CryptGetHashParam(cryptHash, HP_HASHVAL, hash, &cbHash, 0)) 
    { 
     dwStatus = GetLastError(); 
     printf("CryptGetHashParam failed: %d\n", dwStatus); 
     CryptReleaseContext(cryptProv, 0); 
     CryptDestroyHash(cryptHash); 
     *result = dwStatus; 
     return NULL; 
    } 
    for (i = 0; i < cbHash; i++) 
    { 
     strHash[i * 2] = hex[hash[i] >> 4]; 
     strHash[(i * 2) + 1] = hex[hash[i] & 0xF]; 
    } 
    CryptReleaseContext(cryptProv, 0); 
    CryptDestroyHash(cryptHash); 
    return strHash; 
}