AES-128 CFB-8解密的前16个字节已损坏 [英] First 16 bytes of AES-128 CFB-8 decryption are damaged

查看:151
本文介绍了AES-128 CFB-8解密的前16个字节已损坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近一直在研究一个项目,该项目应该在协议的帮助下连接到服务器.到目前为止,一切都很好,但是当我梳理解密程序包时,我很快注意到有些东西无法正常工作.

I've been working on a project recently that should connect to a server with the help of a protocol. So far so good, but when I combed to decrypt the packages, I quickly noticed that something is not working properly.

所有数据包的前16个字节被错误地解密.我已经尝试过使用不同的库,但这也不起作用.我使用C ++语言工作,到目前为止,使用Crypto ++和OpenSSL进行解密都没有成功.

The first 16 bytes of all packets are decrypted incorrectly. I have tried it with different libraries but that does not work either. I work in the C++ language and have so far used Crypto++ and OpenSSL for decryption, without success.

在此链接下,您可以在此处找到协议解密协议链接,这是我对应的代码:

Under this Link you can find the protocol, here the decryption protocol Link and here is my corresponding code:

OpenSSL:

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 ++:

Crypto++:

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(初始化向量)使用了一个相同的共享机密.在其他帖子中,这通常被标记为问题.我不知道在这种情况下如何解决它,因为协议需要它.

I think important to mention is that I use one and the same shared secret for the key and the iv (initialization vector). In other posts, this was often labeled as a problem. I do not know how to fix it in this case because the protocol want it.

我期待着建设性的反馈.

I would be looking forward to a constructive feedback.

推荐答案

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

并且:

CFB_Mode<AES>::Decryption AESDecryptor((byte*)sharedSecret.c_str(),
    (unsigned int)16, sharedSecret.c_str(), 1);

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

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

It is not readily apparent, but you need to set feedback size for the mode of operation of the block cipher in Crypto++. The Crypto++ feedback size is 128 by default.

可以在以下位置的 CFB模式中找到设置CFB模式反馈大小的代码. Crypto ++ Wiki.您需要页面下方的第3个或第4个示例.

The code to set the feedback size of CFB mode can be found at CFB Mode on the Crypto++ wiki. You want the 3rd or 4th example down the page.

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

这是一种传递参数的尴尬方式.它记录在源文件和Wiki的 NameValuePairs 上.它允许您通过一致的接口传递任意参数.一旦您领会了它,它就会很强大.

That is kind of an awkward way to pass parameters. It is documented in the sources files and on the wiki at NameValuePairs. It allows you to pass arbitrary parameters through consistent interfaces. It is powerful once you acquire a taste for it.

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

And then use params to key the encryptor and decryptor:

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):

I believe your calls would look something like this (if I am parsing the OpenSSL correctly):

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 :

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.

In the code above, sharedSecret is twice as large as it needs to be. You derive the key and iv from the seed using HDKF. sharedSecret+0 is the 16-byte key, and sharedSecret+16 is the 16-byte iv.

这篇关于AES-128 CFB-8解密的前16个字节已损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