Как перетасовать, а затем снять чехол, получив ключ в качестве семени

#python #arrays #random #cryptography #shuffle

Вопрос:

Я пытаюсь создать систему шифрования, и для этого я буду использовать bytearray, и я намерен использовать

random.Random(seed).shuffle(bytearray)

функция шифрования информации.

У меня возникли проблемы с обращением вспять этого процесса для расшифровки, я попробовал что-то вроде (не сработало) :

random.Random(1/seed).shuffle(encryptedbytearray)

Есть ли вообще способ это сделать?

Комментарии:

1. @Leemosh Они пытаются отменить перетасовку массива, а не произвести воспроизводимую перетасовку.

2. Межсайтовый обман на crypto.se , хотя в ответе много ненужной математики.

3. Примечание: использовать собственную криптографию и использовать ее в производственном коде-плохая идея ™. Совершенно нормально создать его в образовательных целях, но настоятельно рекомендуется использовать существующую криптосистему для любого производственного кода. (Особенно учитывая, что python random использует твистер Мерсенна, который не является криптографически безопасным).

4. спасибо @SuperStrormer, ваш ответ мне очень помог, чистый код, который легко понять. Да, я понимаю, что использовать это для чего-то более серьезного-плохая идея™, но я просто использую это для личного использования и для того, чтобы научиться программировать. Спасибо вам за вашу драгоценную помощь. 🙂

Ответ №1:

Вам нужно использовать одно и то же начальное значение для перетасовки индексов, чтобы вы могли отследить исходные позиции. (перечисление позволит вам избежать сортировки этого сопоставления)

 import random

def encrypt(decrypted,seed=4):
    encrypted = decrypted.copy()
    random.Random(seed).shuffle(encrypted)
    return encrypted

def decrypt(encrypted,seed=4):
    decrypted = encrypted.copy()
    indexes   = list(range(len(encrypted)))
    random.Random(seed).shuffle(indexes)
    for e,d in enumerate(indexes):
        decrypted[d] = encrypted[e]
    return decrypted
 

Примерный запуск (с использованием списка символов, но он будет работать для bytearrays или любого другого типа списков):

 clearText = list('ABCDE')

encryptedText = encrypt(clearText)
print(encryptedText)
['D', 'E', 'A', 'C', 'B']

decryptedText = decrypt(encryptedText)
print(decryptedText)
['A', 'B', 'C', 'D', 'E']
 

Если вы хотите, чтобы функции работали «на месте» непосредственно в массиве (вместо того, чтобы возвращать значение), вы можете записать их следующим образом:

 def encrypt(decrypted,seed=4):
    random.Random(seed).shuffle(encrypted)

def decrypt(encrypted,seed=4):
    before   = encrypted.copy()
    indexes  = list(range(len(encrypted)))
    random.Random(seed).shuffle(indexes)
    for e,d in enumerate(indexes):
        encrypted[d] = before[e]
 

Ответ №2:

Перетасуйте отсортированный диапазон, чтобы мы могли сопоставить перетасованные показатели с не перетасованными показателями.

 x = list(range(len(s)))
random.Random(seed).shuffle(x)
 

Для семени 12345 это дает [14, 15, 12, 3, 24, 16, 7, 22, 10, 2, 19, 4, 20, 17, 1, 21, 5, 25, 18, 8, 6, 11, 9, 0, 23, 13] результат . Это указывает на то, что значение 0-го индекса в перетасованном списке на самом деле находится в 14-м индексе неупорядоченного списка, 1-й индекс на самом деле является 15-м неупорядоченным и т. Д.

Затем сопоставьте каждый перемешанный индекс с перемешанным значением, а затем отсортируйте (на основе индекса) обратно в их неупорядоченные позиции.

 unshuffled = bytearray(c for i, c in sorted(zip(x, s)))
print(unshuffled)
 

Полный пример:

 import random
# setup
s = bytearray(b"abcdefghijklmnopqrstuvxwyz")
seed = 12345
random.Random(seed).shuffle(s)

# shuffle a sorted range, so that we can match the shuffled indicies to the unshuffled indicies
x = list(range(len(s)))
random.Random(seed).shuffle(x)

# match each shuffled index to the shuffled value, and then sort (based on the index) back into their unshuffled positions
unshuffled = bytearray(c for i, c in sorted(zip(x, s)))
print(unshuffled)
 

Процесс, описанный выше, должен работать для любой перетасованной последовательности (например, списков), а не только для bytearray.

Вот более подробное объяснение этого процесса на crypto.se с гораздо большим количеством математики.