Salsa20使用Crypto ++

时间:2015-10-25 05:32:53

标签: c++

我正在尝试在crypto ++库中使用salsa20代码。 (THIS)在两个程序之间进行通信。

两个程序都使用相同的代码

std::string salsaDo(std::string key, std::string msg, byte iv[STREAM_IV_LENGTH]) {

    //Set up byte arrays for proccess
    byte *plaintextBytes = (byte *)msg.c_str();
    byte *ciphertextBytes = new byte[msg.length()];
    byte *reversetextBytes = new byte[msg.length()];

    //Set up key array
    byte* keyBytes = (byte *)key.substr(0, STREAM_KEY_LENGTH).c_str();

    //Peform encryption method
    Salsa20::Encryption salsa;
    salsa.SetKeyWithIV(keyBytes, STREAM_KEY_LENGTH, iv);
    salsa.ProcessData(ciphertextBytes, plaintextBytes, msg.length());

    salsa.SetKeyWithIV(keyBytes, STREAM_KEY_LENGTH, iv);
    salsa.ProcessData(reversetextBytes, ciphertextBytes, msg.length());

    std::string ivStr((char*)iv, STREAM_IV_LENGTH);

    std::cout << "____\nK:" << key.c_str();
    std::cout << "\nI:" << ivStr.c_str();
    std::cout << "\nM:" << msg.c_str();
    std::cout << "\nE:" << std::string((const char *)ciphertextBytes, msg.length()).c_str();
    std::cout << "\nR:" << std::string((const char *)reversetextBytes, msg.length()).c_str();
    std::cout << "\n____\n";

    //return  msg;

    //return string 
    return std::string((const char *)ciphertextBytes, msg.length());

}

程序中的图像位于http://www.cryptopp.com/

说明:

  • 步骤1:加密纯文本(服务器-M到服务器-E)

  • 步骤2:解密加密文本(Server-E到服务器-R,客户端-M到客户端-E。)这两个应该给出相同的结果,但不要

  • 步骤3:再次运行client-E,检查它是否等于服务器发送的消息。

1 个答案:

答案 0 :(得分:0)

此代码存在一些问题。

  1. 此行在技术上调用未定义的行为:

    byte* keyBytes = (byte *)key.substr(0, STREAM_KEY_LENGTH).c_str();
    

    在这种情况下,substr()调用返回包含子字符串的临时std::string对象。这个临时std::string的生命周期延伸到整行的评估(完整表达式)。 std::string::c_str()返回的C字符串的生存期与std::string相同,但变异操作无效。因此,在这个完整的表达式中,keyBytes一旦行执行就可能是无效指针。

    您可以通过将key覆盖到所需的子字符串来解决问题。在这种情况下,分配给key可确保生命周期延长到使用位置:

    key = key.substr(0, STREAM_KEY_LENGTH);
    const byte* keyBytes = static_cast<const byte*>(key.c_str());
    
  2. salsaDo()函数泄漏内存。由:

    创建的字节数组
    byte *ciphertextBytes = new byte[msg.length()];
    byte *reversetextBytes = new byte[msg.length()];
    

    ..没有被释放。考虑使用std::unique_ptr<byte[]>

    std::unique_ptr<byte[]> ciphertextBytes(new byte[msg.length()]);
    std::unique_ptr<byte[]> reversetextBytes(new byte[msg.length()]);
    
  3. C ++在技术上不支持将数组传递给函数。实际上,参数byte iv[STREAM_IV_LENGTH]被视为您已经编写了byte* iv

    您可以传递对数组的引用。另外,对于const-correctness,您应该标记初始化向量字节const

    std::string salsaDo(std::string key, std::string msg, const byte (&iv)[STREAM_IV_LENGTH])
    {
        //...
    }
    
  4. 我不会使用std::string来存储密钥,或者实际上是任何字节数组,例如返回的加密字节。考虑使用std::unique_ptr<byte[]>std::shared_ptr<byte[]>,或者将引用传递给const数组,或传递指针和长度(例如const byte* keysize_t keyLength)。