【问题标题】:Generate SHA-3 hash in C++ using OpenSSL library使用 OpenSSL 库在 C++ 中生成 SHA-3 哈希
【发布时间】:2018-07-02 22:37:56
【问题描述】:

我已经广泛搜索了一个使用 OpenSSL 最近实现的 SHA-3 算法进行散列的代码示例,但找不到任何代码示例。有关于 SHA-1 和 SHA-3 的代码示例,但在库文件夹中快速搜索会发现 OpenSSL v1.1.1 中甚至没有 SHA3 函数名称?

我到处搜索,但这是相对较新的,我无法找到任何专门关于新算法的信息。

我发现这个线程 Generate SHA hash in C++ using OpenSSL library 涵盖 SHA-1 和 SHA-2,但库中实际上没有 SHA3 函数 - Keccak1600 似乎是 SHA-3 的名称?

【问题讨论】:

标签: openssl documentation sha-3


【解决方案1】:

在 Ubuntu 18.04 上,安装了 libssl-dev

//main.cpp

#include 
#include 
#include  //对于 std::ostringstream
#include  //用于 std::setw、std::hex 和 std::setfill
#include  //用于所有其他 OpenSSL 函数调用
#include  //对于 SHA512_DIGEST_LENGTH

//帮助函数将摘要字节打印为十六进制字符串
std::string bytes_to_hex_string(const std::vector& bytes)
{
    std::ostringstream 流;
    对于(uint8_t b:字节)
    {
        流 (b);
    }
    返回流.str();
}

//执行SHA3-512哈希
std::string sha3_512(const std::string& 输入)
{
    uint32_t 摘要长度 = SHA512_DIGEST_LENGTH;
    常量 EVP_MD* 算法 = EVP_sha3_512();
    uint8_t* 摘要 = static_cast(OPENSSL_malloc(digest_length));
    EVP_MD_CTX* 上下文 = EVP_MD_CTX_new();
    EVP_DigestInit_ex(上下文,算法,nullptr);
    EVP_DigestUpdate(context, input.c_str(), input.size());
    EVP_DigestFinal_ex(context, 摘要, &digest_length);
    EVP_MD_CTX_destroy(上下文);
    std::string 输出 = bytes_to_hex_string(std::vector(digest, digest + digest_length));
    OPENSSL_free(摘要);
    返回输出;
}

