使用 Crypto++ 生成 SHA256 哈希,使用字符串作为输入和输出?

Posted

技术标签:

【中文标题】使用 Crypto++ 生成 SHA256 哈希,使用字符串作为输入和输出?【英文标题】:Generating a SHA256 hash with Crypto++, using a string as input and output? 【发布时间】:2011-08-21 06:21:33 【问题描述】:

我需要一个如何使用 Crypto++ 从 std::string 生成 SHA256 哈希并输出 std::string 的示例。我似乎无法弄清楚。我尝试过的一切都给了我无效的输出。

这是 interjay 回答后的新代码:

string SHA256(string data)

    byte const* pbData = (byte*) data.data();
    unsigned int nDataLen = data.size();
    byte abDigest[CryptoPP::SHA256::DIGESTSIZE];

    CryptoPP::SHA256().CalculateDigest(abDigest, pbData, nDataLen);

    return string((char*)abDigest);

SHA256("A"); 的输出是

我怎样才能把它变成可读的格式?

感谢 interjay 的回答,我能够生成最终的哈希。

【问题讨论】:

【参考方案1】:

这会使用CryptoPP::Base64Encoder 输出一个base64 字符串:

#include "sha.h"
#include "filters.h"
#include "base64.h"

std::string SHA256HashString(std::string aString)
    std::string digest;
    CryptoPP::SHA256 hash;

    CryptoPP::StringSource foo(aString, true,
    new CryptoPP::HashFilter(hash,
      new CryptoPP::Base64Encoder (
         new CryptoPP::StringSink(digest))));

    return digest;

【讨论】:

太棒了,我正在寻找一种通过流水线实现此目的的方法! CryptoPP 还使用SIMD x64 指令来加速它。 嗨,我在其他地方看到了类似的代码。我想知道为什么 HashFilter、Base64Encoder 和 StringSink 不需要显式删除?提前致谢! @Hei:是的,看起来像一堆内存泄漏。或者,作者是 Java 的粉丝。 :) 不,这不会泄漏内存。这是使用 cryptopp.com/wiki/Pipelining 的惯用 CyptoPP 代码【参考方案2】:

这行会给出错误的结果:

unsigned int nDataLen = sizeof(pbData);

它总是会给你一个指针的大小。你想要的是data.size()

另外,你不需要这部分:

if(!CryptoPP::SHA256().VerifyDigest(abDigest, pbData, nDataLen))

    return SHA256(data);

它应该始终正确验证,因为您只是根据相同的数据计算了摘要。如果没有,您将进入无限递归。

要获得可读的输出,您可以将其转换为十六进制。这是来自Crypto++ Wiki 的 MD5 示例,如果您将 MD5 替换为 SHA256,它应该对您有用:

CryptoPP::MD5 hash;
byte digest[ CryptoPP::MD5::DIGESTSIZE ];
std::string message = "abcdefghijklmnopqrstuvwxyz";

hash.CalculateDigest( digest, (byte*) message.c_str(), message.length() );

CryptoPP::HexEncoder encoder;
std::string output;
encoder.Attach( new CryptoPP::StringSink( output ) );
encoder.Put( digest, sizeof(digest) );
encoder.MessageEnd();

std::cout << output << std::endl;  

【讨论】:

好的,我做了这些更改,虽然现在似乎每次都给我相同的输出,但输出都是乱七八糟的随机奇怪字符。如何将其更改为可读格式? 应用您的示例会导致从const char*const byte* 的转换错误。 (byte*) message.c_str() 是正确的转换。【参考方案3】:

您的代码将期望从您提供给字符串构造函数的缓冲区中获得一个以 null 结尾的字符串!这意味着结果几乎肯定是错误的。

要强制执行摘要大小,请改用以下内容:

return std::string((char*)abDigest, CryptoPP::SHA256::DIGESTSIZE);

关于打印它,以下正确地为字符串BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD 生成测试向量"abc"

std::string string_to_hex(const std::string& input)

  static const char* const lut = "0123456789ABCDEF";
  size_t len = input.length();

  std::string output;
  output.reserve(2 * len);
  for (size_t i = 0; i < len; ++i)
  
    const unsigned char c = input[i];
    output.push_back(lut[c >> 4]);
    output.push_back(lut[c & 15]);
  
  return output;


std::string SHA256(std::string data)

  CryptoPP::byte const* pbData = (CryptoPP::byte*)data.data();
  unsigned int nDataLen = data.length();
  CryptoPP::byte abDigest[CryptoPP::SHA256::DIGESTSIZE];

  CryptoPP::SHA256().CalculateDigest(abDigest, pbData, nDataLen);

  // return string((char*)abDigest);  -- BAD!!!
  return std::string((char*)abDigest, CryptoPP::SHA256::DIGESTSIZE);


void test_cryptopp() 
  std::cout << string_to_hex(SHA256("abc")) << std::endl;

【讨论】:

以上是关于使用 Crypto++ 生成 SHA256 哈希,使用字符串作为输入和输出?的主要内容,如果未能解决你的问题,请参考以下文章

go语言练习:sha256sha512哈希算法

是否有内置的方法或插件让Jenkins为我的工件生成SHA256哈希?

如何在 Crypto++ 中使用 RSA OAEP SHA-256 加密/解密数据

SHA256、SHA1、SHA384 哈希到 JSON Web 令牌

Python JWT 库 PyJWT 使用 HS256 签名时遇到问题 - 使用 SHA-256 哈希算法的 HMAC

使用golang生成字符串的SHA哈希