用java中的ctr模式解密aes加密的字节



让我简单解释一下。我在python中有这个加密器:

它使用PyCrypto库。

from Crypto import Random
from Crypto.Cipher import AES
from Crypto.Util import Counter
iv = Random.new().read(8)
encryptor = AES.new(
CRYPTOGRAPHY_KEY,    // 32 bytes
AES.MODE_CTR,
counter=Counter.new(64, prefix=iv),
)

我想用java为它提供一个解密器。

我写了这个代码,但它引发了java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long

SecretKeySpec key = new SecretKeySpec(KEY, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);

附言:我应该提一下,我不是一个经验丰富的Java开发人员。


更新。问题出在初始化向量上。特别感谢@Andy抽出时间。

解决方案:

byte[] nonceAndCounter = new byte[16];
System.arraycopy(iv, 0, nonceAndCounter, 0, 8);
nonceAndCounter[15] = (byte) 1; // PyCrypto's default initial value is 1
IvParameterSpec ivSpec = new IvParameterSpec(nonceAndCounter);

如果您正在尝试使用AES-256(您使用的是32字节密钥),那么您需要安装Java加密扩展(JCE)无限强度管辖权策略文件。这必须安装在需要运行该应用程序的任何地方。如果您计划分发这个应用程序,因此您无法控制可能的java运行时,那么您必须通过其他库(如Bouncy Castle)自己的API使用它们,而不是通过JCE API。(例如,使用Bouncy Castle作为JCE中的"BC"之类的提供商会导致同样的问题。)

编辑:首先您说您得到了无效密钥大小异常,现在更改了问题。对于java.security.InvalidAlgorithmParameterException的情况,问题是AES-256的块大小是16,而不是32。256表示密钥大小,而不是块大小。AES(128192256)总是具有128的块大小。因此,iv必须是16个字节。

EDIT 2:不是这个异常的原因,但代码中另一个可能的问题是,Java中的iv在哪里?你会像在Python中那样随机生成它吗?这将是一个很大的错误,因为你必须在解密过程中使用相同的IV才能使其工作。记住这一点。

我相信您遇到了一个问题,Java在使用AES/CTR/NoPadding时希望IV是完全形式的(16 bytes),而Python接受8 byte前缀并在另一个64 bits(8 bytes)中生成自己的计数器。

在这个答案中,我有跨平台兼容性的示例代码。相关章节为:

byte[] cipher_key = org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEFFEDCBA9876543210");
final int HALF_BLOCK = 64;
byte[] salt = org.bouncycastle.util.encoders.Hex.decode("0123456789ABCDEF");
byte[] nonceAndCounter = new byte[16];
System.arraycopy(salt, 0, nonceAndCounter, 0, ((int) (HALF_BLOCK / 8)));
IvParameterSpec iv = new IvParameterSpec(nonceAndCounter);
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
SecretKeySpec key = new SecretKeySpec(cipher_key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);

最新更新