2

我正在弄清楚如何使用 进行跨平台(Android 和 Python)加密和解密,如果我使用基于 IVAES的话,我似乎可以成功传输数据。String但是,如果我立即切换到使用 生成的字节SecureRandom.generateSeed(),它就会出错。密钥是预先共享的。

工作 Android 代码(删除 try/catch 块以保持简短):

String SecretKey = "0123456789abcdef";
String iv = "fedcba9876543210";

IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
SecretKeySpec keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

//Initialize the cipher
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); 

String message = "What's up?";
byte[] encrypted = cipher.doFinal(message.getBytes());

//Send the data
outputStream.write(encrypted);

有一个小的传输标头可以让客户端知道传入消息的大小,但我认为它不相关,因此我将其省略了。接收此消息的 Python 代码如下所示:

#Predefined:
unpad = lambda s : s[0:-ord(s[-1])]

  encrypted = cs.recv(messagesize) # Receive the encrypted message
  iv = encrypted[:16]

  key = AES.new('0123456789abcdef', AES.MODE_CBC,IV=iv)
  padded_msg  = key.decrypt(encrypted[16:])
  decrypted = unpad(padded_msg) #Remove padding

  print "read [%s]" % decrypted

结果如下:

read [What's up]

如果我在 Java 代码中更改两行:

SecureRandom rnd = new SecureRandom();
IvParameterSpec ivspec = new IvParameterSpec(rnd.generateSeed(16));

Python 输出变为:

read [?=H��m��lڈ�1ls]

我想知道 SecureRandom 有什么变化?我读到默认情况下 String.getBytes() 返回平台默认编码(for Android 4.0),所以我想知道是否必须在 Python 端对使用 SecureRandom 生成的 IV 进行一些操作..?

4

1 回答 1

3

接受者需要被告知 IV 是什么。查看此 Wikipedia 条目中有关 CBC 的部分:您可以看到加密的 n 块消息由 n+1 个块组成,附加块是 IV。没有用于传输它的标准协议,但是我看到的每个代码都是通过在消息前面加上 IV 来做到这一点的,这确实是很自然的事情,并且由于 CBC 的纠错特性即使在代码得到它略有错误。例如,您可以在野外找到使用常量 IV 但在纯文本前面加上随机块的代码,这基本上以不同的方式做同样的事情。有时您甚至会在书中找到这种代码,例如 David Hook 的其他非常好的的第 2 章中的 InlineIvCBCExample.java 。

我建议采用以下方式进行 AES/CBC/PKCS7Padding:

byte[] plaintext = ...;
byte[] key = ...;

// get iv
SecureRandom rnd = new SecureRandom();
byte[] iv = rnd.getBytes(16);
IvParameterSpec ivSpec = new IvParameterSpec(iv);   

// encrypt
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] ciphertext = cipher.doFinal(plaintext);

// copy to result
byte[] result = new byte[iv.length + ciphertext.length];
System.arraycopy(iv, 0, result, 0, iv.length);
System.arraycopy(ciphertext, 0 , result, iv.length, ciphertext.length);
于 2013-11-26T08:41:27.977 回答