Генерация хэша SHA256 с Crypto ++, с использованием строки в качестве ввода и вывода? - PullRequest
19 голосов
/ 09 мая 2011

Мне нужен пример того, как использовать Crypto ++ для генерации хеша SHA256 из std :: string и вывода 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 («А»); есть

enter image description here

Как я могу превратить это в читаемый формат?

Благодаря ответу Interjay я смог создать окончательный хэш.

Ответы [ 3 ]

17 голосов
/ 13 августа 2011

Это выводит строку base64, используя CryptoPP::Base64Encoder:

#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;
}
16 голосов
/ 09 мая 2011

Эта строка даст неправильные результаты:

unsigned int nDataLen = sizeof(pbData);

Это всегда даст вам размер указателя. Вместо этого вы хотите data.size().

Кроме того, вам не нужна эта часть:

if(!CryptoPP::SHA256().VerifyDigest(abDigest, pbData, nDataLen))
{
    return SHA256(data);
}

Он всегда должен проверяться правильно, поскольку вы только что рассчитали дайджест на основе тех же данных. А если этого не произойдет, вы начнете бесконечную рекурсию.

Чтобы получить читабельный вывод, вы можете преобразовать его в шестнадцатеричный формат. Вот пример для MD5 из Crypto ++ Wiki , он должен работать для вас, если вы замените 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;  
0 голосов
/ 23 февраля 2018

Ваш код ожидает строку с нулевым символом в конце из буфера, который вы предоставляете конструктору строк!Это означает, что результат почти наверняка будет неправильным.

Чтобы обеспечить размер дайджеста, используйте вместо него следующее:

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