使用 OpenSSL 和 C++ 生成 sha256

发布于 2024-08-21 16:40:08 字数 406 浏览 5 评论 0原文

我正在寻找使用 openssl 和 C++ 使用 sha256 创建哈希。我知道 Generate SHA hash in C++ using OpenSSL library 有类似的帖子,但我我正在寻找专门创建 sha256 的方法。

更新:

包含路径似乎有问题。 它也找不到任何 OpenSSL 函数

#include "openssl/sha.h"

即使我在构建中包含了路径,

-I/opt/ssl/include/ -L/opt/ssl/lib/ -lcrypto 

I'm looking to create a hash with sha256 using openssl and C++. I know there's a similar post at Generate SHA hash in C++ using OpenSSL library, but I'm looking to specifically create sha256.

UPDATE:

Seems to be a problem with the include paths. It can't find any OpenSSL functions even though I included

#include "openssl/sha.h"

and I included the paths in my build

-I/opt/ssl/include/ -L/opt/ssl/lib/ -lcrypto 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

清引 2024-08-28 16:40:08

我是这样做的:

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);

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);
唔猫 2024-08-28 16:40:08

基于标准

#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;
}

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;
}
君勿笑 2024-08-28 16:40:08

使用 OpenSSL 的 EVP 接口(以下适用于 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;
}

:这个更高级别接口的优点是,您只需将 EVP_sha256() 调用替换为另一个摘要的函数(例如 EVP_sha512()),即可使用不同的摘要。所以它增加了一些灵活性。

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.

浮萍、无处依 2024-08-28 16:40:08

随着 OpenSSL 更新到 3.0,大多数解决方案将无法工作(因为 API 已弃用),建议使用 EVP 函数。下面的代码显示了我对 EVP 的看法,基于 OpenSSL 的官方文档

此实现使用纯 C 并在 Ubuntu 22.04 上进行了验证。

/**
 * Simple program to calculate message digest using openssl'l new EVP method
 *
 * Verified on Ubuntu 22.04 on Jan 29, 2023
 *
 * Install dependency:
 * sudo apt install make gcc libssl-dev -y
 *
 * To compile:
 * gcc sha256sum.c -o shasum.out -lcrypto
 *
 * To cross verify:
 * echo -n "Hello world" | sha256sum
 *
 * Author: Daniel Selvan D. <[email protected]>
 */

#include <stdio.h>
#include <string.h>

#include <openssl/evp.h>

// OpenSSL engine implementation
#define OPENSSL_ENGINE NULL

/**
 * Returns the SHA256 value of the input string
 *
 * @param string input string for which the hash to be calculated
 * @returns string (32 bytes) - SHA256 hash
 */
static const unsigned char *getShaSum(const unsigned char *string)
{
    EVP_MD_CTX *mdCtx = EVP_MD_CTX_new();
    unsigned char mdVal[EVP_MAX_MD_SIZE], *md;
    unsigned int mdLen, i;

    if (!EVP_DigestInit_ex(mdCtx, EVP_sha256(), OPENSSL_ENGINE))
    {
        printf("Message digest initialization failed.\n");
        EVP_MD_CTX_free(mdCtx);
        exit(EXIT_FAILURE);
    }

    // Hashes cnt bytes of data at d into the digest context mdCtx
    if (!EVP_DigestUpdate(mdCtx, string, strlen((const char *)string)))
    {
        printf("Message digest update failed.\n");
        EVP_MD_CTX_free(mdCtx);
        exit(EXIT_FAILURE);
    }

    if (!EVP_DigestFinal_ex(mdCtx, mdVal, &mdLen))
    {
        printf("Message digest finalization failed.\n");
        EVP_MD_CTX_free(mdCtx);
        exit(EXIT_FAILURE);
    }
    EVP_MD_CTX_free(mdCtx);

    printf("DEBUG: Digest is: ");
    for (i = 0; i < mdLen; i++)
        printf("%02x", mdVal[i]);
    printf("\n");

    md = mdVal;

    return md;
}

int main()
{
    // To calculate the hash of a file, read it and pass the pointer
    getShaSum("Hello world");

    exit(EXIT_SUCCESS);
}

这种更高级别接口的优点是您只需更换 EVP_sha256() 调用另一个摘要的函数,例如 EVP_sha512(),以使用不同的摘要。

With the OpenSSL update to 3.0 most of the solution won't work (as the APIs deprecated) and it's recommended to use the EVP functions. Below code shows my take with EVP based on OpenSSL's official documentation

This implementation uses pure C and verified on Ubuntu 22.04

/**
 * Simple program to calculate message digest using openssl'l new EVP method
 *
 * Verified on Ubuntu 22.04 on Jan 29, 2023
 *
 * Install dependency:
 * sudo apt install make gcc libssl-dev -y
 *
 * To compile:
 * gcc sha256sum.c -o shasum.out -lcrypto
 *
 * To cross verify:
 * echo -n "Hello world" | sha256sum
 *
 * Author: Daniel Selvan D. <[email protected]>
 */

#include <stdio.h>
#include <string.h>

#include <openssl/evp.h>

// OpenSSL engine implementation
#define OPENSSL_ENGINE NULL

/**
 * Returns the SHA256 value of the input string
 *
 * @param string input string for which the hash to be calculated
 * @returns string (32 bytes) - SHA256 hash
 */
