Объяснение алгоритма шифрования Blowfish

Мне трудно реализовать алгоритм шифрования Blowfish.

Может ли кто-нибудь объяснить мне, если это функция, в которой происходит шифрование:

 void encrypt (uint32_t & L, uint32_t & R) {
    for (int i=0 ; i<16 ; i += 2) {
       L ^= P[i];
       R ^= f(L);
       R ^= P[i+1];
       L ^= f(R);
    }
    L ^= P[16];
    R ^= P[17];
    swap (L, R);
 }

так как бы выглядела такая функция:

/**
*
* @param string text this is the text to be encrypted
* @return string this is encrypted text 
*/
string EncryptBlowfish(string text){
    //something happens here
}

person user3325976    schedule 23.03.2014    source источник
comment
Blowfish, вероятно, является самым простым и элегантным шифрованием для понимания.   -  person leppie    schedule 23.03.2014
comment
Если вы прочтете функцию key_schedule предоставленной вами ссылки, вы увидите, где происходит шифрование. Функция encrypt работает с двумя последовательными словами в блоке.   -  person Zac Howland    schedule 23.03.2014
comment
Код настолько сложен для понимания из коробки, и я не нашел примеров, чтобы его можно было легко прочитать. У тебя есть @ZacHowland?   -  person user3325976    schedule 24.03.2014
comment
@ user3325976 Я бы порекомендовал вам инвестировать в прикладную криптографию для начала.   -  person Zac Howland    schedule 24.03.2014


Ответы (1)


Как правило, вам следует просмотреть существующие интерфейсы библиотек шифрования и теоретическое описание Blowfish, чтобы лучше понять, как эти реализации были реализованы ранее, включая дизайн интерфейса. Чтобы спроектировать хороший интерфейс, вам нужно найти приличное количество вариантов использования для вашего кода, и в отсутствие этого образца данных, уникального для вашего случая, вы должны вернуться к уже общепринятой мудрости.

Например, взгляните на страницу crypto++ для blowfish (и прокрутите страницу до конца). чтобы пропустить потоки и фильтры, где показано использование шифровальщика, который может передавать отдельные байты).

Продолжая этот пример, ваш код может выглядеть так:

class StatefulBlowfish {    
private:
   BlowfishKey key_;
   BlowfishIv iv_;
public:    
void EncryptCBC(string text, /*out*/ byte*){
   for (int i=0; I < text.size(); i++) {
      // process and xor an individual ‘(byte)text[i]’ the 
      // necessary number of rounds. Consider padding.
  }
  ...    
}

Но такой класс не очень общий и имеет много фиксированных частей, которые могут затруднить его тестирование, использование и поддержку. Еще одна важная вещь, которую следует учитывать, заключается в том, что интерфейс, который вы должны разработать, не ограничивается использованием строки для шифрования, как вы предлагаете в вопросе, а скорее должен учитывать режим цепочки, ключ и iv - они лучше всего создавать и управлять в другом месте, чтобы придерживаться принципа единой ответственности.

Вы также должны стремиться иметь массивы или указатели на массивы байтов в качестве интерфейса ваших низкоуровневых методов шифрования, потому что именно так работает алгоритм, и в идеале сериализация из строки в массив байтов (и наоборот) должна быть выгружены на отдельный интерфейс. (Рассмотрите, например, предположения о «строке» между архитектурами с прямым порядком байтов и прямым порядком байтов или требования к заполнению.)

Хороший общий ООП-проект — это, с одной стороны, набор «частей» шифрования, каждая из которых несет более или менее единственную ответственность (сериализация, заполнение, режим цепочки, инициализация ключа, расписание ключей и т. д.), а с другой стороны, хороший дизайн допускает простое создание более крупной конструкции цепочки ответственности, которая описывает намерение, просто наблюдая за кодом.

Возвращаясь к cryptopp, изменив стандартный пример кода для большей ясности, посмотрите, как все обрабатывается по отдельности:

// a key is created, to be separately initialised with a PRNG
// or from a secure source, hardware TRNG, etc.
SecByteBlock key(Blowfish::DEFAULT_KEYLENGTH); 
...
// an iv is created, similarly to be separately initialised with a PRNG
byte iv[Blowfish::BLOCKSIZE]; 
...
// Wrap blowfish low-level implementation in a CBC chaining mode 
// and initialise it with the key and iv    
CBC_Mode<Blowfish>::Encryption e; 
e.SetKeyWithIV(key, key.size(), iv);    
...    
// have a separate padding wrapper
... new StreamTransformationFilter(e, /*out*/ cipher)
person mockinterface    schedule 24.03.2014