MD5 на основе Crypto API

Полезная в хозяйстве вещь. Лично мне понадобился для генерации 128 битных ключей для потокового шифрования (ключик можно и не передавать, а просто посчитать хеш определенного места в пакете).

#include 

// hash_value указатель на >=16 байтный буфер напр. unsigned char hash[16];
BOOL md5(unsigned char *hash_value,unsigned char *string,DWORD count)
{
 HCRYPTPROV hProv;
 HCRYPTHASH hHash;

 // Инициализация контекста криптопровайдера
 if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0))
 {
  // Cоздание хеш-объекта
  if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
  {
   // Передача хешируемых данных хэш-объекту.
   if (CryptHashData(hHash, string, count, 0))
   {
    // Получение хеш-значения
    count = 16;
    if (CryptGetHashParam(hHash, HP_HASHVAL, hash_value, &count, 0)) return TRUE;
   }
  }
 }

 return FALSE;
}

^ Как оказалось этот код наотрез отказываться работать в Windows XP Home Edition, которая сейчас поставляется с большинством нетбуков.

Полистав MSDN у меня родился этот код:
#define MD5_SIZE 16
BOOL md5(unsigned char *hash_value,unsigned char *string,int count) {
 HCRYPTPROV hProv;
 HCRYPTHASH hHash;
 BOOL res=FALSE;
 char *keyName=NULL; DWORD dwFlags=0;

 // Инициализация контекста криптопровайдера
init_crypt:
 if (!CryptAcquireContext(&hProv, keyName, NULL, PROV_RSA_FULL, dwFlags))
 {
  if(GetLastError() != NTE_BAD_KEYSET) return FALSE;
  if(!dwFlags) 
  { 
   keyName="_"; dwFlags=CRYPT_MACHINE_KEYSET;  
   goto init_crypt;  
  }
  dwFlags=CRYPT_NEWKEYSET; 
  goto init_crypt; 
 }

 // Cоздание хеш-объекта
 if (CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
 {
  // Передача хешируемых данных хэш-объекту.
  if (CryptHashData(hHash, string, count, 0))
  {
   // Получение хеш-значения
   count = MD5_SIZE;
   if (CryptGetHashParam(hHash, HP_HASHVAL, hash_value, &count, 0)) res=TRUE;
  }
  CryptDestroyHash(hHash);
 }

 CryptReleaseContext(hProv,0);
 return res;
}

В случае если не удается создать стандартный контекст:
- проверяется не зарегистрирован ли в системе наш ключ;
- если нет, создается новый пользовательский ключ с именем "_", который в дальнейшем остается в системе.

Просветись по теме
blog comments powered by Disqus
сюда туда