使用 OpenSSL 库在 C++ 中生成 SHA 哈希
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/918676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generate SHA hash in C++ using OpenSSL library
提问by brianegge
回答by brianegge
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;
}
回答by AndiDog
OpenSSL has a horrible documentationwith no code examples, but here you are:
OpenSSL 有一个糟糕的文档,没有代码示例,但你在这里:
#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.
之后,md
将包含二进制 SHA-256 消息摘要。类似的代码可用于其他 SHA 系列成员,只需替换代码中的“256”即可。
If you have larger data, you of course should feed data chunks as they arrive (multiple SHA256_Update
calls).
如果您有更大的数据,您当然应该在数据块到达时提供数据块(多次SHA256_Update
调用)。
回答by mecano
correct syntax at command line should be
命令行中的正确语法应该是
echo -n "compute sha1" | openssl sha1
otherwise you'll hash the trailing newline character as well.
否则你也会散列尾随的换行符。
回答by Nayfe
Adaptation of @AndiDog version for big file:
大文件@AndiDog 版本的适配:
static const int K_READ_BUF_SIZE{ 1024 * 16 };
std::optional<std::string> CalcSha256(std::string filename)
{
// Initialize openssl
SHA256_CTX context;
if(!SHA256_Init(&context))
{
return std::nullopt;
}
// Read file and update calculated SHA
char buf[K_READ_BUF_SIZE];
std::ifstream file(filename, std::ifstream::binary);
while (file.good())
{
file.read(buf, sizeof(buf));
if(!SHA256_Update(&context, buf, file.gcount()))
{
return std::nullopt;
}
}
// Get Final SHA
unsigned char result[SHA256_DIGEST_LENGTH];
if(!SHA256_Final(result, &context))
{
return std::nullopt;
}
// Transform byte-array to string
std::stringstream shastr;
shastr << std::hex << std::setfill('0');
for (const auto &byte: result)
{
shastr << std::setw(2) << (int)byte;
}
return shastr.str();
}
回答by anton_rh
Here is OpenSSLexample of calculating sha-1digest using BIO:
这是使用BIO计算sha-1摘要的OpenSSL示例:
#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).
虽然它比仅仅SHA1
从OpenSSL调用函数要长,但它更通用,可以重新设计以用于文件流(从而处理任何长度的数据)。
回答by Alan CN
C versionof @Nayfe code, generating SHA1 hash from file:
@Nayfe 代码的C 版本,从文件生成 SHA1 哈希:
#include <stdio.h>
#include <openssl/sha.h>
static const int K_READ_BUF_SIZE = { 1024 * 16 };
unsigned char* calculateSHA1(char *filename)
{
if (!filename) {
return NULL;
}
FILE *fp = fopen(filename, "rb");
if (fp == NULL) {
return NULL;
}
unsigned char* sha1_digest = malloc(sizeof(char)*SHA_DIGEST_LENGTH);
SHA_CTX context;
if(!SHA1_Init(&context))
return NULL;
unsigned char buf[K_READ_BUF_SIZE];
while (!feof(fp))
{
size_t total_read = fread(buf, 1, sizeof(buf), fp);
if(!SHA1_Update(&context, buf, total_read))
{
return NULL;
}
}
fclose(fp);
if(!SHA1_Final(sha1_digest, &context))
return NULL;
return sha1_digest;
}
It can be used as follows:
它可以按如下方式使用:
unsigned char *sha1digest = calculateSHA1("/tmp/file1");
The resvariable contains the sha1 hash.
该水库变量包含SHA1哈希。
You can print it on the screen using the following for-loop:
您可以使用以下 for 循环将其打印在屏幕上:
char *sha1hash = (char *)malloc(sizeof(char) * 41);
sha1hash[41] = '##代码##';
int i;
for (i = 0; i < SHA_DIGEST_LENGTH; i++)
{
sprintf(&sha1hash[i*2], "%02x", sha1digest[i]);
}
printf("SHA1 HASH: %s\n", sha1hash);