Python 中的 Twofish 加密

ani*_*mwr 5 python encryption ctypes cryptography twofish

我有一个测试工具,它使用 Twofish 作为加密算法,在将数据发送到服务器之前对其进行加密。该代码是用 C++ 编写的,并使用 Bruce Schneier 的优化 C 实现 ( https://www.schneier.com/code/twofish-optimized-c.zip )。我需要将此工具移植到Python,并且我正在使用twofish模块(https://pypi.python.org/pypi/twofish/0.3.0)。我可以加密和解密 16 个字符长度的字符串,但对于其他字符串长度,它会给出错误“ValueError:无效的块长度”。

如何使用 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
Run Code Online (Sandbox Code Playgroud)

更新: 我正在尝试解决此问题的另一种解决方案。我从 Bruce Schneier 的优化 C 实现 ( https://www.schneier.com/code/twofish-optimized-c.zip )创建了一个 Windows DLL,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)
Run Code Online (Sandbox Code Playgroud)

我应该如何定义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))
Run Code Online (Sandbox Code Playgroud)

执行上述代码时会抛出以下错误:

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
Run Code Online (Sandbox Code Playgroud)

ani*_*mwr 3

我最终通过将 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))
Run Code Online (Sandbox Code Playgroud)