简体   繁体   English

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

[英]decrypt aes encrypted bytes with mode ctr in java

Let me explain shortly. 让我解释一下。 I have this encryptor in python: 我在python中有这个加密器:

It uses PyCrypto library. 它使用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),
)

and I want to have a decryptor for it in java. 我希望在java中有一个解密器。

I wrote this code but it raises java.security.InvalidAlgorithmParameterException: Wrong IV length: must be 16 bytes long . 我编写了这段代码,但它引发了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);

PS I should mention that I'm not an experienced Java developer. PS我应该提到我不是一个经验丰富的Java开发人员。


Update. 更新。 The problem was with initialization vector. 问题出在初始化矢量上。 Special thanks to @Andy for his time. 特别感谢@Andy的时间。

Solution: 解:

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

If you are trying to use AES-256 (you are using 32 bytes key), then you need to have Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files installed. 如果您尝试使用AES-256(使用32字节密钥),则需要安装Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files And this has to be installed wherever this application needs to run. 这必须安装在这个应用程序需要运行的任何地方。 If you plan to distribute this application and thus you don't have control over possible java runtimes, then you have to use other libraries (like Bouncy Castle ) through their own API, not through JCE API. 如果您计划分发此应用程序,因此您无法控制可能的Java运行时,那么您必须通过自己的API而不是通过JCE API使用其他库(如Bouncy Castle )。 (ie using Bouncy Castle as a provider like "BC" in JCE would result in the same problem.) (即在JCE中使用Bouncy Castle作为像“BC”这样的提供者会导致同样的问题。)

EDIT: First you said you are getting invalid key size exception, now changed the question. 编辑:首先你说你得到无效的密钥大小异常,现在改变了问题。 For the java.security.InvalidAlgorithmParameterException case, the problem is AES-256 has block size of 16, not 32. 256 represents the key size, not block size. 对于java.security.InvalidAlgorithmParameterException情况,问题是AES-256的块大小为16,而不是32. 256表示密钥大小,而不是块大小。 AES (128, 192, 256) always has block size of 128. Thus, the iv must be 16 bytes. AES(128,192,256)的块大小始终为128.因此, iv必须是16个字节。

EDIT 2: Not the cause of this exception but another possible problem with your code is, where do you get the iv in Java? 编辑2:不是这个例外的原因,但你的代码的另一个可能的问题是,你在哪里获得Java的iv Do you generate it random as you do in Python? 你是否像Python一样随意生成它? That would be a big mistake since you have to use the same IV during decryption to make it work. 这将是一个很大的错误,因为您必须在解密期间使用相同的IV才能使其正常工作。 Keep this in mind. 记住这一点。

I believe you are encountering an issue where Java expects the IV to be fully-formed ( 16 bytes ) when using AES/CTR/NoPadding while Python accepts an 8 byte prefix and generates its own counter in the other 64 bits ( 8 bytes ). 我相信你遇到的问题是,当使用AES/CTR/NoPadding时,Java期望IV完全形成( 16 bytes ),而Python接受8 byte 前缀并在其他64 bits8 bytes )中生成自己的计数器。

I have example code for cross-platform compatibility in this answer . 我在这个答案中有跨平台兼容性的示例代码。 The relevant section is: 相关部分是:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM