Тот код C, на который вы ссылались, был бы очень полезен для включения в вопрос ;-) В любом случае, я пошел дальше и перевел его на Python.Прежде чем читать, позвольте мне сказать, что я настоятельно рекомендую вам попробовать это самостоятельно и использовать только мою транскрипцию в качестве руководства.Перевод алгоритмов с одного языка программирования на другой - это, как правило, отличная практика, когда вы хотите повысить свои навыки в одном или обоих языках.Даже если вы не знаете C, если вы достаточно знакомы с Python для написания программ на нем, вы должны быть в состоянии понять суть кода C, поскольку существует много сходств.
В любом случае, к коду.
import itertools, operator
Во-первых, генератор псевдослучайных чисел, который был обозначен в представлении как линейный конгруэнтный генератор .Этот тип PRNG является общим алгоритмом, который можно «настраивать», выбирая конкретные значения a
, c
и m
(переменные, упомянутые в статье Википедии).Вот реализация универсального линейного конгруэнтного генератора:
def prng(x, a, c, m):
while True:
x = (a * x + c) % m
yield x
(надеюсь, вы могли бы придумать это самостоятельно)
Теперь для фактической функции:
def pass_to_key(passphrase):
Первым шагом в этом процессе является хэширование (или «отображение») парольной фразы, предоставленной для 32-битного числа.Алгоритм WEP делает это путем создания набора из 4 байтов (таким образом, 4 * 8 = 32 бита), которые инициализируются в ноль.
bits = [0,0,0,0]
Он проходит через строку и XOR каждый символ с одним из байтов;в частности, символ i
переводится в XOR в байт i % 4
.
for i, c in enumerate(passphrase):
bits[i & 3] ^= ord(c)
Затем эти четыре байта объединяются вместе, чтобы сформировать одно 32-битное значение.(В качестве альтернативы я мог бы написать код для хранения их в виде 32-разрядного числа с начала)
val = reduce(operator.__or__, (b << 8*i for (i,b) in enumerate(bits)))
Это 32-разрядное значение используется в качестве начального числа для линейного конгруэнтного генератора с определенными конкретными значениямикоторый вы можете увидеть в коде.Как первоначальный разработчик вычислил эти числа, я понятия не имею.
keys = []
Линейный конгруэнтный генератор может производить до 32 битов вывода одновременно.(В C это ограничение типа данных; в Python мне пришлось принудительно применять его.) Мне нужно 20 байтов для генерации 4 40-битных (5-байтовых) ключей WEP, поэтому я буду повторять PRNG 20 раз,
for i, b in enumerate(itertools.islice(prng(val, 0x343fd, 0x269ec3, 1<<32), 20)):
и от каждого числа берите только третий байт справа (биты 16-23):
keys.append((b >> 16) & 0xff)
Почему третий?Ну, биты на верхнем конце (4-й справа), как правило, не сильно меняются, а биты на нижнем конце могут быть предсказуемыми для многих значений констант PRNG.
После этого остается толькораспечатать сгенерированные байты в группах по 5 *. 1041 *
print ('%02x:%02x:%02x:%02x:%02x\n'*4) % tuple(keys)