由javax.crypto编码的字符串python中的Blowfish解密

pll*_*pll 3 python java encryption pycrypto javax.crypto

使用https://raw.github.com/usefulfor/usefulfor/master/security/JBoss.java上的代码,我做了以下工作:

bash-3.2$ java -cp . JBoss -e testpython
-27038292d345798947e2852756afcf0a
bash-3.2$ java -cp . JBoss -d -27038292d345798947e2852756afcf0a
testpython
Run Code Online (Sandbox Code Playgroud)

但是,我不能为我的生活,弄清楚如何使用python中的pycrypto解密字符串'27038292d345798947e2852756afcf0a'.我的理解是Java代码使用的是Blowfish,而"jaas就是这种方式"作为密码的关键.但我无法理解如何在python中执行此操作.以下结果导致大多数不可打印的垃圾:

import Crypto
from Crypto.Cipher import Blowfish
from base64 import b64encode, b64decode

bs        = Blowfish.block_size
key       = 'jaas is the way'
plaintext = b'27038292d345798947e2852756afcf0a'
iv        = '\0' * 8

c1 = Blowfish.new(key, Blowfish.MODE_ECB)
c2 = Blowfish.new(key, Blowfish.MODE_CBC, iv)
c3 = Blowfish.new(key, Blowfish.MODE_CFB, iv)
c4 = Blowfish.new(key, Blowfish.MODE_OFB, iv)

msg1 = c1.decrypt(plaintext)
msg2 = c2.decrypt(plaintext)
msg3 = c3.decrypt(plaintext)
msg4 = c4.decrypt(plaintext)

print "msg1 = %s\n" % msg1
print "msg2 = %s\n" % msg2 
print "msg3 = %s\n" % msg3 
print "msg4 = %s\n" % msg4 
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

谢谢.

Squ*_*ree 5

首先,Java示例代码非常糟糕.它将密文输出为整数,而密文应保留为二进制字符串.原因是整数可以用无限多个二进制编码来表示.例如,第一个可以是'0x01'(1个字节),'0x0001'(2个字节),依此类推.处理加密函数时,必须对表示非常精确.

此外,该示例使用javax.cryptoAPI 的默认值,这在任何地方都没有描述.所以这真的是反复试验.

对于解决方案,您必须知道如何在Python中将负整数转换为十六进制字符串.在这种情况下,您不需要十六进制字符串,而是它的字节表示.但这个概念是一样的.我使用PyCrypto long_to_bytes将正整数(任意长度)转换为字节字符串.

from Crypto.Cipher import Blowfish
from Crypto.Util.number import long_to_bytes

def tobytestring(val, nbits):
    """Convert an integer (val, even negative) to its byte string representation.
    Parameter nbits is the length of the desired byte string (in bits).
    """
    return long_to_bytes((val + (1 << nbits)) % (1 << nbits), nbits/8)

key = b'jaas is the way'
c1  = Blowfish.new(key, Blowfish.MODE_ECB)

fromjava = b"-27038292d345798947e2852756afcf0a"
# We don't know the real length of the ciphertext, assume it is 16 bytes
ciphertext = tobytestring(int(fromjava, 16), 16*8)
print c1.decrypt(ciphertext)
Run Code Online (Sandbox Code Playgroud)

输出是:

'testpython\x06\x06\x06\x06\x06\x06'
Run Code Online (Sandbox Code Playgroud)

从中您可以看到,javax.crypto还添加了PKCS#5填充,您需要自行删除.尽管如此,这是微不足道的.

但是,问题的真正解决方案是以更好的方式进行Java加密.Python代码将大大简化.