用java中的mode ctr解密aes加密字节

时间:2017-02-14 18:45:29

标签: java cryptography aes

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

它使用PyCrypto库。

var collection =
Array.prototype.slice.call(
  document.querySelectorAll('mycssselector')
).forEach(function(el){
    el.addEventListener("myevent",/*callback*/function(){});
}); 

我希望在java中有一个解密器。

我编写了这段代码,但它引发了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.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long

P.S。我应该提一下,我不是一位经验丰富的Java开发人员。

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

解决方案:

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);

2 个答案:

答案 0 :(得分:3)

如果您尝试使用AES-256(使用32字节密钥),则需要安装Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。这必须安装在这个应用程序需要运行的任何地方。如果您计划分发此应用程序,因此您无法控制可能的Java运行时,那么您必须通过自己的API而不是通过JCE API使用其他库(如Bouncy Castle)。 (即使用Bouncy Castle作为提供者,例如" BC"在JCE中会导致同样的问题。)

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

编辑2:不是这个异常的原因,但代码的另一个可能问题是,你在哪里获得Java中的iv?你是否像Python一样随意生成它?这将是一个很大的错误,因为您必须在解密期间使用相同的IV才能使其正常工作。记住这一点。

答案 1 :(得分:1)

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

我在this answer中有跨平台兼容性的示例代码。相关部分是:

    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);