Пример MSDN HMAC-SHA1 не работает - PullRequest
5 голосов
/ 25 сентября 2011

Создание шагов HMAC с использованием CryptoAPI находится здесь: http://msdn.microsoft.com/en-us/library/Aa379863

  • Для вычисления HMAC

    1. Получить указатель на поставщика услуг шифрования Microsoft (CSP), вызывая CryptAcquireContext.
    2. Создать дескриптор объекта HMAChash, вызвав CryptCreateHash. Передайте CALG_HMAC в параметре Algid. Пройти дескриптор симметричного ключа в параметре hKey. Это симметричный ключ является ключом, используемым для вычисления HMAC.
    3. Укажите тип хеша, который будет использоваться при вызове CryptSetHashParam с параметром dwParam, установленным в значение HP_HMAC_INFO. Параметр pbData должен указывать на инициализированный Структура HMAC_INFO.
    4. Вызовите CryptHashData, чтобы начать вычисление HMAC данных. первый вызов CryptHashData приводит к объединению значения ключа с использованием оператор XOR с внутренней строкой и данными. Результат операция XOR хешируется, а затем целевые данные для HMAC (на который указывает параметр pbData, переданный в вызове CryptHashData) хэшируется. При необходимости последующие звонки CryptHashData может тогда быть сделан, чтобы закончить хеширование цели данные.
    5. Вызовите CryptGetHashParam с параметром dwParam, установленным в HP_HASHVAL. Этот вызов приводит к завершению внутреннего хеша и внешняя строка для объединения с помощью XOR с ключом. Результат Операция XOR хешируется, а затем результат внутреннего хэша (завершено на предыдущем шаге) хэшируется. Внешний хеш тогда закончили и вернули в параметре pbData и длину в Параметр dwDataLen.

Я не могу, потому что жизнь меня заставляет это работать. У меня есть все шаги по порядку, и я все еще не могу запустить мою программу. Ошибки во время работы:

Error in CryptImportKey 0x8009007
Error in CryptCreatHash 0x8009003
Error in CryptSetHashParam 0x00000057
Error in CryptHashData 0x00000057
Error in CryptGetHashParam 0x00000057

Может кто-нибудь помочь?

#include <iostream>
#include <windows.h>
#include <wincrypt.h>
using namespace std;

#define CALG_HMAC CALG_SHA1

int main()
{
//--------------------------------------------------------------------
// Declare variables.
HCRYPTPROV  hProv       = NULL;
HCRYPTHASH  hHash       = NULL;
HCRYPTKEY   hKey        = NULL;
BYTE DesKeyBlob[] = { 0x70,0x61,0x73,0x73,0x77,0x6F,0x72,0x64 };
HCRYPTHASH  hHmacHash   = NULL;
PBYTE       pbHash      = NULL;
DWORD       dwDataLen   = 20;
BYTE        Data[]     = {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
HMAC_INFO   HmacInfo;

//--------------------------------------------------------------------
// Zero the HMAC_INFO structure
ZeroMemory(&HmacInfo, sizeof(HmacInfo));
HmacInfo.HashAlgid = CALG_HMAC;
HmacInfo.pbInnerString = (BYTE*)0x36;
HmacInfo.cbInnerString = 0;
HmacInfo.pbOuterString = (BYTE*)0x5C;
HmacInfo.cbOuterString = 0;

// Step 1
if (!CryptAcquireContext(
    &hProv,                   // handle of the CSP
    NULL,                     // key container name
    NULL,                     // CSP name
    PROV_RSA_FULL,            // provider type
    CRYPT_VERIFYCONTEXT))     // no key access is requested
{
   printf(" Error in AcquireContext 0x%08x \n",
          GetLastError());
}

//--------------------------------------------------------------------
//Step 2
//in step two, we need the hash key used to be imported?
//imports the key used...  as hKey1
if(!CryptImportKey(
       hProv,
       DesKeyBlob,
       sizeof(DesKeyBlob),
       0,
       CRYPT_EXPORTABLE,
       &hKey ))
{
       printf("Error in !CryptImportKey 0x%08x \n",
          GetLastError());
}

if (!CryptCreateHash(
    hProv,      // handle of the CSP
    CALG_HMAC,  // hash algorithm to use
    hKey,       // hash key this shoudl point to a key used to compute the HMAC?
    0,          // reserved
    &hHmacHash  // address of hash object handle
)){
   printf("Error in CryptCreateHash 0x%08x \n",
          GetLastError());
}
// Step 3

if (!CryptSetHashParam(
    hHmacHash,//hProv,//hHash,//hHmacHash,                // handle of the HMAC hash object
    HP_HMAC_INFO,             // setting an HMAC_INFO object
    (BYTE*)&HmacInfo,         // the HMAC_INFO object
    0))                       // reserved
{
   printf("Error in CryptSetHashParam 0x%08x \n", 
          GetLastError());
}

//Step 4

if (!CryptHashData(
    hHmacHash,                // handle of the HMAC hash object
    Data,                    // message to hash
    sizeof(Data),            // number of bytes of data to add
    0))                       // flags
{
   printf("Error in CryptHashData 0x%08x \n", 
          GetLastError());
}
//Step 5

if (!CryptGetHashParam(
    hHmacHash,                 // handle of the HMAC hash object
    HP_HASHVAL,                // query on the hash value
    pbHash,                    // pointer to the HMAC hash value
    &dwDataLen,                // length, in bytes, of the hash
    0))
{
   printf("Error in CryptGetHashParam 0x%08x \n", GetLastError());
}

// Print the hash to the console.

printf("The hash is:  ");
for(DWORD i = 0 ; i < dwDataLen ; i++) 
{
   printf("%2.2x ",pbHash[i]);
}
printf("\n");

int a;

std::cin >> a;

    return 0;
}

1 Ответ

2 голосов
/ 25 сентября 2011

Вам может потребоваться (? 1 ) указать, какой алгоритм хеширования вы хотите использовать.

#define CALG_HMAC CALG_SHA1 // or CALG_MD5 etc

Редактировать

  • ПочемуВы инициализируете dwDataLen = 20 (вместо 0)?

  • Почему вы изменили алгоритм хеширования с SHA1

  • Почему вы не выходите изErrorExit больше (это само по себе предотвратит сбой вместо правильного сообщения об ошибке)

  • Вы используете CryptImportKey вместо CryptDeriveKey - такого нет даже в примере в MSDN.Не может быть совпадением, что CryptImportKey - это сбой вызова с 0x80090005 (NTE_BAD_DATA).Ключ не поддерживается вашим CSP!

  • Чтобы это работало, вам нужен доступ к ключу, так что вам по крайней мере нужно изменить CRYPT_VERIFY_CONTEXT на что-то другое (не знаю что);Я пытался использовать

.

if (!CryptAcquireContext(
            &hProv,                   
            NULL,                     
            MS_STRONG_PROV,           // allow 2048 bit keys, in case you need it
            PROV_RSA_FULL,            
            CRYPT_MACHINE_KEYSET))    // just a guess

Теперь моя программа приводит к 0x80090016: Keyset does not exist.Это может быть просто потому, что у меня нет этого набора ключей, или потому что я работаю в Linux под Wine.

Надеюсь, это поможет.


1 Скомпилировано в Linux с использованием:

i586-mingw32msvc-g++ -m32 -O2 -g test.cpp -o test.exe

Сбой при запуске (без параметров), но это может быть несовместимостью с вином (или тот факт, что я не прочитал источникчтобы увидеть, что он делает:))

...