主函数()
{
    std::string 输出 = sha3_512(std::string("abcdef"));
    std::cout 

-lssl-lcrypto 链接以编译此代码:

/usr/bin/g++-10 main.cpp -lssl -lcrypto

输出:

01309a45c57cd7faef9ee6bb95fed29e5e2e0312af12a95fffeee340e5e5948b4652d26ae4b75976a53cc1612141af6e24df36517a61f46a1a05f59cf667046a

使用此工具验证输出:https://emn178.github.io/online-tools/sha3_512.html

【讨论】:

    【解决方案2】:

    在此页面上有一些用于生成哈希的通用示例代码:

    https://wiki.openssl.org/index.php/EVP_Message_Digests

    该特定代码会生成 SHA256 哈希。要将其转换为使用 SHA3,请将EVP_sha256() 的两个实例替换为EVP_sha3_224()EVP_sha3_256()EVP_sha3_384()EVP_sha3_512() 之一(视情况而定)。

    【讨论】:

      【解决方案3】:

      我写了一个简单的例子,它使用 openssl SHA-3 实现来计算从标准输入读取的所有数据的摘要。 使用命令行参数指定 SHA-3 摘要长度。 在 Linux Parrot(基于 Debian 的发行版)、libssl-dev 1.1.1c-1 上测试。

      Link to the repository.

      或者这里是源代码:

      #include <openssl/evp.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <unistd.h>
      #include <errno.h>
      /*
       * building on Debian requires libssl-dev package (sudo apt install libssl-dev)
       */
      
      #define BUF_SIZE 1024
      
      #define HANDLE_ERROR(msg) { fprintf(stderr, "%s\n", msg); exit(EXIT_FAILURE); }
      #define HANDLE_ERROR2(msg, mdctx) { fprintf(stderr, "%s\n", msg); EVP_MD_CTX_destroy(mdctx); exit(EXIT_FAILURE); }
      
      int main(int argc,  char * const argv[]) {
      
          int opt;
          char * endptr;
          char buffer[BUF_SIZE];
          int bytes_read;
      
          EVP_MD_CTX * mdctx;
          int val;
          unsigned char * digest;
          unsigned int digest_len;
          EVP_MD * algo = NULL;
      
          while ((opt = getopt(argc, argv, "t:")) != -1) {
              switch (opt) {
              case 't':
                  errno = 0;
      
                  val = strtol(optarg, &endptr, 10);
      
                  if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
                          || (errno != 0 && val == 0)) {
                      perror("Wrong value for t parameter");
                      exit(EXIT_FAILURE);
                  }
      
                  if (endptr == optarg) {
                      fprintf(stderr, "No value was found for t parameter\n");
                      exit(EXIT_FAILURE);
                  }
      
                  switch (val) {
                  case 224:
                      algo = EVP_sha3_224();
                      break;
                  case 256:
                      algo = EVP_sha3_256();
                      break;
                  case 384:
                      algo = EVP_sha3_384();
                      break;
                  case 512:
                      algo = EVP_sha3_512();
                      break;
                  default:
                      fprintf(stderr,"Wrong value for t parameter (valid values: 224, 256, 384, 512)");
                      exit(EXIT_FAILURE);
                  }
      
                  break;
              default: /* '?' */
                  fprintf(stderr, "Usage: %s [-t sha3_size]\n"
                          "Example program which calculates SHA-3 hash of data read from stdin.\n"
                          "Uses openssl implementation of SHA-3 algorithm.\n"
                          "sha3_size can be: 224, 256, 384, 512. Default is 256.\n",
                          argv[0]);
                  exit(EXIT_FAILURE);
              }
          }
      
          if (algo == NULL) {
              algo = EVP_sha3_256();
          }
      
      
          if ((mdctx = EVP_MD_CTX_create()) == NULL) {
              HANDLE_ERROR("EVP_MD_CTX_create() error")
          }
      
          // initialize digest engine
          if (EVP_DigestInit_ex(mdctx, algo, NULL) != 1) { // returns 1 if successful
              HANDLE_ERROR2("EVP_DigestInit_ex() error", mdctx)
          }
      
          while ((bytes_read = read(STDIN_FILENO, buffer, BUF_SIZE)) > 0) { // read returns 0 on EOF, -1 on error
              // provide data to digest engine
              if (EVP_DigestUpdate(mdctx, buffer, bytes_read) != 1) { // returns 1 if successful
                  HANDLE_ERROR2("EVP_DigestUpdate() error", mdctx)
              }
      
          }
      
          if (bytes_read == -1) {
              perror("read error");
              exit(1);
          }
      
          digest_len = EVP_MD_size(algo);
      
          if ((digest = (unsigned char *)OPENSSL_malloc(digest_len)) == NULL) {
              HANDLE_ERROR2("OPENSSL_malloc() error", mdctx)
          }
      
          // produce digest
          if (EVP_DigestFinal_ex(mdctx, digest, &digest_len) != 1) { // returns 1 if successful
              OPENSSL_free(digest);
              HANDLE_ERROR2("EVP_DigestFinal_ex() error", mdctx)
          }
      
          for (int i = 0; i < digest_len; i++) {
              printf("%02x", digest[i]);
          }
      
          OPENSSL_free(digest);
          EVP_MD_CTX_destroy(mdctx);
      
          return 0;
      }
      

      【讨论】:

        【解决方案4】:

        在安装 openssl 并配置 PATH 后,在源文件中包含 &lt;openssl/evp.h&gt;here 是描述和示例。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-08-13
          • 2011-04-18
          • 1970-01-01
          • 2017-09-20
          • 2013-09-08
          • 2023-03-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多