C, C++の標準ライブラリでは、SHA系アルゴリズムを生成するクラス、関数が、提供されていないです。
今回は、OpenSSLの関数でハッシュ値を生成しました。
実施環境
- OpenSSL 3.0系
- Visual Stuido 2022 Commnunity
OpenSSLのインストール
Win32/Win64 OpenSSLより Windows版 OpenSSLをダウンロードして、インストールします。64bit版のサンプルを作成するので、「Win64 OpenSSL v3.0.7」をインストールしました。
プロジェクトの設定
サンプルのプロジェクトの「追加のインクルードディレクトリ」に C:\Program Files\OpenSSL-Win64\include を追加します。「追加のライブラリディレクトリ」に C:\Program Files\OpenSSL-Win64\lib\VC を追加します。「追加のライブラリファイル」に libcrypto64MD.lib を追加します。
サンプルプログラム
その1
おそらく、コードが一番、短くて済む方法?。 関数 SHA256 を使います。
#include <iostream>
#include <string>
#include <vector>
#include <openssl/sha.h>
int main()
{
std::string str("Hello World");
unsigned char uchash1[20];
size_t hashSize1 = sizeof(uchash1);
unsigned char uchash2[32];
size_t hashSize2 = sizeof(uchash2);
SHA1((const unsigned char *)str.data(), str.size(), uchash1);
SHA256((const unsigned char*)str.data(), str.size(), uchash2);
std::vector<unsigned char> hash1;
hash1.resize(hashSize1);
for (size_t i = 0; i < hashSize1; i++) {
hash1.at(i) = uchash1[i];
}
std::vector<unsigned char> hash2;
hash2.resize(hashSize2);
for (size_t i = 0; i < hashSize2; i++) {
hash2.at(i) = uchash2[i];
}
std::cout << "SHA1" << std::endl;
for (size_t i = 0; i < hash1.size(); i++) {
std::cout << std::hex << (int)hash1.at(i);
}
std::cout << std::endl;
std::cout << "SHA256" << std::endl;
for (size_t i = 0; i < hash2.size(); i++) {
std::cout << std::hex << (int)hash2.at(i);
}
std::cout << std::endl;
}
その2
ハッシュ値の生成を細かく制御したい場合は、EVP digestを使います。
#include <iostream>
#include <string>
#include <vector>
#include <openssl/evp.h>
int main()
{
std::string str("Hello World");
EVP_MD_CTX* mdctx;
const EVP_MD* md;
md = EVP_get_digestbyname("SHA1");
if (md == NULL) {
printf("Unknown message digest %s\n", "SHA1");
exit(1);
}
mdctx = EVP_MD_CTX_new();
if (!EVP_DigestInit_ex2(mdctx, md, NULL)) {
printf("Message digest initialization failed.\n");
EVP_MD_CTX_free(mdctx);
exit(1);
}
if (!EVP_DigestUpdate(mdctx, str.data(), str.size())) {
printf("Message digest update failed.\n");
EVP_MD_CTX_free(mdctx);
exit(1);
}
unsigned char uchash1[20];
unsigned int hashSize1;
if (!EVP_DigestFinal_ex(mdctx, uchash1, &hashSize1)) {
printf("Message digest finalization failed.\n");
EVP_MD_CTX_free(mdctx);
exit(1);
}
EVP_MD_CTX_free(mdctx);
std::vector<unsigned char> hash1;
hash1.resize(hashSize1);
for (size_t i = 0; i < hashSize1; i++) {
hash1.at(i) = uchash1[i];
}
std::cout << "SHA1" << std::endl;
for (size_t i = 0; i < hash1.size(); i++) {
std::cout << std::hex << (int)hash1.at(i);
}
std::cout << std::endl;
md = EVP_get_digestbyname("SHA256");
if (md == NULL) {
printf("Unknown message digest %s\n", "SHA256");
exit(1);
}
mdctx = EVP_MD_CTX_new();
if (!EVP_DigestInit_ex2(mdctx, md, NULL)) {
printf("Message digest initialization failed.\n");
EVP_MD_CTX_free(mdctx);
exit(1);
}
if (!EVP_DigestUpdate(mdctx, str.data(), str.size())) {
printf("Message digest update failed.\n");
EVP_MD_CTX_free(mdctx);
exit(1);
}
unsigned char uchash2[32];
unsigned int hashSize2;
if (!EVP_DigestFinal_ex(mdctx, uchash2, &hashSize2)) {
printf("Message digest finalization failed.\n");
EVP_MD_CTX_free(mdctx);
exit(1);
}
EVP_MD_CTX_free(mdctx);
std::vector<unsigned char> hash2;
hash2.resize(hashSize2);
for (size_t i = 0; i < hashSize2; i++) {
hash2.at(i) = uchash2[i];
}
std::cout << "SHA256" << std::endl;
for (size_t i = 0; i < hash2.size(); i++) {
std::cout << std::hex << (int)hash2.at(i);
}
std::cout << std::endl;
}