Generate sha256 with OpenSSL and C++
Solution 1
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);
Solution 2
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;
}
Solution 3
Using OpenSSL's EVP interface (the following is for 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, e.g. EVP_sha512()
, to use a different digest. So it adds some flexibility.
Solution 4
A more "C++"ish version
#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;
}
Solution 5
Here's the function I personally use - I simply derived it from the function I used for sha-1
hashing:
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;
}
stan
Updated on July 05, 2022Comments
-
stan almost 2 years
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.
UPDATE:
Seems to be a problem with the include paths. It can't find any OpenSSL functions even though I included
#include "openssl/sha.h"
and I included the paths in my build
-I/opt/ssl/include/ -L/opt/ssl/lib/ -lcrypto
-
TCB13 almost 13 yearsHi, for everyone using the great QT :) - You can also use this, just add to your project file
LIBS +=-lcrypto
and then you can just convert the code to a class and everything will work fine ;) -
jww over 12 years-1: “SHA1_Init(), SHA1_Update() and SHA1_Final() return 1 for success, 0 otherwise.”, openssl.org/docs/crypto/sha.htm.
-
jww over 12 years-1: “SHA1_Init(), SHA1_Update() and SHA1_Final() return 1 for success, 0 otherwise.”, openssl.org/docs/crypto/sha.htm.
-
Max over 12 yearsdidn't want to obscure the code with C-style return value checks. DIY if you care
-
jww over 12 years"DIY if you care" - sorry to inconvenience you. Folks will blindly copy/paste it. Ignoring return values is a dangerous practice, and should not be demonstarated (especially in high integrity code).
-
stan about 12 yearsHaven't tested this out, but this definitely looks cleaner than all the other "C++" versions.
-
Homer6 over 11 yearsThis code compiles and produced the expected output. On ubuntu, you can use: sudo apt-get install libssl-dev && g++ -lcrypto main.cc to compile it.
-
Konrad Rudolph over 11 years@noloader Irrelevant since these functions aren’t used here.
-
jww over 11 years@Konrad Rudolph Its the same API interface, and the OpenSSL man pages lead back to the SHA1 stuff. Ignoring return values in high integrity software is very bad karma.
-
UpAndAdam almost 10 yearsWhat the heck is sha256_hash_string(...) looks like you reference a non-existent function in your code...
-
Admin over 9 years@jww I cried reading your comment because it's true, people will write "secure" applications by copy-and-paste programming. But I also agree to some degree with Max only because it shouldn't be on our shoulders to prevent stupid people from incorrectly using our knowledge, or stupid people from using "secure" software written by a copy and paste programmer.
-
omni almost 8 yearsThis solution is actually better than the accepted one, as ostringstream is much, much safer than messing with arrays and
sprintf
. -
villapx over 7 yearsAccording to the OpenSSL docs, "The EVP interface to message digests should almost always be used in preference to the low level interfaces. This is because the code then becomes transparent to the digest used and much more flexible." So keep that in mind when deciding to use this code, i.e. make sure you're positive that you'll only ever use SHA256. Otherwise, it's more worth your time to learn the EVP interface.
-
toinetoine over 7 years@Homer6 for g++, technically the dependency should be after the src file that depends on it (caused complication issues for me on Ubuntu 16.04.1). Should be:
g++ main.cc -lcrypto
-
Admin almost 7 yearsMay I ask how to solve the 'byte' in second function was not declared
-
Fnr almost 6 years
byte
is just as the name says, a byte (can be typedef'd with anunsigned char
).sha256_hash_string
I think he means the functionsha256
he previously defined -
Nasreddine Galfout about 5 yearsthis code does not check for errors, It is a shot on the foot do not copy paste with out making the appropriate Update
-
lmat - Reinstate Monica about 5 yearsif statements without else clauses ... so ... deep ... cannot see light ... Upvoted nonetheless because it uses the recommended EVP interface!
-
villapx about 5 years@LimitedAtonement Indeed, I left "proper" error checking as an exercise to the end developer :) but at a minimum, I made sure I did all the if-checks just to highlight where they're required. Thanks for the +1!
-
lmat - Reinstate Monica over 4 years"DIY if you care" But seriously now, who cares about error conditions?
-
Olivia Stork over 3 yearsIt's even better practice to use
std::byte
, but this code looks like C++98 only. -
csavvy over 3 yearsSorry,I know its very old. The prototype of
SHA256
isunsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md);
as mentioned here sha. May be i am referring old or not sure. As I need to calculate SHA256 of certain files , can you point me in right direction of openssl libs based onC
-
127 over 2 yearsthis one excludes 0s from resulting hash sometimes
-
Csuszmusz over 2 yearsfor anybody else coming here: EVP_MD_CTX could be a unique ptr with custom deleter . much cleaner code. just to nitpick here. std::unique_ptr<EVP_MD_CTX, std::function<void(EVP_MD_CTX*)>> mdCtx(EVP_MD_CTX_new(), [](EVP_MD_CTX* g) { EVP_MD_CTX_free(g); });