How can I generate SHA1 or SHA2 hashes using the OpenSSL libarary?
I searched google and could not find any function or example code.
How can I generate SHA1 or SHA2 hashes using the OpenSSL libarary?
I searched google and could not find any function or example code.
From the command line, it's simply:
printf "compute sha1" | openssl sha1
You can invoke the library like this:
#include <stdio.h> #include <string.h> #include <openssl/sha.h> int main() { unsigned char ibuf[] = "compute sha1"; unsigned char obuf[20]; SHA1(ibuf, strlen(ibuf), obuf); int i; for (i = 0; i < 20; i++) { printf("%02x ", obuf[i]); } printf("\n"); return 0; }
OpenSSL has a horrible documentation with no code examples, but here you are:
#include <openssl/sha.h> bool simpleSHA256(void* input, unsigned long length, unsigned char* md) { SHA256_CTX context; if(!SHA256_Init(&context)) return false; if(!SHA256_Update(&context, (unsigned char*)input, length)) return false; if(!SHA256_Final(md, &context)) return false; return true; }
Usage:
unsigned char md[SHA256_DIGEST_LENGTH]; // 32 bytes if(!simpleSHA256(<data buffer>, <data length>, md)) { // handle error }
Afterwards, md
will contain the binary SHA-256 message digest. Similar code can be used for the other SHA family members, just replace "256" in the code.
If you have larger data, you of course should feed data chunks as they arrive (multiple SHA256_Update
calls).
correct syntax at command line should be
echo -n "compute sha1" | openssl sha1
otherwise you'll hash the trailing newline character as well.
Here is OpenSSL example of calculating sha-1 digest using BIO:
#include <openssl/bio.h> #include <openssl/evp.h> std::string sha1(const std::string &input) { BIO * p_bio_md = nullptr; BIO * p_bio_mem = nullptr; try { // make chain: p_bio_md <-> p_bio_mem p_bio_md = BIO_new(BIO_f_md()); if (!p_bio_md) throw std::bad_alloc(); BIO_set_md(p_bio_md, EVP_sha1()); p_bio_mem = BIO_new_mem_buf((void*)input.c_str(), input.length()); if (!p_bio_mem) throw std::bad_alloc(); BIO_push(p_bio_md, p_bio_mem); // read through p_bio_md // read sequence: buf <<-- p_bio_md <<-- p_bio_mem std::vector<char> buf(input.size()); for (;;) { auto nread = BIO_read(p_bio_md, buf.data(), buf.size()); if (nread < 0) { throw std::runtime_error("BIO_read failed"); } if (nread == 0) { break; } // eof } // get result char md_buf[EVP_MAX_MD_SIZE]; auto md_len = BIO_gets(p_bio_md, md_buf, sizeof(md_buf)); if (md_len <= 0) { throw std::runtime_error("BIO_gets failed"); } std::string result(md_buf, md_len); // clean BIO_free_all(p_bio_md); return result; } catch (...) { if (p_bio_md) { BIO_free_all(p_bio_md); } throw; } }
Though it's longer than just calling SHA1
function from OpenSSL, but it's more universal and can be reworked for using with file streams (thus processing data of any length).