2015-03-25 103 views
3

我有一個測試工具,它在將數據發送到服務器之前使用Twofish作爲加密算法來加密數據。代碼使用C++編寫,並使用Bruce Schneier優化的C實現(https://www.schneier.com/code/twofish-optimized-c.zip)。我需要將此工具移植到Python,並使用兩個模塊(https://pypi.python.org/pypi/twofish/0.3.0)。我可以加密和解密16個字符長度的字符串,但對於其他字符串長度,它會給出錯誤'ValueError:invalid block length'。Python中的雙重加密

我該如何加密&使用Python的Twofish模塊來解密大數據?

>>> 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 

更新: 我想了這個問題的另一個解決方案。 我已經創建了一個Windows DLL,來自Bruce Schneier優化的C實現(https://www.schneier.com/code/twofish-optimized-c.zip)的twofish.dll。 此外,我已經導出包裝函數編碼&使用__declspec(dllexport)解碼成員函數。

我使用ctype.CDLL函數在Python中加載此DLL。 的原型編碼功能是:

__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

我終於解決了這個問題,將Bruce Schneier的Twofish優化C實現(https://www.schneier.com/code/twofish-optimized-c.zip)編譯成DLL並使用ctypes模塊加載該DLL。

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個八位位組。答曰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,需要像PKCS#5/PKCS#7那樣的適當填充來加密任意長度的數據,而不僅僅是數據塊大小的多倍。 – 2015-03-25 07:18:48