Python - пытается разобраться с битами файла - PullRequest
0 голосов
/ 03 февраля 2012

Я совсем недавно начал изучать Python, и я решил изучать вещи, пытаясь решить проблему, которая мне кажется интересной.Эта проблема состоит в том, чтобы взять файл (двоичный или нет) и зашифровать его, используя простой метод, что-то вроде замены каждого «1001 0001» в нем на «0010 0101», и наоборот.

ОднакоЯ не нашел способ сделать это.При чтении файла я могу создать массив, в котором каждый элемент содержит один байт данных, с помощью метода read ().Но как я могу заменить этот байт другим, если это один из байтов, которые я выбрал для замены, и затем записать полученную информацию в выходной зашифрованный файл?

Заранее спасибо!

Ответы [ 4 ]

2 голосов
/ 03 февраля 2012

Чтобы поменять местами байты 10010001 и 00100101:

#!/usr/bin/env python
import string

a, b = map(chr, [0b10010001, 0b00100101])
translation_table = string.maketrans(a+b, b+a) # swap a,b

with open('input', 'rb') as fin, open('output', 'wb') as fout:
     fout.write(fin.read().translate(translation_table))
1 голос
/ 03 февраля 2012

read () возвращает неизменную строку, поэтому сначала вам нужно преобразовать ее в список символов.Затем просмотрите список и измените байты, если необходимо, и, наконец, объедините список обратно в новую строку для записи в выходной файл.

filedata = f.read()
filebytes = list(filedata)
for i, c in enumerate(filebytes):
    if ord(c) == 0x91:
        filebytes[i] = chr(0x25)
newfiledata = ''.join(filebytes)
0 голосов
/ 03 февраля 2012

Я сожалею об этой несколько релевантной стене текста - у меня просто учебное настроение.

Если вы хотите оптимизировать такую ​​операцию, я предлагаю использовать numpy ,Преимущество состоит в том, что вся операция перевода выполняется с помощью одной отдельной операции, и они написаны на C, так что это почти так же быстро, как вы можете получить ее, используя python.

В приведенном ниже примере я просто XOR каждый байт с 0b11111111 с использованием справочной таблицы - первый элемент - это перевод 0b0000000, второй - перевод 0b00000001, третий 0b00000010 и т. Д.Изменяя таблицу поиска, вы можете выполнять любые переводы, которые не меняются внутри файла.

import numpy as np
import sys

data = np.fromfile(sys.argv[1], dtype="uint8")
lookup_table = np.array(
    [i ^ 0xFF for i in range(256)], dtype="uint8")
lookup_table[data].tofile(sys.argv[2])

Чтобы подчеркнуть простоту всего этого, я не проверял аргументы.Вызовите скрипт следующим образом:

python name_of_script.py input_file.txt output_file.txt

Чтобы напрямую ответить на ваш вопрос, если вы хотите поменять местами 0b10010001 и 0b00100101, вы замените строку lookup_table = ... на эту:

lookup_table = np.array(range(256), dtype="uint8")
lookup_table[0b10010001] = 0b00100101
lookup_table[0b00100101] = 0b10010001

Конечно, нет шифрования справочной таблицы, которое нелегко взломать с помощью частотного анализа .Но, как вы, возможно, знаете, шифрование с использованием одноразовой клавиатуры невозможно сломать, если она безопасна.Этот измененный сценарий шифрует или дешифрует с помощью одноразовой панели (которую вы должны будете создать самостоятельно, сохранить в файле и каким-то образом (есть проблема) безопасно передать предполагаемому получателю сообщения):

data = np.fromfile(sys.argv[1], dtype="uint8")
pad = np.fromfile(sys.argv[2], dtype="uint8")
(data ^ pad[:len(data)]).tofile(sys.argv[3])

Пример использования (linux):

$ dd if=/dev/urandom of=pad.bin bs=512 count=5
$ python pytrans.py pytrans.py pad.bin encrypted.bin

Получатель затем делает:

$ python pytrans.py encrypted.bin pad.bin decrypted.py

Альт!Быстрое и неразрушимое шифрование с тремя строками (плюс две строки импорта) в python.

0 голосов
/ 03 февраля 2012

После ответа Аарона, когда у вас есть строка, вы также можете использовать translate или replace:

In [43]: s = 'abc'

In [44]: s.replace('ab', 'ba')
Out[44]: 'bac'

In [45]: tbl = string.maketrans('a', 'd')

In [46]: s.translate(tbl)
Out[46]: 'dbc'

Документы: Python string.

...