Как декодировать зашифрованный объект AES-256 / CBC / ZeroBytePadding

Я довольно новичок в Java Cryptography. Я предоставил следующий код PHP для расшифровки зашифрованного объекта AES-256 / CBC / ZeroBytePadding.

function decrypt($key, $data)
{
if (!in_array(strlen($key), array(32, 48, 64)))
{
throw new Exception("Invalid key");
}

$key_hex = pack('H*', $key);

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);

$ciphertext = base64_decode($data);

# retrieves the IV, iv_size should be created using mcrypt_get_iv_size()
$iv_dec = substr($ciphertext, 0, $iv_size);

# retrieves the cipher text (everything except the $iv_size in the front)
$ciphertext_dec = substr($ciphertext, $iv_size);

# may remove 00h valued characters from end of plain text
$result = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key_hex, $ciphertext_dec, MCRYPT_MODE_CBC, $iv_dec);

return $result;
}

Мне нужно сделать то же самое в Java. После долгих поисков я сделал следующий код:

 public String decrypt(byte key[], String encrypted)
throws GeneralSecurityException {
if (key.length != 32 || key.length != 48 || key.length != 64) {
throw new IllegalArgumentException("Invalid key size.");
}
byte[] ciphertextBytes = Base64.decodeBase64(encrypted.getBytes());

// Need to find the IV length here. I am using 16 here

IvParameterSpec iv = new IvParameterSpec(ciphertextBytes, 0, 16);
ciphertextBytes = Arrays.copyOfRange(ciphertextBytes, 16,
ciphertextBytes.length);

SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(ciphertextBytes);

// remove zero bytes at the end
int lastLength = original.length;
for (int i = original.length - 1; i > original.length - 16; i--) {
if (original[i] == (byte) 0) {
lastLength--;
} else {
break;
}
}

return new String(original, 0, lastLength);
}

Но мне нужно найти длину IV здесь. В PHP они делают это используя:
$ iv_size = mcrypt_get_iv_size (MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
Как реализовать это в Java? Кто-нибудь может мне помочь, пожалуйста?

Я называю метод следующим образом:

public static void main(String args[]) {
String key =     "F5D4471791B79B6360C1EFF4A76250C1D7E5C23F5E4C3C43893B6CCAA796E307";
String encrypted =     "F4N8SvpF1zgyMnQKwLlX\\/Dfgsj4kU58pg3kaSrt+AJt9D7\\/3vAfngegtytAdCUwwkQ2nxj8PVABRy0aaeBfsJN9n2Ltco6oPjdcmx8eOI";

try {
String decrypted = decrypt(Hex.decodeHex(key.toCharArray()), encrypted);
System.out.println(decrypted);
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

0

Решение

IV для AES (Rijndael-128) в режиме CBC всегда имеет тот же размер, что и блок, который составляет 16 байтов или 128 бит. Если вы продолжаете использовать режим CBC, то вы можете жестко закодировать это значение или использовать Cipher#getBlockSize(),

Если вы хотите использовать AES-256, вам необходимо установить файлы политики Unlimited Strength для вашего JRE / JDK (Ссылка для Java 8). AES-128 можно использовать без изменений, но экспортные ограничения США требуют, чтобы вы включили ключи более высокого размера самостоятельно.

2

Другие решения

Ответ: С помощью Artjom B. я создал код, который расшифровывает зашифрованную строку AES-256 / CBC / ZeroBytePadding. Я публикую это для тех, кому нужна помощь.

1. Во-первых, вы должны загрузить Политику юрисдикции неограниченного расширения Java Cryptography Extension (JCE) для своей версии JDK.

2. Распакуйте zip-файл & положить local_policy.jar & US_export_policy.jar в пути / Путь JDK / jre / lib / security. Это необходимо, так как мой ключ составляет 64 байта. AES требует 16/24/32 байта ключа.

3. Скопируйте и вставьте мой код & измените его согласно вашему требованию: P.

import java.security.GeneralSecurityException;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.binary.Base64;

public class Decryption {

public static void main(String args[]) {
//I have changed the original key. So mere copy pasting may not work. Put your key here.
String key = "FfDaaaaaaa444aaaa7aaEFF4A76efaaaaaE5C23F5E4C3adeaaaaaaCAA796E307";
String encrypted = "8AQ8SvpF1zgyNyxKwLlX\\/cGzwLE5skU58pg3kaSrt+AJt9D7\\/3vaNRPZISIKMdCUwwkQ2nxj8PVABRy0aaeBfsJN9n2Ltco6oPjdcmx8eOI";
String decrypted = "";
try {

try {
decrypted = decrypt(Hex.decodeHex(key.toCharArray()), encrypted);
} catch (DecoderException e) {
e.printStackTrace();
}

System.out.println(decrypted);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}

}

public static String decrypt(byte key[], String encrypted)
throws GeneralSecurityException {
/*
* if (key.length != 32 || key.length != 48 || key.length != 64) { throw
* new IllegalArgumentException("Invalid key size."); }
*/
byte[] ciphertextBytes = Base64.decodeBase64(encrypted.getBytes());

IvParameterSpec iv = new IvParameterSpec(ciphertextBytes, 0, 16);

ciphertextBytes = Arrays.copyOfRange(ciphertextBytes, 16,
ciphertextBytes.length);

SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(ciphertextBytes);

// Remove zero bytes at the end.
int lastLength = original.length;
for (int i = original.length - 1; i > original.length - 16; i--) {
if (original[i] == (byte) 0) {
lastLength--;
} else {
break;
}
}

return new String(original, 0, lastLength);

}

}

Спасибо @Artjom B. за вашу помощь & экспертиза :).

0

По вопросам рекламы [email protected]