У меня трудные времена реализации алгоритм шифрования 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
}
Как правило, вам следует ознакомиться с существующими интерфейсами библиотеки шифрования и теоретическим описанием Blowfish, чтобы лучше понять, как выполнялась эта реализация ранее, включая дизайн интерфейса. Чтобы спроектировать хороший интерфейс, вам нужно набрать приличное количество вариантов использования для вашего кода, и в отсутствие этого примера данных, уникального для вашего случая, вы должны вернуться к уже общепринятому мнению.
Например, взгляните на крипто ++ страница для 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)
Других решений пока нет …