Crypto ++ SHA1函数

时间:2014-05-02 04:20:13

标签: visual-c++ crypto++

我无法弄清楚我的功能有什么问题 - 它会在返回时导致断点。

std::string generateHash(std::string source)
{
    CryptoPP::SHA1 hash;
    byte digest[CryptoPP::SHA1::DIGESTSIZE];
    hash.CalculateDigest(digest, (const byte*)source.c_str(), source.size());
    std::string output;
    CryptoPP::HexEncoder encoder;
    CryptoPP::StringSink test = CryptoPP::StringSink(output);
    encoder.Attach((CryptoPP::BufferedTransformation*)&CryptoPP::StringSink(output));
    encoder.Put(digest, sizeof(digest));
    encoder.MessageEnd();
    return output; // here
}

2 个答案:

答案 0 :(得分:3)

encoder.Attach((CryptoPP::BufferedTransformation*)&CryptoPP::StringSink(output));

在这一行中,CryptoPP::StringSink(output)是一个临时对象。此呼叫后CryptoPP::StringSink(output)不再存在。因此,如果您尝试按照其地址(encoder.Attachencoder.Put),您将获得未定义的行为。 (就像你永远不应该返回局部变量的地址)

我的参考代码:

 std::string generateHash(std::string source)
  {
      CryptoPP::SHA1 hash;
      byte digest[CryptoPP::SHA1::DIGESTSIZE];
      hash.CalculateDigest(digest, (const byte*)source.c_str(), source.size());
      std::string output;
      CryptoPP::HexEncoder encoder;
      CryptoPP::StringSink test = CryptoPP::StringSink(output);
      encoder.Attach(new CryptoPP::StringSink(output));
      encoder.Put(digest, sizeof(digest));
      encoder.MessageEnd();
      return output;
  }

答案 1 :(得分:2)

   CryptoPP::HexEncoder encoder;
   CryptoPP::StringSink test = CryptoPP::StringSink(output);
   encoder.Attach((CryptoPP::BufferedTransformation*)&CryptoPP::StringSink(output));

Onemouth的解决方案是正确的,但这就是你遇到麻烦的原因:

  • StringSink(output)在堆栈上是临时的,当StringSink析构函数运行时它将被清除
  • HexEncoder'拥有'指向StringSink(output)的指针,因此HexEncoder将在StringSink(output)
  • 上调用删除

所以StringSink被清理了两次。

为了完整性,StringSink 删除字符串output,因为它需要引用,而不是指针。

这是README.txt中记录的行为:

88  *** Important Usage Notes ***
89  
90  1. If a constructor for A takes a pointer to an object B (except primitive
91  types such as int and char), then A owns B and will delete B at A's
92  destruction.  If a constructor for A takes a reference to an object B,
93  then the caller retains ownership of B and should not destroy it until
94  A no longer needs it. 

虽然它高度不寻常,但可能能够做你想做的事情并按如下方式修复它(但我不< / em>建议按照你的方式去做):

encoder.Attach(new Redirector(&CryptoPP::StringSink(output)));

Redirector停止了所有权链。当Redirector被销毁时,会破坏其附加的转换(StringSink)。但同样,它不是使用库的方式。

Redirector在图书馆的其他地方非常有用,但在这种情况下并非如此。