问题:调用 “手把手用C++解密Chrome80版本数据库” 一文中的demo源码,想要实现AES-GCM解密数据,发现得到的cookie值不正确,但他们的特征 长度 等都很近似。
经调试,个人认为是GCM解码出现问题,但看了网上很多C++实现AES-GCM的代码,发现他们的解码方法都是相同的,因此请教论坛师傅,能否看出该文章的代码问题出现在何处。
#include <iostream>
#include "cryptlib.h"
#include "rijndael.h"
#include "modes.h"
#include "files.h"
#include "osrng.h"
#include "hex.h"
#include "base64.h"
using namespace CryptoPP;
// aes ebc 加密(输出 base64)
std::string aes_encrypt_ecb_base64(std::string data , unsigned char* key, int keylen)
{
std::string encrypt_str;
try
{
CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption ecb_encription(key, keylen);
CryptoPP::StreamTransformationFilter stf_encription(
ecb_encription,
new CryptoPP::Base64Encoder(new CryptoPP::StringSink(encrypt_str)),
CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
);
stf_encription.Put(reinterpret_cast<const unsigned char*>(data.c_str()), data.length() + 1);
stf_encription.MessageEnd();
}
catch (std::exception e) {
std::cout << e.what() << std::endl;
}
return encrypt_str;
}
// aes ebc 加密(输出 hex)
std::string aes_encrypt_ecb_hex(std::string data , unsigned char* key, int keylen)
{
std::string encrypt_str;
try
{
CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption ecb_encription(key, keylen);
CryptoPP::StreamTransformationFilter stf_encription(
ecb_encription,
new CryptoPP::HexEncoder(new CryptoPP::StringSink(encrypt_str)),
CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
);
stf_encription.Put(reinterpret_cast<const unsigned char*>(data.c_str()), data.length() + 1);
stf_encription.MessageEnd();
}
catch (std::exception e) {
std::cout << e.what() << std::endl;
}
return encrypt_str;
}
// aes ebc 解密(输出 base64)
std::string aes_decrypt_ecb_base64(std::string base64_data, unsigned char* key, int keylen)
{
try
{
std::string aes_encrypt_data;
CryptoPP::Base64Decoder decoder;
decoder.Attach(new CryptoPP::StringSink(aes_encrypt_data));
decoder.Put(reinterpret_cast<const unsigned char*>(base64_data.c_str()), base64_data.length());
decoder.MessageEnd();
std::string decrypt_data;
CryptoPP::ECB_Mode<CryptoPP::AES>::Decryption ebc_description(key, keylen);
CryptoPP::StreamTransformationFilter stf_description(
ebc_description,
new CryptoPP::StringSink(decrypt_data),
CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
);
stf_description.Put(
reinterpret_cast<const unsigned char*>(aes_encrypt_data.c_str()),
aes_encrypt_data.length()
);
stf_description.MessageEnd();
return decrypt_data;
}
catch (std::exception e) {
std::cout << e.what() << std::endl;
return "";
}
}
// aes ebc 解密(输出 hex)
std::string aes_decrypt_ecb_hex(std::string hex_data, unsigned char* key, int keylen)
{
try
{
std::string aes_encrypt_data;
CryptoPP::HexDecoder decoder;
decoder.Attach(new CryptoPP::StringSink(aes_encrypt_data));
decoder.Put(reinterpret_cast<const unsigned char*>(hex_data.c_str()), hex_data.length());
decoder.MessageEnd();
std::string decrypt_data;
CryptoPP::ECB_Mode<CryptoPP::AES>::Decryption ebc_description(key, keylen);
CryptoPP::StreamTransformationFilter stf_description(
ebc_description,
new CryptoPP::StringSink(decrypt_data),
CryptoPP::BlockPaddingSchemeDef::ZEROS_PADDING
);
stf_description.Put(
reinterpret_cast<const unsigned char*>(aes_encrypt_data.c_str()),
aes_encrypt_data.length()
);
stf_description.MessageEnd();
return decrypt_data;
}
catch (std::exception e) {
std::cout << e.what() << std::endl;
return "";
}
}
int main()
{
// ebc base64
std::string en_base64 = aes_encrypt_ecb_base64("hello cryptopp",(unsigned char*)"1234567812345678", 16);
printf("en:%s \n", en_base64.c_str());
std::string de_base64 = aes_decrypt_ecb_base64(en_base64, (unsigned char*)"1234567812345678", 16);
printf("de:%s \n", de_base64.c_str());
// ebc hex
std::string en_hex = aes_encrypt_ecb_hex("hello cryptopp", (unsigned char*)"1234567812345678", 16);
printf("en:%s \n", en_hex.c_str());
std::string de_hex = aes_decrypt_ecb_hex(en_hex, (unsigned char*)"1234567812345678", 16);
printf("de:%s \n", de_hex.c_str());
(void)getchar();
return 0;
}
参考GPT和自己的思路,如果您使用了手把手用C++解密Chrome80版本数据库的代码示例,并且您发现解密后的cookie值不正确,可能是以下几个原因导致的:
1.密钥不正确:在解密数据之前,您需要确保使用正确的密钥。请确认您使用的是正确的密钥。
2.参数不正确:AES-GCM解密需要正确的参数才能工作。请检查您是否正确设置了参数,例如初始化向量(IV)和附加数据。
3.数据损坏:如果您尝试解密已经被损坏的数据,则解密后的cookie值可能不正确。请确保您尝试解密正确的数据。
4.解密算法不匹配:如果您的加密数据使用了不同的加密算法(例如AES-CBC),则使用AES-GCM解密算法可能会导致不正确的结果。
为了解决此问题,请尝试检查您的代码并确保上述问题得到了解决。如果问题仍然存在,请提供更多详细信息,例如代码示例和错误消息,以便我可以更好地帮助您。
参考gpt和自己的思路,在使用Crypto++库进行AES-GCM解密时,需要确保正确设置以下参数:
1 密钥和IV:使用正确的密钥和初始化向量(IV)进行解密。在代码中,可以使用CryptoPP::SecByteBlock类型的密钥和IV来表示它们。
2 GCM模式:使用GCM模式进行解密,可以通过创建一个CryptoPP::GCMCryptoPP::AES::Decryption对象来实现。
3 授权数据:在GCM模式下,需要使用授权数据来保证安全性。授权数据是一些附加信息,例如加密数据的长度等。授权数据可以在解密过程中使用。
以下是一个简单的示例,展示了如何使用Crypto++库进行AES-GCM解密:
#include <iostream>
#include <string>
#include <cryptopp/cryptlib.h>
#include <cryptopp/aes.h>
#include <cryptopp/gcm.h>
#include <cryptopp/hex.h>
#include <cryptopp/filters.h>
using namespace CryptoPP;
int main()
{
// AES key and IV
byte key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
byte iv[12] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b};
// Encrypted data
std::string ciphertext_hex = "87ff6c1b0b0d71f8f6ae9eac5e5c5e6d8d6b2e47b04f53e5f6d8d6b2e47b04f5";
// Convert the ciphertext to bytes
byte ciphertext[ciphertext_hex.size() / 2];
HexDecoder decoder;
decoder.Decode(ciphertext, reinterpret_cast<const byte*>(ciphertext_hex.data()), ciphertext_hex.size());
// Decrypt the ciphertext
byte plaintext[ciphertext_hex.size() / 2];
GCM<AES>::Decryption gcm;
gcm.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
gcm.SpecifyDataLengths(0, ciphertext_hex.size() / 2, 0);
gcm.DecryptAndVerify(plaintext, ciphertext, ciphertext_hex.size() / 2, NULL, 0);
// Print the decrypted plaintext
std::cout << std::string(reinterpret_cast<const char*>(plaintext), ciphertext_hex.size() / 2) << std::endl;
return 0;
}
在这个示例中,我们使用了一个16字节的AES密钥和12字节的IV。我们将16进制的密文字符串转换为字节数组,并使用GCM模式解密。最后,我们打印出解密后的明文字符串。
该回答引用ChatGPT
如有疑问,可以回复我!
以下是使用Crypto++库在C++中实现AES-GCM解密的示例代码:
#include <iostream>
#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <cryptopp/filters.h>
#include <cryptopp/gcm.h>
int main()
{
// 从文件或其他来源读取密文、密钥和IV
std::string ciphertext = "2LgT+PZ32aA8bHdSPynsPw=="; // base64编码的密文
std::string key = "0123456789ABCDEF"; // 密钥
std::string iv = "1234567890abcdef"; // 初始化向量
// 解码密文
std::string decoded_ciphertext;
CryptoPP::StringSource(ciphertext, true,
new CryptoPP::Base64Decoder(new CryptoPP::StringSink(decoded_ciphertext)));
// 创建AES-GCM解密器
CryptoPP::GCM<CryptoPP::AES>::Decryption decryptor;
decryptor.SetKeyWithIV(reinterpret_cast<const byte*>(key.data()), key.size(),
reinterpret_cast<const byte*>(iv.data()), iv.size());
// 解密密文
std::string plaintext;
CryptoPP::AuthenticatedDecryptionFilter adf(decryptor,
new CryptoPP::StringSink(plaintext),
CryptoPP::AuthenticatedDecryptionFilter::MAC_AT_BEGIN);
adf.Put(reinterpret_cast<const byte*>(decoded_ciphertext.data()), decoded_ciphertext.size());
adf.MessageEnd();
// 输出解密结果
std::cout << "Plaintext: " << plaintext << std::endl;
return 0;
}
注意,此代码假定已经读取了密文、密钥和初始化向量,密文已经使用base64编码。在实际应用中,这些值可能需要以其他方式获取。
此代码创建了一个AES-GCM解密器,然后将密文传递给AuthenticatedDecryptionFilter,并在结束后调用MessageEnd来完成解密操作。解密结果将存储在名为plaintext的字符串中,并打印到标准输出中。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
为了更好地帮助您解决问题,我需要您提供更多的上下文和细节。您可以在下面提供更具体的信息:
在没有更多信息的情况下,以下是一些可能导致问题的原因:
在这里,我提供一个AES-GCM解密的代码示例,您可以参考这个代码,并根据您的需求进行修改:
#include <iostream>
#include <string>
#include <cryptopp/aes.h>
#include <cryptopp/gcm.h>
#include <cryptopp/hex.h>
using namespace CryptoPP;
using std::string;
using std::cout;
using std::endl;
// 加密后的数据
const string cipher = "CE8E63118145A6A2D1E9ACAF28FC8631F477017D5F139A902F5AA92E2A7204292504AA4A93F9E1A8F5C57A5D5B5A5B5D5E5B5F5F4954F9E9E1F8F6E3E6A3E6A3A6E8";
int main()
{
// 解密密钥
const byte key[] = { 0x98, 0x20, 0xEF, 0x1D, 0x68, 0xAC, 0xCA, 0xBA, 0xCE, 0xD1, 0x88, 0xE9, 0xE8, 0x2D, 0x1C, 0xFD };
// IV值
const byte iv[] = { 0x7E, 0x04, 0xFC, 0x98, 0xB6, 0x9A, 0x2B, 0x98, 0x5B, 0x50, 0xEC, 0x9F };
// 使用HexDecoder将字符串形式的加密密文转换为字节形式
byte decrypted[CryptoPP::AES::BLOCKSIZE];
HexDecoder decoder;
decoder.Attach(new ArraySink(reinterpret_cast<byte*>(&decrypted[0]), CryptoPP::AES::BLOCKSIZE));
decoder.Put(reinterpret_cast<const byte*>(cipher.c_str()), cipher.size());
decoder.MessageEnd();
// 使用AES-GCM解密
GCM<AES>::Decryption decryption;
decryption.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));
string decryptedText;
try
{
DecodingChannel channel(new StringSink(decryptedText));
ChannelSwitch cs;
cs.AddDefaultRoute(channel);
cs.AddRoute("TAGGED", new AuthenticatedDecryptionFilter(decryption, NULL, AuthenticatedDecryptionFilter::MAC_AT_BEGIN));
StringSource(reinterpret_cast<const byte*>(&decrypted[0]), CryptoPP::AES::BLOCKSIZE, true, new Redirector(cs));
}
catch (CryptoPP::Exception& e)
{
cout << "Exception: " << e.what() << endl;
return 1;
}
// 输出解密后的结果
cout << "Decrypted Text: \"" << decryptedText << "\"" << endl;
return 0;
}
以上代码仅供参考,仍需要根据您的具体情况进行修改。
如果我的回答解决了您的问题,请采纳!
通过执行 “手把手用C++解密Chrome80版本数据库”的代码示例发现执行解密的cookie值虽然错误,但是和正确cookie值的长度以及特征都很近似。执行效果如下图所示,左侧为执行结果,右侧为真正cookie值。
#include <iostream>
#include <string>
#include <cryptopp/aes.h>
#include <cryptopp/gcm.h>
#include <cryptopp/hex.h>
#include <cryptopp/filters.h>
#include <cryptopp/files.h>
using namespace CryptoPP;
int main()
{
try
{
// 读取密文和密钥
std::string ciphertext, key;
FileSource("ciphertext.bin", true, new StringSink(ciphertext));
FileSource("key.bin", true, new StringSink(key));
// 解码密钥
SecByteBlock secKey((const unsigned char*)key.data(), key.size());
// 解码密文
byte iv[GCM<>::BLOCKSIZE];
std::memcpy(iv, ciphertext.data(), GCM<>::BLOCKSIZE);
std::string ciphertextWithoutIv(ciphertext, GCM<>::BLOCKSIZE);
// AES-GCM解密
GCM<AES>::Decryption gcmDecryption;
gcmDecryption.SetKeyWithIV(secKey, secKey.size(), iv, sizeof(iv));
std::string decryptedText;
StringSource(ciphertextWithoutIv, true,
new AuthenticatedDecryptionFilter(gcmDecryption,
new StringSink(decryptedText),
AuthenticatedDecryptionFilter::DEFAULT_FLAGS,
GCM<>::TAG_SIZE));
std::cout << "解密后的文本:" << std::endl;
std::cout << decryptedText << std::endl;
}
catch (const CryptoPP::Exception& e)
{
std::cerr << "加密异常:" << e.what() << std::endl;
return -1;
}
return 0;
}
在这个示例中,我们使用FileSource从文件中读取密文和密钥,使用GCM::Decryption进行AES-GCM解密,使用StringSource将密文传递给AuthenticatedDecryptionFilter,并将解密结果保存到StringSink中。
需要注意的是,在解密前需要从密文中提取出IV(Initialization Vector),并将其传递给GCM::Decryption对象的SetKeyWithIV方法。
此外,需要注意密文和密钥的编码方式,一般情况下,建议使用二进制方式保存密文和密钥。