Reputation: 508
Let me explain shortly. I have this encryptor in python:
It uses PyCrypto library.
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.
I wrote this code but it raises 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);
P.S. I should mention that I'm not an experienced Java developer.
Update. The problem was with initialization vector. Special thanks to @Andy for his time.
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);
Upvotes: 4
Views: 2996
Reputation: 14184
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
).
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);
Upvotes: 1
Reputation: 1169
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. 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. (i.e. using Bouncy Castle as a provider like "BC" in JCE would result in the same problem.)
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. AES (128, 192, 256) always has block size of 128. Thus, the iv
must be 16 bytes.
EDIT 2: Not the cause of this exception but another possible problem with your code is, where do you get the iv
in Java? Do you generate it random as you do in Python? That would be a big mistake since you have to use the same IV during decryption to make it work. Keep this in mind.
Upvotes: 3