Generate sha256 with OpenSSL and C++
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'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.