How to get/set internal state of a CFB_Mode Encryption Object?

烈酒焚心 提交于 2020-02-25 09:17:08

问题


Is it possible to create a new Encryption object that has the same internal state as a previously created Encryption object (I need this, to only keep the IV between function calls, and not the whole object)?

I thought it should be possible with the function GetNextIV but I didn't get the right result. In the following example the string This is the text gets encoded and the correct encoded text is:

94-41-d2-d4-06-05-f6-cd-d0-25-d6-f4-f6-52-55-7b-7c-

But I get:

94-a8-a9-b3-e0-a9-b3-e0-b4-a8-a5-e0-b4-a5-b8-b4-c0-

As you can see only the first byte (94) is encoded right. You can try it with following code sample:

#include <iostream>
#include <iomanip>
#include <crypto++/modes.h>
#include <crypto++/aes.h>
#include <crypto++/osrng.h>

using namespace CryptoPP;

void printHex(const byte in) {
    std::cout << std::setfill('0') << std::setw(2) << std::hex << (int)in << "-";
}

int main() {

    // Generate a random key and IV
    AutoSeededRandomPool rnd;
    SecByteBlock key(0x00, AES::DEFAULT_KEYLENGTH);
    rnd.GenerateBlock(key, key.size());
    byte iv[AES::BLOCKSIZE];
    rnd.GenerateBlock(iv, AES::BLOCKSIZE);

    // Encrypt byte by byte
    // this results in the correct encrypted text
    byte text[] = "This is the text";
    int msgLen = sizeof(text);
    CFB_Mode<AES>::Encryption cfbEncB(key, key.size(), iv);
    for (byte* beg = &text[0]; beg != &text[msgLen]; ++beg) {
        printHex(cfbEncB.ProcessByte(*beg));
    }
    std::cout << std::endl;

    // Encrypt byte by byte only keeping IV for each iteration
    // This is not the expected output, how to get it right?
    byte nextiv[AES::BLOCKSIZE];
    std::copy(&iv[0], &iv[AES::BLOCKSIZE], &nextiv[0]);
    for (byte* beg = &text[0]; beg != &text[msgLen]; ++beg) {
        CFB_Mode<AES>::Encryption cfbEncC(key, key.size(), nextiv);
        printHex(cfbEncC.ProcessByte(*beg));
        cfbEncC.GetNextIV(nextiv);
    }
    std::cout << std::endl;
}

回答1:


I thought it should be possible with the function GetNextIV but I didn't get the right result...

Sadly, NO. Here's the comments on GetNextIV from cryptlib.h:

//! get a secure IV for the next message
/*! This method should be called after you finish encrypting one message and are ready to start the next one.
    After calling it, you must call SetKey() or Resynchronize() before using this object again. 
    This method is not implemented on decryption objects. */
virtual void GetNextIV(RandomNumberGenerator &rng, byte *IV);

So GetNextIV is used to get IVs that meet the cipher's IV requirements for distinct messages, and not the internal state for the current message.

The second clue it does not reveal internal state is the PRNG parameter. If you use the NullRNG(), then it should throw an exception. Internal state should not be randomized :)


How to get internal state of a CFB_Mode Encryption Object?

I think the internal state you are looking for is in m_register and m_temp. They are protected and lack accessors, so you will need to modify the library.

From modes.h:

class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
{
public:
    IV_Requirement IVRequirement() const {return RANDOM_IV;}
    static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";}

protected:
    unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
    byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
    bool CanIterate() const {return m_feedbackSize == BlockSize();}
    void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount);
    void TransformRegister();
    void CipherResynchronize(const byte *iv, size_t length);
    void SetFeedbackSize(unsigned int feedbackSize);
    void ResizeBuffers();

    SecByteBlock m_temp;
    unsigned int m_feedbackSize;
};

From modes.cpp:

void CFB_ModePolicy::Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount)
{
    assert(m_cipher->IsForwardTransformation());    // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
    assert(m_feedbackSize == BlockSize());

    unsigned int s = BlockSize();
    if (dir == ENCRYPTION)
    {
        m_cipher->ProcessAndXorBlock(m_register, input, output);
        m_cipher->AdvancedProcessBlocks(output, input+s, output+s, (iterationCount-1)*s, 0);
        memcpy(m_register, output+(iterationCount-1)*s, s);
    }
    else
    {
        memcpy(m_temp, input+(iterationCount-1)*s, s);  // make copy first in case of in-place decryption
        m_cipher->AdvancedProcessBlocks(input, input+s, output+s, (iterationCount-1)*s, BlockTransformation::BT_ReverseDirection);
        m_cipher->ProcessAndXorBlock(m_register, input, output);
        memcpy(m_register, m_temp, s);
    }
}

void CFB_ModePolicy::TransformRegister()
{
    assert(m_cipher->IsForwardTransformation());    // CFB mode needs the "encrypt" direction of the underlying block cipher, even to decrypt
    m_cipher->ProcessBlock(m_register, m_temp);
    unsigned int updateSize = BlockSize()-m_feedbackSize;
    memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize);
    memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize);
}

How to set internal state of a CFB_Mode Encryption Object?

This one is easier. Just call SetKeyWithIV or Resynchronize.



来源:https://stackoverflow.com/questions/28744134/how-to-get-set-internal-state-of-a-cfb-mode-encryption-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!