我希望使用 openssl 和 C + + 创建一个具有 sha256的 hash。我知道在 使用 OpenSSL 库在 C + + 中生成 SHA 散列有一个类似的帖子,但我正在寻找特别创建 sha256。
更新:
似乎是一个包含路径的问题。它找不到任何 OpenSSL 函数,即使我包含
#include "openssl/sha.h"
我在构建中包含了路径
-I/opt/ssl/include/ -L/opt/ssl/lib/ -lcrypto
我认为你只需要将 SHA1函数替换为 SHA256函数,并在你的文章中使用来自链接的 tatk 代码
我是这么做的:
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; }
它的名字是这样的:
static unsigned char buffer[65]; sha256("string", buffer); printf("%s\n", buffer);
一个更“ 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; }
性病
#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; }
使用 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; }
这种更高级别接口的优点是,您只需将 EVP_sha256()调用与另一个摘要的函数(例如 EVP_sha512())交换,就可以使用不同的摘要。所以它增加了一些灵活性。
EVP_sha256()
EVP_sha512()
下面是我个人使用的函数——我只是从 sha-1哈希函数中派生出来的:
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; }
如果要计算文件的 sha256散列..。
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