【问题标题】:How encrypt and decrypt several values in a row如何连续加密和解密多个值
【发布时间】:2017-10-02 14:09:30
【问题描述】:

在我的程序中,我使用crypto++ 库。 我有这样的结构:

struct crypt_struct{
  //consists of encrypted data
  string name1;
  string name2;
  string name3;
}
struct decrypt_struct{
  //consists of decrypted data
  int name1;
  string name2;
  double name3;
}

我有加密功能:

crypt_struct encrypt(decrypt_struct struct_in) {
    //Key and IV setup
    //AES encryption uses a secret key of a variable length (128-bit, 196-bit or 256-   
    //bit). This key is secretly exchanged between two parties before communication   
    //begins. DEFAULT_KEYLENGTH= 16 bytes
    byte key[CryptoPP::AES::DEFAULT_KEYLENGTH], iv[CryptoPP::AES::BLOCKSIZE];
    memset(key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
    memset(iv, 0x00, CryptoPP::AES::BLOCKSIZE);
    //output encrypt struct
    crypt_struct struct_out;

    //encrypt text
    string ciphertext;

    CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
    CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(ciphertext));


    //int name1
    stfEncryptor.Put(reinterpret_cast<const unsigned char*> ((to_string(struct_in.name1)).c_str()), (to_string(struct_in.name1)).length() + 1);
    stfEncryptor.MessageEnd();
    struct_out.name1 = ciphertext;
    cout << ciphertext << endl;
    ciphertext.clear();

    //string name2
    stfEncryptor.Put(reinterpret_cast<const unsigned char*> (struct_in.name2.c_str()), struct_in.name2.length() + 1);
    stfEncryptor.MessageEnd();
    struct_out.name2 = ciphertext;
    cout << ciphertext << endl;
    ciphertext.clear();

    //double name3
    stfEncryptor.Put(reinterpret_cast<const unsigned char*> ((to_string(struct_in.name3)).c_str()), (to_string(struct_in.name3)).length() + 1);
    stfEncryptor.MessageEnd();
    struct_out.name3 = ciphertext;
    cout << ciphertext << endl;
    ciphertext.clear();

    return struct_out;
}

及解密功能:

decrypt_struct decrypt(crypt_struct struct_in)
{
    //Key and IV setup
    //AES encryption uses a secret key of a variable length (128-bit, 196-bit or 256-   
    //bit). This key is secretly exchanged between two parties before communication   
    //begins. DEFAULT_KEYLENGTH= 16 bytes

    byte key[CryptoPP::AES::DEFAULT_KEYLENGTH], iv[CryptoPP::AES::BLOCKSIZE];
    memset(key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
    memset(iv, 0x00, CryptoPP::AES::BLOCKSIZE);
    //
    // Decrypt
    //
    decrypt_struct struct_out;
    string decryptedtext;
    CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);
    CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decryptedtext));

    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(struct_in.name1.c_str()), struct_in.name1.length());
    struct_out.name1= atoi(decryptedtext.c_str());
    stfDecryptor.MessageEnd();
    decryptedtext.clear();

    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(struct_in.name2.c_str()), struct_in.name2.length());
    struct_out.name2= atoi(decryptedtext.c_str());
    stfDecryptor.MessageEnd();
    decryptedtext.clear();

    stfDecryptor.Put(reinterpret_cast<const unsigned char*>(struct_in.name3.c_str()), struct_in.name3.length());
    struct_out.name3= atoi(decryptedtext.c_str());
    stfDecryptor.MessageEnd();
    decryptedtext.clear();

    return struct_out;

}

如果我尝试只加密一个变量,那么一切都会正确解密。但是,如果我尝试同时加密多个变量,则会出现错误。而且,在对变量int类型进行加密时,也会出现同样的错误。用什么可以连接,有没有人想法?

在我看来,原因可能是这个函数一次只能加密一行。

【问题讨论】:

  • 我对@9​​87654325@ 不是很熟悉,但是将加密数据存储在C++ 字符串中似乎有点危险,因为它会附加一个\0 - 并且加密数据本身可能包含一个空值中间的终止符 - 所以c_str 在尝试解密数据时可能不会返回正确的表示 - 使用字节/字符缓冲区会更安全。
  • @Predilute,这个我不太清楚,所以我试着按照这个库的源代码来实现一切。
  • 您应该能够将结果解密为std::string - 但您肯定会在尝试将加密数据存储为std::string 时遇到问题。如果二进制数据中包含 0x00,std::string 会将其解释为空终止符并截断您的加密数据。
  • std::string 没有空终止符,是吗?我认为这是我们使用字符串而不是 char[]s 的主要原因。如果字符串中间有一个空终止符,字符数组实际上会截断数据。
  • 我在 struct crypt_struct{ char* name1; char* name2; char* name3;} 上更改了 struct crypt_struct{ string name1; string name2; string name3;},但没有帮助。

标签: c++ encryption cryptography crypto++


【解决方案1】:

问题是这样的: 问题是在这个库的源代码中,解密时使用了c_str()函数。那些:

stfDecryptor.Put(reinterpret_cast<const unsigned char*> (struct_in.name1.c_str()), struct_in.name1.size());

官方文档说:

如果字符串对象不包含其他空字符,则从c_str() 获得的指针只能被视为指向以空字符结尾的字符串的指针。

在加密函数中,将一个零字符添加到字符串中,当我们尝试解密时,通过c_str() 函数,我们用第一个零字符修剪我们的字符串。

但是,在 с++ 11 的标准中,添加了一个类似的函数,它执行与 data() 函数相同的操作,只是它不考虑空字符。

结果,我收到了:

stfDecryptor.Put(reinterpret_cast<const unsigned char*> (struct_in.name1.data()), struct_in.name1.size());

此外,如果您先加密name1,然后再加密name2,再加密name3,这一点也很重要。那和解密你应该以相同的顺序。

【讨论】:

  • 您应该使用类似BSON 或Google 的Protocol Buffers 来序列化您的数据。您也可以使用 ITU 的 ASN.1,但使用起来有点困难。序列化后加密 blob。
猜你喜欢
  • 1970-01-01
  • 2020-04-23
  • 1970-01-01
  • 2014-03-27
  • 1970-01-01
  • 2018-08-04
  • 1970-01-01
  • 2010-10-10
  • 2012-10-03
相关资源
最近更新 更多