Java AES加密(工作)和Python解密(不工作)

时间:2014-01-06 04:14:49

标签: java python encryption aes

我正在尝试用Java加密消息并用Python解密它。不幸的是我刚开始使用python并且无法使解密工作。

这是我的Java代码:

KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = sr.generateSeed(16);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
SecretKey aesKey = keygen.generateKey();

//save byte array in text file to recreate key later
byte[] encodedKey = aesKey.getEncoded();
new File("myPath\\AESKey.txt");
FileOutputStream fos = new FileOutputStream("myPath\\AESKey.txt");
//save AesKey in first 16 bytes and Initial Vector in next 16 bytes
fos.write(encodedKey);
fos.write(iv);
fos.close();

String secretText = "Hello cryptography";      
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivSpec);
byte[] encrypted = cipher.doFinal(secretText.getBytes());
BASE64Encoder myEncoder  = new BASE64Encoder();
String encodedSecretText = myEncoder.encode(encrypted);

new File("myPath\\encodedSecretText.txt");
FileOutputStream fos2 = new FileOutputStream("myPath\\encodedSecretText.txt");
fos2.write(encodedSecretText.getBytes());  
fos2.close();

我能够用java解密消息,但不能用python解密。我希望有人可以告诉我如何做到这一点。我用另一个答案的填充复制了部分并假设这是问题。

我收到消息:ord()期望的字符串长度为1,但找到了int。

的Python:

from Crypto import Random
from Crypto.Cipher import AES
import base64

BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) 
unpad = lambda s : s[0:-ord(s[-1])]

#read bytes of aesKey
file = open("myPath/AESKey.txt","rb")
aesKey = file.read(16)
iv = file.read(16)
file.close()
sec = open("myPath/encodedSecretText.txt")
for line in sec:
encodedSecretText =  line.rstrip()
sec.close()

class AESCipher:
    def __init__( self, key ):
        self.key = key
    def encrypt( self, raw ):
        raw = pad(raw)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new( self.key, AES.MODE_CBC, iv )
        return base64.b64encode( iv + cipher.encrypt( raw ) ) 
    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] ))

aes = AESCipher(aesKey)   
print(aes.decrypt(encodedSecretText))

感谢任何提示。

1 个答案:

答案 0 :(得分:1)

你在整数上调用ord。这显然是非法的。 ord的重点是你给它一个Unicode字符,作为一个字符串,它会返回代码点的数值。

那么,为什么你有一个号码?好吧,我不确定你的预期,但让我们来看看你实际拥有的东西。如果s[-1]是整数,则s是某种整数序列。而s是调用cipher.decrypt()的结果。正如该函数的the documentation所述,它返回一个字节字符串。这不是一个特定的类型,只是一个类型的描述 - 您可以通过一些基本调试找出实际返回值是什么,可能是这样的:

    cipher = AES.new(self.key, AES.MODE_CBC, iv )
    plaintext = cipher.decrypt(enc[16:])
    print(type(plaintext), repr(plaintext))
    return unpad(plaintext)    

但我猜这是一个bytes对象,(引自http://docs.python.org/3/library/functions.html#bytes)...

  

是0 <= x <0的范围内的不可变整数序列。 256.

因此,s[-1][0, 256)范围内的整数。因此错误。

那么,你应该做什么呢?好吧,你为什么打电话给ord?你有一个字节。大概你想要的是一个字节。所以......不要在那里打电话。


与此同时,您的代码中至少还有一个严重错误:

for line in sec:
encodedSecretText =  line.rstrip()
sec.close()

粘贴后,这会引发IndentationError。如果你缩进第二行和第三行,你将从一个已关闭的文件中读取错误。所以大概你想缩进第二个。在这种情况下,你正在做的是遍历所有行,从每个行中删除尾随空格,然后对它们不做任何操作。在循环结束时,encodedSecretText保存编码文本的最后一行,并且所有其他行都被遗忘并且无法恢复。

如果你想将所有文本读入一个行列表,你会想要这样的东西:

encodedSecretText = []
for line in sec:
    encodedSecretText.append(line.rstrip())

或者,如果你想将它读成一个大字符串,删除换行符,你可以执行上述操作然后encodedSecretText = b''.join(encodedSecretText),或者只是跳过整个循环并执行encodedSecretText = sec.read().replace(b'\n', b'')。< / p>