使用OpenSSL和C++生成sha256

sta*_*tan 60 c++ unix openssl sha256

我正在寻找使用openssl和C++创建sha256的哈希.我知道在使用OpenSSL库的C++生成SHA哈希的帖子类似,但我希望专门创建sha256.

更新:

似乎是包含路径的问题.即使我包含它也找不到任何OpenSSL函数

#include "openssl/sha.h"
Run Code Online (Sandbox Code Playgroud)

我在构建中包含了路径

-I/opt/ssl/include/ -L/opt/ssl/lib/ -lcrypto 
Run Code Online (Sandbox Code Playgroud)

小智 67

我是这样做的:

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;
}
Run Code Online (Sandbox Code Playgroud)

它被称为这样:

static unsigned char buffer[65];
sha256("string", buffer);
printf("%s\n", buffer);
Run Code Online (Sandbox Code Playgroud)

  • 什么是sha256_hash_string(...)看起来你在代码中引用了一个不存在的函数... (13认同)
  • -1:"SHA1_Init(),SHA1_Update()和SHA1_Final()返回1表示成功,否则返回0.",http://www.openssl.org/docs/crypto/sha.htm. (3认同)
  • 请问如何解决第二个函数中的'byte'未声明的问题 (3认同)

Yol*_*ola 41

以std为基础

#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;
}
Run Code Online (Sandbox Code Playgroud)

  • 没有测试过这个,但这看起来比所有其他"C++"版本更清晰. (5认同)
  • 此代码编译并生成预期输出.在ubuntu上,您可以使用:sudo apt-get install libssl-dev && g ++ -lcrypto main.cc来编译它. (4认同)
  • 根据[OpenSSL docs](https://www.openssl.org/docs/manmaster/crypto/EVP_DigestInit.html),**"消息摘要的EVP接口几乎总是优先于低级接口使用这是因为代码对所使用的摘要变得透明,而且更加灵活."**所以在决定使用这段代码时要记住这一点,即确保你是_positive_你只会使用SHA256.否则,您更值得花时间学习EVP界面. (4认同)
  • @ Homer6 for g ++,从技术上讲,依赖项应该是[之后](http://stackoverflow.com/a/13784484/1053362)依赖于它的src文件(在Ubuntu 16.04.1上对我造成了复杂问题)。应该是:`g ++ main.cc -lcrypto` (2认同)

vil*_*apx 13

使用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;
}
Run Code Online (Sandbox Code Playgroud)

这种更高级别界面的优点是您只需要将EVP_sha256()调用与另一个摘要的功能交换出来,例如EVP_sha512(),使用不同的摘要.所以它增加了一些灵活性.

  • 没有 else 子句的 if 语句...如此...深...看不到光...尽管如此,还是被投票了,因为它使用了推荐的 EVP 接口! (3认同)
  • 对于来到这里的其他人:EVP_MD_CTX 可能是带有自定义删除器的唯一 ptr 。更干净的代码。只是在这里挑剔。std::unique_ptr&lt;EVP_MD_CTX, std::function&lt;void(EVP_MD_CTX*)&gt;&gt; mdCtx(EVP_MD_CTX_new(), [](EVP_MD_CTX* g) { EVP_MD_CTX_free(g); }); (3认同)
  • @LimitedAtonement 确实,我将“适当的”错误检查作为练习留给了最终开发人员:) 但至少,我确保我做了所有的 if 检查只是为了突出他们需要的地方。感谢您的 +1! (2认同)

Dan*_*van 5

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

该实现使用 pureC并经过验证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. <danilselvan@gmail.com>
 */

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

Run Code Online (Sandbox Code Playgroud)

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