Using OpenSSL's EVP interface (the following is for OpenSSL 1.1):
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <memory>
#include <openssl/evp.h>
struct OpenSSLFree {
void operator()(void* ptr) {
EVP_MD_CTX_free((EVP_MD_CTX*)ptr);
}
};
template <typename T>
using OpenSSLPointer = std::unique_ptr<T, OpenSSLFree>;
bool computeHash(const std::string& unhashed, std::string& hashed) {
OpenSSLPointer<EVP_MD_CTX> context(EVP_MD_CTX_new());
if(context.get() == NULL) {
return false;
}
if(!EVP_DigestInit_ex(context.get(), EVP_sha256(), NULL)) {
return false;
}
if(!EVP_DigestUpdate(context.get(), unhashed.c_str(), unhashed.length())) {
return false;
}
unsigned char hash[EVP_MAX_MD_SIZE];
unsigned int lengthOfHash = 0;
if(!EVP_DigestFinal_ex(context.get(), hash, &lengthOfHash)) {
return false;
}
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();
return true;
}
int main(int, char**)
{
std::string pw1 = "password1", pw1hashed;
std::string pw2 = "password2", pw2hashed;
std::string pw3 = "password3", pw3hashed;
std::string pw4 = "password4", pw4hashed;
computeHash(pw1, pw1hashed);
computeHash(pw2, pw2hashed);
computeHash(pw3, pw3hashed);
computeHash(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.
OPENSSL_NO_SHA256
to see what's wrong. The-lcrypto
parameter should be correct. – Hora