Поясню: в устройство нужен по возможности криптостойкий RND-генератор (не генератор гаммы). В качестве случайных salt-значений доступны временные отсчеты различных системных событий (прерываний и т.д.).
Использовать hash-функцию очень не хочется, слишком много вычислений.
RC4 в принципе подходит, но для модификации его таблиц желательны "отбеленные" данные, а голые timestamps не подходят. Поэтому я решил сделать быстрое и "правильное" отбеливание. После проверки выхода алгоритма отбеливания встал вопрос - а нужен ли RC4 ?
Вот этот отбеливатель/генератор и нужно заценить:
Идея:
M - разрядность машинного слова, N - небольшое натуральное число (8 <= N <= 256);
Организуем M «параллельных» регистров сдвига, длинной N, с обратной связью, так чтобы биты в одной позиции регистров образовывали машинное слово.
В качестве нелинейной функции обратной связи используем сложение по модулю M циклически сдвинутого на 3 слова, образованного одним из отводов генераторов, и обычной комбинацией (сложение по модулю 2) слов остальных "обычной" обратной связи. Параллельные регистры сдвига реализуем на кольцевом буфере размера N.
Добавление исходных salt-значений происходит независимо от выборки отбеленных. Добавление - по событию, выборка - при необходимости, одновременно со сдвигом регистров. Добавление salt-значение реализуется
"кольцевым" сложением (сложением с последующим добавлением собственного переноса) к элементам кольцевого буфера, перебираемых по кругу.
// псевдо код с++
unsinged poo[lN]; // кольцевой буфер
usigned head, tail; // при старте == 0
void push_salt(unsigned salt)
{
unsigned value = pool[head] + salt;
pool[head] = value + (value < salt); // кольцевое сложение с переносом
head = (head + 1) % N;
}
unsigned pop_salt()
{
// y ~~ F(X**N, X**23 + X**17);
unsigned result = rotate(pool[tail], 3);
result += pool[tail + 17] ^ pool[tail + 23];
pool[tail] = result + 1;
tail = (tail + 1) % N;
return result;
}
---
Сейчас за основу взят полином (N, 23, 17, 0), можно взять хороший/неприводимый например (63, 1, 0), но я думаю что для такой обратной связи все равно. Точнее говоря, я не могу вывести критерии выбора "лучшего" полинома. Может кто-нибудь плавает в GF лучше рыбы, или есть знакомые ?
Зацените генератор plz (GF experience is needed)08.09.03 10:28 Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
Не такой уж и легкий, а достаточно навороченый.
Все, конечно, хорошо, вот только медленный должен быть (более сотни тактов на генерацию).
Хотя на современных гигагерцовых процессорах это не заметно будет.
Сначала речь шла о каком-то устройстве. Эту штуку что, аппаратно реализовывать надо будет? Или в состав устройства будет входить компьютер на базе процессора Пентиум4? Для устройства-то лучше что-нибудь на основе "железного" RNG. Приведенный алгоритм не очень-то и прост для аппаратной реализации.
Думаю, если массивчик раза в два или в четыре покороче сделать - стойкость сильно не упадет.
Самое главное, чтобы LYSAP_RandomPushSalt достаточно часто вызывался. Через раз достаточно будет. А то вдруг на милион LYSAP_GetRandom один LYSAP_RandomPushSalt придется.
>
> unsigned LYSAP_GetRandom()
> {
> unsigned __int32 Value =
> Random.Pool[Random.Tail] // X ** 1
> ^ Random.Pool[(Random.Tail + 1) & 63] // X ** 64
> ^ Random.Pool[(Random.Tail + 62) & 63] // X ** 4
> ^ Random.Pool[(Random.Tail + 61) & 63]; // X ** 3
>
> unsigned __int32 Salt =
> 1 // may be any non-zero
> + ROT_L(Random.Pool[(Random.Tail + 11) & 63], 5)
> + ROT_L(Random.Pool[(Random.Tail + 23) & 63], 7)
> + ROT_L(Random.Pool[(Random.Tail + 37) & 63], 1);
>
> Value += Salt; Value += Value < Salt; // cyclic
> addition with carry
> Random.Pool[Random.Tail = (Random.Tail + 1) & 63] =
> Value;
> return Value;
> }
---
И все таки "легкий", а не "сложный"23.07.03 10:57 Автор: leo <Леонид Юрьев> Статус: Elderman
> Не такой уж и легкий, а достаточно навороченый. > Все, конечно, хорошо, вот только медленный должен быть > (более сотни тактов на генерацию). > Хотя на современных гигагерцовых процессорах это не заметно > будет. > Сначала речь шла о каком-то устройстве. Эту штуку что, > аппаратно реализовывать надо будет? Или в состав устройства > будет входить компьютер на базе процессора Пентиум4? Для > устройства-то лучше что-нибудь на основе "железного" RNG. > Приведенный алгоритм не очень-то и прост для аппаратной > реализации. > Думаю, если массивчик раза в два или в четыре покороче > сделать - стойкость сильно не упадет. > Самое главное, чтобы LYSAP_RandomPushSalt достаточно часто > вызывался. Через раз достаточно будет. А то вдруг на милион > LYSAP_GetRandom один LYSAP_RandomPushSalt придется.
И все таки "легкий", а не "сложный":
- Нет ни одного умножения, и ни одного деления;
- В процедурах генерации нет ни одного цикла;
- Размер массива кратен степени двойки;
- Мало операций: три сдвига, три XOR-а, четыре сложения (одно простое);
А если сравнить с генерацией на базе SHA, MD5 или RIPE-MD, то гораздо проще - в разы.
Генерация в RC4 проще, но он выдает байт за такт, и требует больше операций для PushSalt().
Будет использоваться и в embedded ПО, и в железе. Реализуется на VHLD с легкостью.
Уменьшать буфер лучше не надо - там примитивный полином X**64 + X**4 + X**3 + 1. Но можно уменьшить разрадность с 32 до 16.
PushSalt() добавляет "неопределенность", но не влияет на качество распределения. Поэтому если PushSalt() не делать вообще, то получиться просто хороший генератор псевдослучайных чисел.
С другой стороны, каждый бит из PushSalt(), через 4096 тактов генерации, почти равновероятно влияет на каждый бит состояния генератора, и каждое сгенерированное число.
И все таки "легкий", а не "сложный"23.07.03 12:03 Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
> Будет использоваться и в embedded ПО, и в железе. > Реализуется на VHLD с легкостью.
Я это к тому, что если случайные числа нужны (генерация ключа, например), то везде это намного проще реализовано (пользователь катает мышку или жмет на кнопки и замеряются временные интервалы). Если ПСЧ (для гаммы по ключу, например), так там никакой случайности быть не должно.
> Уменьшать буфер лучше не надо - там примитивный полином > X**64 + X**4 + X**3 + 1. Но можно уменьшить разрадность с > 32 до 16. > > PushSalt() добавляет "неопределенность", но не влияет на > качество распределения. Поэтому если PushSalt() не делать > вообще, то получиться просто хороший генератор > псевдослучайных чисел.
Генератор хороший, но уже ПСЧ и предсказуемый, стало быть.
> С другой стороны, каждый бит из PushSalt(), через 4096 > тактов генерации, почти равновероятно влияет на каждый бит > состояния генератора, и каждое сгенерированное число.