我正在尝试用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))
感谢任何提示。
答案 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>