static const unsigned char *getShaSum(const unsigned char *string)
{
    EVP_MD_CTX *mdCtx = EVP_MD_CTX_new();
    unsigned char mdVal[EVP_MAX_MD_SIZE], *md;
    unsigned int mdLen, i;

    if (!EVP_DigestInit_ex(mdCtx, EVP_sha256(), OPENSSL_ENGINE))
    {
        printf("Message digest initialization failed.\n");
        EVP_MD_CTX_free(mdCtx);
        exit(EXIT_FAILURE);
    }

    // Hashes cnt bytes of data at d into the digest context mdCtx
    if (!EVP_DigestUpdate(mdCtx, string, strlen((const char *)string)))
    {
        printf("Message digest update failed.\n");
        EVP_MD_CTX_free(mdCtx);
        exit(EXIT_FAILURE);
    }

    if (!EVP_DigestFinal_ex(mdCtx, mdVal, &mdLen))
    {
        printf("Message digest finalization failed.\n");
        EVP_MD_CTX_free(mdCtx);
        exit(EXIT_FAILURE);
    }
    EVP_MD_CTX_free(mdCtx);

    printf("DEBUG: Digest is: ");
    for (i = 0; i < mdLen; i++)
        printf("%02x", mdVal[i]);
    printf("\n");

    md = mdVal;

    return md;
}

int main()
{
    // To calculate the hash of a file, read it and pass the pointer
    getShaSum("Hello world");

    exit(EXIT_SUCCESS);
}

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.

酒与心事 2024-08-28 16:40:08

自 openssl 3.0 起,函数“SHA256_Init”“SHA256_Update”“SHA256_Final”已弃用,这是获取 sha256 的新方法

#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include "openssl/sha.h"

using namespace std;

string sha256(const string inputStr)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
    const unsigned char* data = (const unsigned char*)inputStr.c_str();
    SHA256(data, inputStr.size(), hash);
    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("test") << endl;
    cout << sha256("test2") << endl;
    return 0;
}

the functions "SHA256_Init" "SHA256_Update" "SHA256_Final" is deprecated since openssl 3.0, this is the new way to get sha256

#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include "openssl/sha.h"

using namespace std;

string sha256(const string inputStr)
{
    unsigned char hash[SHA256_DIGEST_LENGTH];
    const unsigned char* data = (const unsigned char*)inputStr.c_str();
    SHA256(data, inputStr.size(), hash);
    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("test") << endl;
    cout << sha256("test2") << endl;
    return 0;
}
触ぅ动初心 2024-08-28 16:40:08

我真的很喜欢 @villapx 回复,但我的编辑被拒绝了,所以我将发布现代 C++ 处理指针生命周期的实现。

#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];
    size_t lengthOfHash = 0;

    if(!EVP_DigestFinal_ex(context.get(), hash, &lengthOfHash)) {
        return false;
    }

    std::stringstream ss;
    for(size_t i{}; 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;
}

I really liked @villapx reply but my edit was rejected so I will post modern c++ take on handling pointer lifecycle for his implementation.

#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];
    size_t lengthOfHash = 0;

    if(!EVP_DigestFinal_ex(context.get(), hash, &lengthOfHash)) {
        return false;
    }

    std::stringstream ss;
    for(size_t i{}; 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;
}
夏花。依旧 2024-08-28 16:40:08

如果你想计算文件的 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

If you want to compute the sha256 hash of a file...

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
黯淡〆 2024-08-28 16:40:08

这是我个人使用的函数 - 我只是从用于 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;
}

Here's the function I personally use - I simply derived it from the function I used for sha-1 hashing:

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;
}
救星 2024-08-28 16:40:08

从 OpenSSL 3.0 开始,OpenSSL 已弃用大部分旧版(例如 SHA.h)Api,因此我不建议使用它,而是迁移到新的 OpenSSL 3.xx API
请参阅 https://www.openssl.org/docs/man3.0 /man7/migration_guide.html

现在关于您的问题:

  • 创建和创建使用 EVP_MD_CTX_new() 初始化新的摘要上下文
  • 使用 EVP_DigestInit_ex() 初始化摘要上下文,以使用特定的摘要类型,例如 EVP_sha256() 以及可选的您的 ENGINE Impl
  • 使用 EVP_DigestUpdate() 哈希您的字节 使用
  • EVP_DigestFinal_ex() 检索摘要值 使用
  • EVP_MD_CTX_free 释放您的上下文>

PS:不要忘记为输出摘要分配内存,在EVP_sha256()的情况下可以使用SHA256_DIGEST_LENGTH,并且显然可以处理任何错误

OpenSSL deprecated most of the older (Ex : SHA.h) Api starting OpenSSL 3.0 so i do not recommend using it, but rather migrate to the new OpenSSL 3.xx API
see https://www.openssl.org/docs/man3.0/man7/migration_guide.html

Now regarding your question :

  • Create & Init a new digest context using EVP_MD_CTX_new()
  • Initialize the Digest Context using EVP_DigestInit_ex() to use a specific digest type like EVP_sha256() and optionally your ENGINE Impl
  • Hash your bytes using EVP_DigestUpdate()
  • Retrieve the Digest value using EVP_DigestFinal_ex()
  • Free your context using EVP_MD_CTX_free

P.S : Do not forget to allocate memory for your output Digest, you can use SHA256_DIGEST_LENGTH in the case of EVP_sha256(), and obviously handle any errors

最美的太阳 2024-08-28 16:40:08

更“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;
}

A more "C++"ish version

#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;
}
心房的律动 2024-08-28 16:40:08

我认为您只需将 SHA1 函数替换为 SHA256 函数,并使用帖子中链接中的 tatk 代码

I think that you only have to replace SHA1 function with SHA256 function with tatk code from link in Your post

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文