首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AES-128 CFB-8解密的前16个字节已损坏

AES-128 CFB-8解密的前16个字节已损坏
EN

Stack Overflow用户
提问于 2019-11-18 21:56:19
回答 1查看 440关注 0票数 0

我最近一直在做一个项目,它应该在协议的帮助下连接到服务器。到目前为止一切正常,但当我梳理解密这些包时,我很快就注意到有些东西不能正常工作。

所有数据包的前16个字节都未正确解密。我尝试过使用不同的库,但也不起作用。我使用的是C++语言,到目前为止,我已经使用Crypto++和OpenSSL进行了解密,但没有成功。

在此Link下,您可以找到协议,这里是解密协议Link,下面是我的相应代码:

OpenSSL:

代码语言:javascript
复制
void init() {

    unsigned char* sharedSecret = new unsigned char[AES_BLOCK_SIZE];

    std::generate(sharedSecret,
        sharedSecret + AES_BLOCK_SIZE,
        std::bind(&RandomGenerator::GetInt, &m_RNG, 0, 255));

    for (int i = 0; i < 16; i++) {
        sharedSecretKey += sharedSecret[i];
    }

    // Initialize AES encryption and decryption
    if (!(m_EncryptCTX = EVP_CIPHER_CTX_new()))
        std::cout << "123" << std::endl;

    if (!(EVP_EncryptInit_ex(m_EncryptCTX, EVP_aes_128_cfb8(), nullptr, (unsigned char*)sharedSecretKey.c_str(), (unsigned char*)sharedSecretKey.c_str())))
        std::cout << "123" << std::endl;

    if (!(m_DecryptCTX = EVP_CIPHER_CTX_new()))
        std::cout << "123" << std::endl;

    if (!(EVP_DecryptInit_ex(m_DecryptCTX, EVP_aes_128_cfb8(), nullptr, (unsigned char*)sharedSecretKey.c_str(), (unsigned char*)sharedSecretKey.c_str())))
        std::cout << "123" << std::endl;

    m_BlockSize = EVP_CIPHER_block_size(EVP_aes_128_cfb8());
}

std::string result;
int size = 0;
result.resize(1000);
EVP_DecryptUpdate(m_DecryptCTX, &((unsigned char*)result.c_str())[0], &size, &sendString[0], data.size());

Crypto++:

代码语言:javascript
复制
CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption AESDecryptor((byte*)sharedSecret.c_str(), (unsigned int)16, sharedSecret.c_str(), 1);

std::string sTarget("");
CryptoPP::StringSource ss(data, true, new CryptoPP::StreamTransformationFilter(AESDecryptor, new CryptoPP::StringSink(sTarget)));

我认为值得一提的是,我对密钥和iv (初始化向量)使用了一个相同的共享密钥。在其他帖子中,这通常被贴上问题的标签。在这种情况下,我不知道如何修复它,因为协议需要它。

我期待着一个建设性的反馈。

EN

回答 1

Stack Overflow用户

发布于 2019-11-19 04:08:12

EVP_EncryptInit_ex(m_EncryptCTX,EVP_aes_128_cfb8(),nullptr,(unsigned char*)sharedSecretKey.c_str(),(unsigned char*)sharedSecretKey.c_str())

和:

CFB_Mode::Decryption AESDecryptor((字节*) sharedSecret.c_str(),(无符号整数)16,sharedSecret.c_str(),1);std::string sTarget("");StringSource ss(StreamTransformationFilter,true,StreamTransformationFilter(AESDecryptor,StringSink(STarget);

这不是很明显,但您需要为Crypto++中的块密码的操作模式设置反馈大小。默认情况下,Crypto++反馈大小为128。

设置循环流化床模式反馈大小的代码可以在Crypto++维基上的CFB Mode找到。你想要下一页的第三个或第四个例子。

代码语言:javascript
复制
AlgorithmParameters params =
        MakeParameters(Name::FeedbackSize(), 1 /*8-bits*/)
        (Name::IV(), ConstByteArrayParameter(iv));

这是一种笨拙的传递参数的方式。它被记录在源代码文件和NameValuePairs的wiki上。它允许您通过一致的接口传递任意参数。一旦你尝到了它的味道,它就会变得强大。

然后使用params为加密器和解密器设置密钥:

代码语言:javascript
复制
CFB_Mode< AES >::Encryption enc;
enc.SetKey( key, key.size(), params );

// CFB mode must not use padding. Specifying
//  a scheme will result in an exception
StringSource ss1( plain, true, 
   new StreamTransformationFilter( enc,
      new StringSink( cipher )
   ) // StreamTransformationFilter      
); // StringSource

我相信你的调用应该是这样的(如果我正确解析了OpenSSL的话):

代码语言:javascript
复制
const byte* ptr = reinterpret_cast<const byte*>(sharedSecret.c_str());

AlgorithmParameters params =
        MakeParameters(Name::FeedbackSize(), 1 /*8-bits*/)
        (Name::IV(), ConstByteArrayParameter(ptr, 16));

CFB_Mode< AES >::Encryption enc;
enc.SetKey( ptr, 16, params );

在你的产品代码中,你应该使用唯一键和iv。所以使用HKDF来做类似这样的事情

代码语言:javascript
复制
std::string seed(AES_BLOCK_SIZE, '0');
std::generate(seed, seed + AES_BLOCK_SIZE,
    std::bind(&RandomGenerator::GetInt, &m_RNG, 0, 255));

SecByteBlock sharedSecret(32);
const byte usage[] = "Key and IV v1";

HKDF<SHA256> hkdf;
hkdf.DeriveKey(sharedSecret, 32, &seed[0], 16, usage, COUNTOF(usage), nullptr, 0);

AlgorithmParameters params =
        MakeParameters(Name::FeedbackSize(), 1 /*8-bits*/)
        (Name::IV(), ConstByteArrayParameter(sharedSecret+16, 16));

CFB_Mode< AES >::Encryption enc;
enc.SetKey(sharedSecret+0, 0, params);

在上面的代码中,sharedSecret是所需大小的两倍。您可以使用HDKF从种子派生密钥和iv。sharedSecret+0是16字节的密钥,sharedSecret+16是16字节的iv。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58916216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档