Использование функций HMAC vs EVP в OpenSSL

Это очень простой вопрос, но в чем разница между EVP и HMAC? EVP – это дайджест сообщений, но как он отличается от того, что генерируется HMAC?

… в чем разница между EVP и HMAC

EVP_* – это интерфейс высокого уровня. HMAC_* , AES_* и друзья – примитивы нижнего уровня. Вы можете работать с ними, но рекомендуется, чтобы вы работали с EVP_* . HMAC_* основаны на программном обеспечении и не используют аппаратное обеспечение.

Функции EVP_* позволят вам легко поменять местами различные hashи, и код по существу не EVP_* . И вы будете использовать аппаратное ускорение, например AES-NI для AES-CMAC, если оно доступно.

Ниже приведен пример OpenSSL на основе https://www.openssl.org/docs/crypto/EVP_DigestInit.html .

 EVP_MD_CTX* mdctx = NULL; const EVP_MD* md = NULL; unsigned char md_value[EVP_MAX_MD_SIZE]; int md_len = 0; char message[] = "Now is the time for all good men to " "come to the aide of their country\n"; OpenSSL_add_all_digests(); md = EVP_get_digestbyname("SHA1"); mdctx = EVP_MD_CTX_create(); if(!EVP_DigestInit_ex(mdctx, md, NULL)) handleError(); if(!EVP_DigestUpdate(mdctx, message, strlen(message))) handleError(); if(!EVP_DigestFinal_ex(mdctx, md_value, &md_len)) handleError(); if(!EVP_MD_CTX_destroy(mdctx)) handleError(); printf("Digest is: "); for(int i = 0; i < md_len; i++) printf("%02x", md_value[i]); printf("\n"); 

Теперь, и HMAC немного отличается от Hash. HMAC - это хеш-ключ, в то время как hash не используется. Вы также можете использовать функции EVP_* для HMAC'ing. Ниже приведена вики-страница OpenSSL. Подписание и проверка EVP :

 EVP_MD_CTX* mdctx = NULL; const EVP_MD* md = NULL; EVP_PKEY *pkey = NULL; unsigned char md_value[EVP_MAX_MD_SIZE]; int md_len = 0; char message[] = "Now is the time for all good men to " "come to the aide of their country\n"; OpenSSL_add_all_digests(); if(!(mdctx = EVP_MD_CTX_create())) handleError(); if(!(md = EVP_get_digestbyname("SHA1"))) handleError(); if(!(pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, "password", strlen("password")))) handleError(); if(1 != EVP_DigestSignInit(mdctx, NULL, md, NULL, pkey)) handleError(); /* Call update with the message */ if(1 != EVP_DigestSignUpdate(mdctx, message, strlen(message))) handleError(); if(1 != EVP_DigestSignFinal(mdctx, md_value, &md_len)) handleError(); printf("HMAC is: "); for(int i = 0; i < md_len; i++) printf("%02x", md_value[i]); printf("\n"); 

Интерфейс низкого уровня будет выглядеть так:

 EVP_MD_CTX* mdctx = NULL; const EVP_MD* md = NULL; unsigned char md_value[EVP_MAX_MD_SIZE]; int md_len = 0; char message[] = "Now is the time for all good men to " "come to the aide of their country\n"; OpenSSL_add_all_digests(); md = EVP_get_digestbyname("SHA1"); mdctx = EVP_MD_CTX_create(); if(!HMAC_Init_ex(mdctx, key, sizeof(key), md, NULL)) handleError(); if(!HMAC_Update(mdctx, message, strlen(message))) handleError(); if(!HMAC_Final(mdctx, md_value, &md_len)) handleError(); if(!HMAC_CTX_cleanup(mdctx)) handleError(); printf("HMAC is: "); for(int i = 0; i < md_len; i++) printf("%02x", md_value[i]); printf("\n"); 

Для получения правильной ключевой структуры для HMAC вам необходимо использовать функцию EVP_PKEY_new_mac_key. И не забудьте освободить его с помощью EVP_PKEY_free.