Я боролся с этим уже пару дней. Мне нужно использовать API, который принимает зашифрованный параметр. API был написан на C #. Запрошенное шифрование следующее:
Алгоритм: AES
Режим шифрования: CBC
Режим заполнения: PKCS7
Размер блока: 128
Размер ключа: 256
Key: String -> Ключ генерируется путем преобразования предоставленной строки в байтовый массив размером 32: Encoding.ASCII.GetBytes (…). API утверждает, что строка генерируется ими с помощью функции хеширования строки MD5.
IV: массив IV генерируется путем преобразования предоставленной строки в массив байтов размером 16: Encoding.ASCII.GetBytes (…).
Представление зашифрованной строки: Base64
После поиска и проб столько всего, что было предложено в Интернете, я все еще не могу получить одно и то же зашифрованное значение (особенно, что PKCS7 не поддерживается по умолчанию и PKCS5 должен работать так же, но это не так). Вот несколько вещей, которые я пробовал:
1) Использование надувного замка для использования PKCS7
2) Добавление соответствия JCE, чтобы иметь возможность снять ограничение на размер ключа и блока.
После связи с ними они прислали мне работающий фрагмент Android (который, если я запускаю на простой java 8, жалуется на провайдера (NoSuchAlgorithmException: Не удается найти провайдера, поддерживающего AES / CBC / PKCS7Padding)):
public static String encrypt(String value) {
String plainText = value;
String escapedString;
try {
byte[] key = ENCRYPT_KEY.getBytes("UTF-8");
byte[] ivs = ENCRYPT_IV.getBytes("UTF-8");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivs);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, paramSpec);
escapedString = Base64.encodeToString(cipher.doFinal(plainText.getBytes("UTF-8")), Base64.DEFAULT).trim();
return escapedString;
} catch (Exception e) {
e.printStackTrace();
return value;
}
}
Пожалуйста, любая помощь будет очень признательна.
Вот фрагмент кода из того, что я пробовал:
package com.melhem.TestJava;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class StringFunc {
final static String key = "API_KEY_32_CHARs";
final static String iv = "API_IV_16_CHARs";
final static String algorithm = "AES/CBC/PKCS7Padding";
private static Cipher cipher = null;
private static SecretKeySpec skeySpec = null;
private static IvParameterSpec ivSpec = null;
public static void main(String[] args) {
System.out.println(encrypt("STRING_TO_ENCODE"));
}
private static void setUp(){
try{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
skeySpec = new SecretKeySpec(key.getBytes("ASCII"), "AES");
ivSpec = new IvParameterSpec(iv.getBytes("ASCII"));
cipher = Cipher.getInstance(algorithm);
}catch(NoSuchAlgorithmException | NoSuchPaddingException ex){
ex.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String encrypt(String str){
try{
// Integer strL = (int) Math.ceil(str.length() / 8.0);
// Integer strB = strL*8;
// str = padRight(str, ' ', strB);
setUp();
try {
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec);
System.out.println("Block size: " + cipher.getBlockSize() * 8);
System.out.println("Algorithm name: " + cipher.getAlgorithm());
System.out.println("Key size: " + skeySpec.getEncoded().length * 8);
} catch (InvalidAlgorithmParameterException ex) {
ex.printStackTrace();
return "";
}
byte[] enc = cipher.doFinal(str.getBytes("ASCII"));
String s = new String(Base64.getEncoder().encode(enc));
s = s.replace("+", "__plus__");
s = s.replace("/", "__slash__");
return s;
}catch(InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex){
ex.printStackTrace();
return "";
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";
}
}
public static String padRight(String msg, char x, int l) {
String result = "";
if (!msg.isEmpty()) {
for (int i=0; i<(l-msg.length()); i++) {
result = result + x;
}
result = msg + result;
}
return result;
}
}