使用CryptoPP库加密和解密字节数组/向量

时间:2017-12-13 11:10:12

标签: c++ encryption aes crypto++

我正在尝试加密已解析为字符串的字节数组。这似乎适用于所有情况,除了字节数组包含0x00的情况。

int main()
{
    byte cipherTextWithZeroByte[32] = {
        0xD3, 0xFA, 0xD6, 0xEC, 0x84, 0x4E, 0xD3, 0xD8,
        0x2B, 0x76, 0x6C, 0xE8, 0x02, 0xF2, 0xB2, 0x6F,
        0x00, 0xE8, 0x99, 0x8C, 0xEC, 0x4B, 0x3C, 0x7D,         
        0xAC, 0xDE, 0x86, 0x02, 0x51, 0xAB, 0x3F, 0x04
    };

    string cipherText((char *)cipherTextWithZeroByte);
    string plainText = decrypt(cipherText, sizeof(cipherTextWithZeroByte));

    return 1;
}

string decrypt(string cipherText, int size)
{
    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::HexEncoder(
                           new CryptoPP::StringSink(decryptedText)));

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

    return decryptedText;
}

在这种情况下,字节数组包含0x00。这会导致cipherText被缩短,导致无效长度。抛出异常:&#39; StreamTransformationFilter:找到无效的PKCS#7块填充&#39;

所以我认为最好使用 ArraySource ArraySink 来确保字符串不会被终止。

int main()
{
    byte cipherTextWithZeroByte[32] = {
        0xD3, 0xFA, 0xD6, 0xEC, 0x84, 0x4E, 0xD3, 0xD8,
        0x2B, 0x76, 0x6C, 0xE8, 0x02, 0xF2, 0xB2, 0x6F,
        0x00, 0xE8, 0x99, 0x8C, 0xEC, 0x4B, 0x3C, 0x7D,         
        0xAC, 0xDE, 0x86, 0x02, 0x51, 0xAB, 0x3F, 0x04
    };

    vector<byte> cipherTextData(cipherTextWithZeroByte, cipherTextWithZeroByte + sizeof(cipherTextWithZeroByte) / sizeof(cipherTextWithZeroByte[0]));
    vector<byte> plainTextData = decrypt(cipherTextData);

    return 1;
}

vector<byte> decrypt(vector<byte> cipherText)
{
    vector<byte> plainText;
    plainText.resize(cipherText.size());

    CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryptor;
    decryptor.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));


    CryptoPP::ArraySource ss(&cipherText[0], cipherText.size(), true,
              new CryptoPP::HexEncoder(
                  new CryptoPP::StreamTransformationFilter(decryptor,
                      new CryptoPP::ArraySink(plainText.data(), plainText.size()))));

    return plainText;
}

在这种情况下,抛出一个异常,即密文不是密钥长度的倍数,这显然不是这里的情况。 (密钥= 16字节,密文= 16字节)。我认为库将字节数组转换为字符串,而不是0x00字节后的所有数据。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

加密是二进制字节而不是字符操作。因此,加密输出不能转换为字符串。如果需要字符串输出,请将加密数据编码为字符串兼容格式,常见格式为Base64和十六进制。

特别是字符串中的空字节按照惯例在“C”中表示信号语言是字符串的结尾。

即加密将二进制数据编码为字符串格式,并且在解密时首先通过使用编码操作的反转将字符串表示解码为二进制数据。