[英]Generate sha256 with OpenSSL and C++
I'm looking to create a hash with sha256 using openssl and C++. I know there's a similar post at Generate SHA hash in C++ using OpenSSL library , but I'm looking to specifically create sha256.我正在寻找使用 openssl 和 C++ 创建带有 sha256 的 hash。我知道在使用 OpenSSL 库在 C++ 中生成 SHA hash 中也有类似的帖子,但我正在寻找 sham25
UPDATE:更新:
Seems to be a problem with the include paths.似乎是包含路径的问题。 It can't find any OpenSSL functions even though I included
即使我包括在内,它也找不到任何 OpenSSL 函数
#include "openssl/sha.h"
and I included the paths in my build我在我的构建中包含了路径
-I/opt/ssl/include/ -L/opt/ssl/lib/ -lcrypto
Here's how I did it:这是我如何做到的:
void sha256_hash_string (unsigned char hash[SHA256_DIGEST_LENGTH], char outputBuffer[65])
{
int i = 0;
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
}
outputBuffer[64] = 0;
}
void sha256_string(char *string, char outputBuffer[65])
{
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, string, strlen(string));
SHA256_Final(hash, &sha256);
int i = 0;
for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
}
outputBuffer[64] = 0;
}
int sha256_file(char *path, char outputBuffer[65])
{
FILE *file = fopen(path, "rb");
if(!file) return -534;
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
const int bufSize = 32768;
unsigned char *buffer = malloc(bufSize);
int bytesRead = 0;
if(!buffer) return ENOMEM;
while((bytesRead = fread(buffer, 1, bufSize, file)))
{
SHA256_Update(&sha256, buffer, bytesRead);
}
SHA256_Final(hash, &sha256);
sha256_hash_string(hash, outputBuffer);
fclose(file);
free(buffer);
return 0;
}
It's called like this:它是这样叫的:
static unsigned char buffer[65];
sha256("string", buffer);
printf("%s\n", buffer);
std based基于标准
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
using namespace std;
#include <openssl/sha.h>
string sha256(const string str)
{
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, str.c_str(), str.size());
SHA256_Final(hash, &sha256);
stringstream ss;
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
ss << hex << setw(2) << setfill('0') << (int)hash[i];
}
return ss.str();
}
int main() {
cout << sha256("1234567890_1") << endl;
cout << sha256("1234567890_2") << endl;
cout << sha256("1234567890_3") << endl;
cout << sha256("1234567890_4") << endl;
return 0;
}
Using OpenSSL'sEVP interface (the following is for OpenSSL 1.1):使用 OpenSSL 的EVP 接口(以下针对 OpenSSL 1.1):
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <openssl/evp.h>
bool computeHash(const std::string& unhashed, std::string& hashed)
{
bool success = false;
EVP_MD_CTX* context = EVP_MD_CTX_new();
if(context != NULL)
{
if(EVP_DigestInit_ex(context, EVP_sha256(), NULL))
{
if(EVP_DigestUpdate(context, unhashed.c_str(), unhashed.length()))
{
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int lengthOfHash = 0;
if(EVP_DigestFinal_ex(context, hash, &lengthOfHash))
{
std::stringstream ss;
for(unsigned int i = 0; i < lengthOfHash; ++i)
{
ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
}
hashed = ss.str();
success = true;
}
}
}
EVP_MD_CTX_free(context);
}
return success;
}
int main(int, char**)
{
std::string pw1 = "password1", pw1hashed;
std::string pw2 = "password2", pw2hashed;
std::string pw3 = "password3", pw3hashed;
std::string pw4 = "password4", pw4hashed;
hashPassword(pw1, pw1hashed);
hashPassword(pw2, pw2hashed);
hashPassword(pw3, pw3hashed);
hashPassword(pw4, pw4hashed);
std::cout << pw1hashed << std::endl;
std::cout << pw2hashed << std::endl;
std::cout << pw3hashed << std::endl;
std::cout << pw4hashed << std::endl;
return 0;
}
The advantage of this higher level interface is that you simply need to swap out the EVP_sha256()
call with another digest's function, eg EVP_sha512()
, to use a different digest.这个更高级别接口的优点是您只需将
EVP_sha256()
调用替换为另一个摘要的函数,例如EVP_sha512()
,即可使用不同的摘要。 So it adds some flexibility.所以它增加了一些灵活性。
A more "C++"ish version一个更“C++”的版本
#include <iostream>
#include <sstream>
#include "openssl/sha.h"
using namespace std;
string to_hex(unsigned char s) {
stringstream ss;
ss << hex << (int) s;
return ss.str();
}
string sha256(string line) {
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, line.c_str(), line.length());
SHA256_Final(hash, &sha256);
string output = "";
for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
output += to_hex(hash[i]);
}
return output;
}
int main() {
cout << sha256("hello, world") << endl;
return 0;
}
Here's the function I personally use - I simply derived it from the function I used for sha-1
hashing:这是我个人使用的函数 - 我只是从我用于
sha-1
散列的函数中派生出来的:
char *str2sha256( const char *str, int length ) {
int n;
SHA256_CTX c;
unsigned char digest[ SHA256_DIGEST_LENGTH ];
char *out = (char*) malloc( 33 );
SHA256_Init( &c );
while ( length > 0 ) {
if ( length > 512 ) SHA256_Update( &c, str, 512 );
else SHA256_Update( &c, str, length );
length -= 512;
str += 512;
}
SHA256_Final ( digest, &c );
for ( n = 0; n < SHA256_DIGEST_LENGTH; ++n )
snprintf( &( out[ n*2 ] ), 16*2, "%02x", (unsigned int) digest[ n ] );
return out;
}
If you want to compute the sha256 hash of a file...如果你想计算一个文件的 sha256 hash ...
auto sha256 = [](std::string fname,
std::vector<unsigned char>& hash) -> bool {
std::unique_ptr<EVP_MD_CTX, void (*)(EVP_MD_CTX *)>
evpCtx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
EVP_DigestInit_ex(evpCtx.get(), EVP_sha256(), nullptr);
constexpr size_t buffer_size { 1 << 12 };
std::vector<char> buffer(buffer_size,'\0');
std::ifstream fp(fname, std::ios::binary);
if (!fp.is_open()) {
std::cerr << "Unable to open '" << fname << "'!\n";
return false;
}
while (fp.good()) {
fp.read(buffer.data(), buffer_size);
EVP_DigestUpdate (evpCtx.get(), buffer.data(), fp.gcount());
}
fp.close();
hash.resize(SHA256_DIGEST_LENGTH);
std::fill(hash.begin(), hash.end(), 0);
unsigned int len;
EVP_DigestFinal_ex (evpCtx.get(), hash.data(), &len);
return true;
};
...
std::vector<unsigned char> hash;
sha256("/etc/profile", hash);
std::stringstream out;
for (size_t i = 0; i < hash.size(); i++)
out << std::setfill('0') << std::setw(2)
<< std::hex << int(hash[i]);
std::string hashStr = out.str();
std::cout << hashStr << std::endl;
...
a3fe9f414586c0d3cacbe3b6920a09d8718e503bca22e23fef882203bf765065
With the OpenSSL update to 3.0 most of the solution won't work ( as the APIs deprecated ) and it's recommended to use the EVP
functions.随着 OpenSSL 更新到 3.0,大多数解决方案将无法使用(因为 API 已弃用),建议使用
EVP
函数。 Below code shows my take with EVP based on OpenSSL's official documentation下面的代码显示了我根据OpenSSL 的官方文档对EVP的看法
This implementation uses pure C
and verified on Ubuntu 22.04
此实现使用纯
C
并在Ubuntu 22.04
上验证
/**
* Simple program to calculate message digest using openssl'l new EVP method
*
* Verified on Ubuntu 22.04 on Jan 29, 2023
*
* Install dependency:
* sudo apt install make gcc libssl-dev -y
*
* To compile:
* gcc sha256sum.c -o shasum.out -lcrypto
*
* To cross verify:
* echo -n "Hello world" | sha256sum
*
* Author: Daniel Selvan D. <danilselvan@gmail.com>
*/
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
// OpenSSL engine implementation
#define OPENSSL_ENGINE NULL
/**
* Returns the SHA256 value of the input string
*
* @param string input string for which the hash to be calculated
* @returns string (32 bytes) - SHA256 hash
*/
static const unsigned char *getShaSum(const unsigned char *string)
{
EVP_MD_CTX *mdCtx = EVP_MD_CTX_new();
unsigned char mdVal[EVP_MAX_MD_SIZE], *md;
unsigned int mdLen, i;
if (!EVP_DigestInit_ex(mdCtx, EVP_sha256(), OPENSSL_ENGINE))
{
printf("Message digest initialization failed.\n");
EVP_MD_CTX_free(mdCtx);
exit(EXIT_FAILURE);
}
// Hashes cnt bytes of data at d into the digest context mdCtx
if (!EVP_DigestUpdate(mdCtx, string, strlen((const char *)string)))
{
printf("Message digest update failed.\n");
EVP_MD_CTX_free(mdCtx);
exit(EXIT_FAILURE);
}
if (!EVP_DigestFinal_ex(mdCtx, mdVal, &mdLen))
{
printf("Message digest finalization failed.\n");
EVP_MD_CTX_free(mdCtx);
exit(EXIT_FAILURE);
}
EVP_MD_CTX_free(mdCtx);
printf("DEBUG: Digest is: ");
for (i = 0; i < mdLen; i++)
printf("%02x", mdVal[i]);
printf("\n");
md = mdVal;
return md;
}
int main()
{
// To calculate the hash of a file, read it and pass the pointer
getShaSum("Hello world");
exit(EXIT_SUCCESS);
}
The advantage of this higher level interface is that you simply need to swap out the EVP_sha256()
call with another digest's function, eg EVP_sha512()
, to use a different digest.这个更高级别接口的优点是您只需将
EVP_sha256()
调用换成另一个摘要的 function,例如EVP_sha512()
,即可使用不同的摘要。
我认为您只需要使用来自您帖子中的链接的 tatk 代码将 SHA1 函数替换为 SHA256 函数
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.