Генерация хэша HMAC SHA256 с использованием ключа в С++

Я ищу какую-то функцию или способ, который вернул бы хэш HMAC SHA256 в С++ с использованием секретного ключа. Я видел документацию Crypto++ и OpenSSL, но она не принимает дополнительный параметр секретного ключа для вычисления. Может ли кто-нибудь помочь мне, предоставив некоторую информацию, фрагменты кода или ссылки.


person RDoonds    schedule 09.06.2016    source источник
comment
HMAC по определению имеют ключевой ввод, а также ввод данных. дайте ссылку на HMAC, с которым у вас возникли проблемы. См. определение HMAC. HMAC используют хеш-функцию, поэтому вы увидите некоторую форму объединения имен.   -  person zaph    schedule 10.06.2016
comment
Я удалил теги OpenSSL и Crypto++. Вы должны добавить теги, когда используете технологию; а не что-то вроде Что мне использовать и как мне это сделать?   -  person jww    schedule 10.06.2016


Ответы (6)


В документации OpenSSL для HMAC четко указано требование "ключа ' как часть инициализации контекста.

int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len,
               const EVP_MD *md, ENGINE *impl);

HMAC() вычисляет код аутентификации сообщения из n байтов в d, используя хеш-функцию evp_md и ключ key длиной key_len байт.

person Community    schedule 10.06.2016

Вы можете использовать библиотеку POCO.

Образец кода:

class SHA256Engine : public Poco::Crypto::DigestEngine
{
public:
    enum
    {
        BLOCK_SIZE = 64,
        DIGEST_SIZE = 32
    };

    SHA256Engine()
            : DigestEngine("SHA256")
    {
    }

};


Poco::HMACEngine<SHA256Engine> hmac{secretKey};
hmac.update(string);

std::cout << "HMACE hex:" << Poco::DigestEngine::digestToHex(hmac.digest()) << std::endl;// lookout difest() calls reset ;)

Пример интеграции с POCO с помощью cmake install:

mkdir build_poco/
cd build_poco/ && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install ../poco/

CMakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.8)
PROJECT(SamplePoco)

SET(CMAKE_CXX_STANDARD 14)

SET(SOURCE_FILES
        src/main.cpp
        )

SET(_IMPORT_PREFIX lib/build_poco/install)

INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoFoundationTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoNetTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoJSONTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoXMLTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoCryptoTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoUtilTargets.cmake)
INCLUDE(lib/build_poco/install/lib/cmake/Poco/PocoNetSSLTargets.cmake)


ADD_EXECUTABLE(SamplePoco ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(SamplePoco
        Poco::Foundation
        Poco::Crypto
        Poco::Util
        Poco::JSON
        Poco::NetSSL
        )
TARGET_INCLUDE_DIRECTORIES(SamplePoco PUBLIC src/)

Здесь используется пример реализации: https://github.com/gelldur/abucoins-api-cpp

person Dawid Drozd    schedule 07.10.2017

Ниже приведен пример функции для генерации SHA256-HMAC с использованием Crypto++.

#include <string>
#include <string_view>

#include <cryptopp/filters.h>
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::HashFilter;

#include <cryptopp/hmac.h>
using CryptoPP::HMAC;

#include <cryptopp/sha.h>
using CryptoPP::SHA256;

std::string CalcHmacSHA256(std::string_view decodedSecretKey, std::string_view request)
{
    // Calculate HMAC
    HMAC<SHA256> hmac(reinterpret_cast<CryptoPP::byte const*>(decodedSecretKey.data()), decodedSecretKey.size());

    std::string calculated_hmac;
    auto sink = std::make_unique<StringSink>(calculated_hmac);

    auto filter = std::make_unique<HashFilter>(hmac, sink.get());
    sink.release();

    StringSource(reinterpret_cast<CryptoPP::byte const*>(request.data()), request.size(), true, filter.get()); // StringSource
    filter.release();

    return calculated_hmac;
}

#include <iostream>

int main() {
    std::cout << CalcHmacSHA256("key", "data");
}

Источником является спецификация CME iLink2.

person Dmytro Ovdiienko    schedule 29.05.2020
comment
Страница, на которую вы ссылаетесь, не использует make_unique - person M.M; 25.01.2021
comment
После создания объекта HashFilter я вызываю функцию-член std::unique_ptr::release, чтобы передать право собственности с unique_ptr на HashFilter. - person Dmytro Ovdiienko; 25.01.2021
comment
Правильно, версия CME этой функции не использует std::unique_ptr - person Dmytro Ovdiienko; 25.01.2021
comment
Хорошо, это имеет смысл - person M.M; 25.01.2021

Для согласованности ниже приведен пример функции для создания SHA256-HMAC с использованием OpenSSL.

#include <openssl/sha.h>
#include <openssl/hmac.h>

#include <string>
#include <string_view>
#include <array>

std::string CalcHmacSHA256(std::string_view decodedKey, std::string_view msg)
{
    std::array<unsigned char, EVP_MAX_MD_SIZE> hash;
    unsigned int hashLen;

    HMAC(
        EVP_sha256(),
        decodedKey.data(),
        static_cast<int>(decodedKey.size()),
        reinterpret_cast<unsigned char const*>(msg.data()),
        static_cast<int>(msg.size()),
        hash.data(),
        &hashLen
    );

    return std::string{reinterpret_cast<char const*>(hash.data()), hashLen};
}

Для справки, мне больше нравится Crypto++, так как в случае Crypto++ сгенерированный двоичный файл меньше. Недостатком является то, что Crypto++ не имеет модуля CMake.

person Dmytro Ovdiienko    schedule 28.10.2020

Спецификации для хеш-алгоритма SHA256 и для алгоритмов HMAC являются открытыми спецификациями, которые каждый может прочитать и реализовать самостоятельно.

Простой поиск в Google легко найдет открытые общедоступные спецификации для этих алгоритмов.

Фактически, в RFC 6234 есть даже общедоступная справочная реализация SHA256 и HMAC.

person Sam Varshavchik    schedule 09.06.2016
comment
правило №1: никогда не внедряйте криптографические библиотеки самостоятельно. - person Martin Kosicky; 21.09.2018
comment
Очевидно, кто-то нарушил правило №1 :) - person Myar; 14.11.2018

Вы можете использовать cpp-cryptlite для генерации хэша HMAC SHA256. Ниже приведен фрагмент кода:

std::string src_str = "abcdefg";
std::string secret_key = "xxxxxx";  // this value is an example
boost::uint8_t digest[32];  // cryptlite::sha256::HASH_SIZE
cryptlite::hmac<cryptlite::sha256>::calc(src_str, secret_key, digest);
// and digest is the output hash
person zhumm    schedule 27.12.2020
comment
Это зависит от библиотеки повышения. Это ни хорошо, ни плохо. Просто это так. - person Dmytro Ovdiienko; 26.01.2021