2005-03-12

用 twofish 做块加密

Twofish是一种块加密算法。块加密算法适合进行流加密,倒是一个发展趋势。Twofish的运算速度比以前的Blowfish之类要快一点,今天终于有机会在Python里试验了一下。虽然这种算法已经出现了好几年,并且是被置于公共领域的算法,但我还是发现现在可以利用的Twofish算法库种类好象不多,也良莠不齐。算起来,还是从GnuPG项目中衍生的libgcrypt加密算法库比较完善,而且维护也比较及时,项目活跃程度比较高,用起来放心一点。

在Debian中,安装libgcrypt比较方便:
sudo apt-get install libgcrypt11 libgcrypt11-dev

不过libgcrypt是一个标准C代码库,为了在Python中使用,需要包装一下,把它做成Python扩展模块。在sf.net上,我找到了libgcrypt-py。在Debian下,编译安装很顺利;但在FreeBSD下,好象gcc不会自己到/usr/local中查找对应的libgcrypt的库和头文件,导致编译失败。在对setup.py做了修改之后,终于安装成功了。
--- libgcrypt-py-0.1.0/setup.py 2004-07-22 11:47:15.000000000 +0800
+++ libgcrypt-py-0.1.0-new/setup.py 2005-03-12 21:37:24.122370040 +0800
@@ -11,16 +11,25 @@
url="http://libgcrypt-py.sourceforge.net",
download_url="http://sourceforge.net/projects/libgcrypt-py/",
py_modules=['Gcrypt'],
+ packages=['_Gcrypt'],
ext_package="_Gcrypt",
ext_modules=[
Extension("_Cipher", ["_Gcrypt/ciphermodule.c"],
- libraries=["gcrypt", "gpg-error"]),
+ libraries=["gcrypt", "gpg-error"],
+ library_dirs=["/lib", "/usr/lib", "/usr/local/lib"],
+ include_dirs=["/usr/include", "/usr/local/include"]),
Extension("_Hash", ["_Gcrypt/hashmodule.c"],
- libraries=["gcrypt", "gpg-error"]),
+ libraries=["gcrypt", "gpg-error"],
+ library_dirs=["/lib", "/usr/lib", "/usr/local/lib"],
+ include_dirs=["/usr/include", "/usr/local/include"]),
Extension("_Random", ["_Gcrypt/randommodule.c"],
- libraries=["gcrypt", "gpg-error"]),
+ libraries=["gcrypt", "gpg-error"],
+ library_dirs=["/lib", "/usr/lib", "/usr/local/lib"],
+ include_dirs=["/usr/include", "/usr/local/include"]),
Extension("_Pk", ["_Gcrypt/pkmodule.c"],
- libraries=["gcrypt", "gpg-error"]),
+ libraries=["gcrypt", "gpg-error"],
+ library_dirs=["/lib", "/usr/lib", "/usr/local/lib"],
+ include_dirs=["/usr/include", "/usr/local/include"]),
]
)

下面就打开一个Python,来测试一下:
import Gcrypt
from binascii import hexlify, unhexlify

key16 = '1234567890123456'
mode = 'ECB'
plaintext = '1234567812345678'

t=Gcrypt.Cipher('TWOFISH-128', mode, key16)
ciphertext = t.Encrypt(plaintext)
shouldbe = '8dfc2c5cbc722c3eda60b6f6d5d64adaa08113c4a107dc0967880359b686c1d7'
hexlify(ciphertext) == shouldbe
hexlify(ciphertext) == shouldbe
t.Decrypt(unhexlify(shouldbe)) == plaintext
t.Decrypt(unhexlify(shouldbe)) == plaintext
a=shouldbe.upper()
' '.join([a[i:i+2] for i in range(0, len(a), 2)])

key32 = key16 + '\0'*(32-len(key16))
t=Gcrypt.Cipher('TWOFISH-256', mode, key32)
ciphertext = t.Encrypt(plaintext)
shouldbe = '2d74e616829cc6d036081177fd2bd231d8858c5d39bcb2336c2071b331beee9b'
hexlify(ciphertext) == shouldbe
hexlify(ciphertext) == shouldbe
t.Decrypt(unhexlify(shouldbe)) == plaintext
t.Decrypt(unhexlify(shouldbe)) == plaintext
a=shouldbe.upper()
' '.join([a[i:i+2] for i in range(0, len(a), 2)])

好了,结论是,基本可用。不过和我用C编写的libgcrypt测试程序比起来,Python版本的256位key的加密结果后16字节竟然不太一样!怎么回事?!难道这两只鱼非得要把每16字节一块单独进行运算吗?没办法,理论功底不够,暂且放下,等回头再试试吧。

补:有人提到import Gcrypt会出错,系统提示“No module named _Gcrypt._Random”。出现这种情况一是在libgcrypt-py-0.1.0中执行的import命令,python在现有的目录结构中找不到_Random.so所致;另一个原因是,原代码中的setup.py缺少上面patch中的“packages=['_Gcrypt'],”这一行,这导致_Gcrypt/__init__.py没有被安装到系统中,这也同样会使import出错。

没有评论: