2015-03-25 4 views
3

У меня есть тестовый инструмент, который использует Twofish в качестве алгоритма шифрования для шифрования данных перед отправкой на сервер. Код написан на C++ и использует оптимизированную реализацию C Bruce Schneier (https://www.schneier.com/code/twofish-optimized-c.zip). Мне нужно перенести этот инструмент на Python, и я использую модуль twofish (https://pypi.python.org/pypi/twofish/0.3.0). Я могу шифровать и расшифровывать строки длиной 16 символов, но для других длин строк он дает ошибку «ValueError: недопустимая длина блока».Twofish encryption in Python

Как я могу зашифровать & расшифровать большие данные с помощью модуля Twofish Python?

>>> from twofish import Twofish 
>>> key = binascii.unhexlify('8CACBE276491F6FF4B1EC0E9CFD52E76') 
>>> t = Twofish(key) 
>>> cipher_text = T.encrypt('deadbeaf12345678') 
>>> plain_text = t.decrypt(cipher_text) 
>>> plain_text 
'deadbeaf12345678' 
>>> cipher_text = t.encrypt('deadbeaf12345678hello world 1234') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/local/lib/python2.7/site-packages/twofish.py", line 69, in encrypt 
    raise ValueError('invalid block length') 
ValueError: invalid block length 

Update: Я пробуя другое решение этой проблемы. Я создал Windows DLL, twofish.dll из оптимизированной реализации C Bruce Schneier (https://www.schneier.com/code/twofish-optimized-c.zip). Кроме того, я экспортировал функции-обертки для кодирования & функции расшифровки члена с помощью __declspec (dllexport).

Я загружаю эту DLL в Python, используя ctype.CDLL. Прототип функции кодирования является:

__declspec(dllexport) int encode(unsigned char *key, unsigned char *in, unsigned int inlen, unsigned char *out, unsigned int outbuflen, unsigned int& outlen) 

Как следует определить типы аргументов в сценарии Python?

import ctypes 
import binascii 
import requests 

twofish_dll = ctypes.CDLL("twofish.dll") 

encode = twofish_dll.encode 

f = open('test.xml', 'r') 
plain_text = f.read() 
f.close() 

cipher_text = ctypes.create_string_buffer(8192) 
cipher_text_lenght = (ctypes.c_uint)() 

KCS = '8CACBE276491F6FF4B1EC0E9CFD52E76' 
key = binascii.unhexlify(KCS) 

encode.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint, ctypes.c_char_p, ctypes.c_uint, ctypes.POINTER(ctypes.c_uint)] 
encode(ctypes.c_char_p(key), ctypes.c_char_p(plain_text), len(plain_text), cipher_text, 8192, ctypes.byref(cipher_text_lenght)) 

При выполнении приведенного выше кода ошибки бросает ниже:

Traceback (most recent call last): 
    File "C:\Data\sepm_test.py", line 21, in <module> 
    encode(ctypes.c_char_p(key), ctypes.c_char_p(plain_text), len(plain_text), cipher_text, 8192, ctypes.byref(cipher_text_lenght)) 
TypeError: bytes or integer address expected instead of str instance 

ответ

1

Я, наконец, решил эту проблему, собрав оптимизированную реализацию C Bruce Schneier для Twofish (https://www.schneier.com/code/twofish-optimized-c.zip) в DLL и загрузив эту DLL, используя модуль ctypes.

import ctypes 
import binascii 
import requests 

twofish_dll = ctypes.CDLL("twofish.dll") 

encode = twofish_dll.encode 

f = open('test.xml', 'r') 
plain_text = f.read() 
f.close() 
plain_text_buffer = ctypes.create_string_buffer(str.encode(plain_text)) 
plain_text_buffer_length = (ctypes.c_uint)(len(plain_text_buffer)) 

cipher_text_buffer = ctypes.create_string_buffer(8192) 
cipher_text_buffer_length = (ctypes.c_uint)(len(cipher_text_buffer)) 
cipher_text_length = ctypes.c_uint(0) 

KCS = '8CACBE276491F6FF4B1EC0E9CFD52E76' 
key = binascii.unhexlify(KCS) 

encode.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_uint, ctypes.c_char_p, ctypes.c_uint, ctypes.POINTER(ctypes.c_uint)] 
encode.restype = ctypes.c_int 

encode(ctypes.c_char_p(key), plain_text_buffer, plain_text_buffer_length, cipher_text_buffer, cipher_text_buffer_length, ctypes.pointer(cipher_text_length)) 
2

Twofish представляет собой блочный шифр, который шифрует только 16 октетов в то время. Quoth the documentation:

Create a twofish.Twofish instance with a key of length ]0, 32] and then use the encrypt and decrypt methods on 16 bytes blocks.

All values must be binary strings (str on Python 2, bytes on Python 3)

[WARNING] this should be used in a sensible cipher mode, like CTR or CBC. If you don't know what this means, you should probably use a higher level library.

ли обратить внимание на предупреждение, CBC or CTR is not rocket science, но если вы используете Twofish наивности, его безопасность ужасающе скомпрометированы.

+1

Для CBC для зашифрования данных произвольной длины требуется не только кратное размеру блока, но и для заполнения CBC, например PKCS # 5/PKCS # 7. –