Я разрабатываю шифр под названием Дафна, который принимает байт открытого текста и возвращает зашифрованный байт и измененную Дафну. При применении к списку он должен возвращать список зашифрованных байтов и Дафну после обработки всех байтов. Я не уверен, как это сделать, не занимая O (n) памяти. Вот код:
byteEncrypt :: Daphne -> Word8 -> (Daphne,Word8)
byteEncrypt (Daphne key sreg acc) plain = ((Daphne key newsreg newacc),crypt) where
left = computeLeft key sreg acc
right = computeRight key sreg acc
crypt = step plain left right
newacc = acc+plain
newsreg = Seq.drop 1 (sreg |> crypt)
byteDecrypt :: Daphne -> Word8 -> (Daphne,Word8)
byteDecrypt (Daphne key sreg acc) crypt = ((Daphne key newsreg newacc),plain) where
left = computeLeft key sreg acc
right = computeRight key sreg acc
plain = invStep crypt left right
newacc = acc+plain
newsreg = Seq.drop 1 (sreg |> crypt)
seqEncrypt :: Seq.Seq Word8 -> (Daphne,Seq.Seq Word8) -> (Daphne,Seq.Seq Word8)
seqEncrypt Seq.Empty a = a
seqEncrypt (bs:|>b) (daph,acc) = (daph2,acc2) where
(daph1,acc1) = seqEncrypt bs (daph,acc)
(daph2,c) = byteEncrypt daph1 b
acc2 = acc1 |> c
listEncrypt :: Daphne -> [Word8] -> (Daphne,[Word8])
listEncrypt daph bs = (daph1,toList seq1) where
(daph1,seq1) = seqEncrypt (Seq.fromList bs) (daph,Seq.Empty)
seqDecrypt :: Seq.Seq Word8 -> (Daphne,Seq.Seq Word8) -> (Daphne,Seq.Seq Word8)
seqDecrypt Seq.Empty a = a
seqDecrypt (bs:|>b) (daph,acc) = (daph2,acc2) where
(daph1,acc1) = seqDecrypt bs (daph,acc)
(daph2,c) = byteDecrypt daph1 b
acc2 = acc1 |> c
listDecrypt :: Daphne -> [Word8] -> (Daphne,[Word8])
listDecrypt daph bs = (daph1,toList seq1) where
(daph1,seq1) = seqDecrypt (Seq.fromList bs) (daph,Seq.Empty)
listEncrypt имеет копию списка в ОЗУ в виде последовательности, которая занимает O(n) ОЗУ, что не должно быть необходимым.
Полный код находится на https://github.com/phma/daphne. Он еще не готов к производству; Я не проводил криптоанализ, не говоря уже о ком-то еще. Я могу пропускать через него гигабайты данных и вычислять статистику.





Я не совсем понял, зачем вы вообще ввели последовательности, поэтому я может неправильно понял проблему. Но это похоже на рекурсию список будет работать нормально. Что-то вроде (не проверено)
listEncrypt daph [] = (daph, [])
listEncrypt daph (b:bs) = (finalDaph, e:es)
where
(nextDaph, e) = byteEncrypt daph b
(finalDaph, es) = listEncrypt nextDaph bs
И на самом деле этот паттерн является mapAccumL. Я думаю, что byteEncrypt уже имеет свои аргументы в правильном порядке, так что это будет просто
listEncrypt = mapAccumL byteEncrypt
Любой из них должен нуждаться только в постоянной памяти, но с одной оговоркой.
Если вы проверите окончательную дафну перед использованием зашифрованного списка, для
например, выполнив print (listEncrypt something something), это будет
нужно пройти весь список, чтобы сначала получить окончательную дафну, а
хранить весь зашифрованный список в памяти, чтобы иметь возможность использовать этот
следующий. Сначала распечатайте зашифрованный список, а затем окончательные daphne и
все должно быть в порядке. И если вы только проверяете snd (listEncrypt something something), это должно работать даже в бесконечных списках.
Дафна уже использует последовательность в качестве регистра сдвига, поэтому использование последовательности не добавляет новых библиотек. Скоро пойду по магазинам, вечером попробую.