我正在寻找一种在C++中使用密钥返回HMAC SHA256哈希的函数或方法。我已经看过Crypto++和OpenSSL的文档,但它们不接受额外的密钥参数进行计算。请问有人可以通过提供一些信息、代码片段或链接来帮助我吗?
我正在寻找一种在C++中使用密钥返回HMAC SHA256哈希的函数或方法。我已经看过Crypto++和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++没有CMake模块。
-lssl -lcrypto
键吗? - Dmytro Ovdiienkofind_package(OpenSSL REQUIRED)
,然后使用TARGET_LINK_LIBRARIES (${PROJECT_NAME} OpenSSL::Crypto)
。 - Dmytro Ovdiienko您可以使用 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 ;)
mkdir build_poco/
cd build_poco/ && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install ../poco/
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/)
#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规范
make_unique
。 - M.MHashFilter
对象,我调用std::unique_ptr::release
成员函数将所有权从unique_ptr
释放到HashFilter
。 - Dmytro Ovdiienkostd::unique_ptr
。 - Dmytro OvdiienkoHMAC 的 OpenSSL 文档明确指出,上下文初始化的一部分需要“密钥”。
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len,
const EVP_MD *md, ENGINE *impl);
我不得不稍微修改@DmytroOvdiienko的答案才能获得十六进制输出:
#include <iomanip>
...
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
);
std::stringstream out;
for (unsigned int i=0; i < hashLen; i++) {
out << std::setfill('0') << std::setw(2) << std::right << std::hex << (int)hash.data()[i];
}
return out.str();
}
int main(int, char**) {
std::string key = "ESiFg448MqOmhQyxbt6HEHHPnAA1OE8nX0o9ANIVMIvWLISQS0MivDrkZvnBxMEI";
std::string msg = "foo";
std::string_view key_view{key};
std::string_view msg_view{msg};
std::cout << CalcHmacSHA256(key_view, msg_view) << std::endl;
}
使用 <iomanip>
、setfill
、setw
、right
来确保单个十六进制值前缀为 0。另一种选择是使用 boost 库:
#include <boost/format.hpp>
...
out << boost::format("%02x") % (int)hash.data()[i];
您可以使用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