2015-02-26 4 views
1

Возможно ли создать новый объект Encryption, который имеет такое же внутреннее состояние, что и ранее созданный объект Encryption (мне нужно это, чтобы поддерживать только IV между вызовами функций, а не весь объект)?Как получить/установить внутреннее состояние объекта шифрования CFB_Mode?

Я думал, что это должно быть возможно с помощью функции GetNextIV, но я не получил нужный результат. В следующем примере строка This is the text будет закодирован и правильный закодированный текст:

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

Но я получаю:

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

Как вы можете видеть только первый байт (94) кодируется правильно. Вы можете попробовать его со следующим примером кода:

#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

Я подумал, что это должно быть возможно с функцией GetNextIV, но я не получил нужного результата ...

К сожалению, нет. Вот комментарии по GetNextIV из 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); 

Так GetNextIV используется для получения капельницы, которые отвечают требованиям IV шифра для различных сообщений, а не внутреннее состояние для текущего сообщения.

Второй ключ, который не показывает внутреннее состояние, - это параметр PRNG. Если вы используете NullRNG(), тогда он должен выбросить исключение. Внутреннее состояние не должно быть рандомизированы :)


Как получить внутреннее состояние CFB_Mode шифрования объекта?

Я думаю внутреннее состояние вы ищете в m_register и m_temp. Они защищены и не имеют доступа, поэтому вам нужно будет изменить библиотеку.

От 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; 
}; 

От 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); 
} 

Как установить внутреннее состояние CFB_Mode шифрования объекта?

Это проще. Просто позвоните SetKeyWithIV или Resynchronize.

+0

Благодарим вас за ответ.Как установить состояние, как вы думаете, мне нужно вызвать 'SetKeyWithIV' с ранее извлеченным значением' m_temp' или 'm_register'? –

Смежные вопросы