Мне дали задание сгенерировать тикет на Java (OpenJDK 11) для входа на внешний сайт.В настоящее время этот тикет генерируется кодом .net (2.0), из которого у меня нет исходного кода, поэтому нам пришлось декомпилировать библиотеки DLL и работать оттуда.
Я получил модуль и открытый показатель (оба в кодировке base64) от провайдера.
MODULUS = "yBl8llKaMhEeMxI/fyUN07l5GwhQDlhAnNzoui....=";
EXPONENT = "AQAB";
Билет для генерации состоит из 3 частей: (1) данные: шифрование AES "username "(2) ключ: зашифрованный RSA ключ AES (3) IV: зашифрованный RSA IV
Целевой веб-сайт расшифровывает ключ и IV и использует их для расшифровки« данных ».Из декомпилированных DLL я вижу, что RSACryptoServiceProvider используется для RSA, а RijndaelManaged для AES.
Я генерирую открытый ключ:
BigInteger modulus = new BigInteger(1, Base64.decodeBase64(MODULUS.getBytes(UTF_8)));
BigInteger exponent = new BigInteger(1, Base64.decodeBase64(EXPONENT.getBytes(UTF_8)));
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
publicKey = fact.generatePublic(rsaPubKey);
Используемый размер ключа AES составляет 128 бит:
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
MyKey = keyGenerator.generateKey();
Метод шифрования AES:
AESCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(MyKey.getEncoded(), "AES"), new IvParameterSpec(AESCipher.getIV())
И метод шифрования RSA:
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
cipherData = cipher.doFinal(data);
Проблема в том, что я не могу понять, почему не удается войти в систему, мы просто получаем сообщение "сбой входа в систему", но не видим никаких деталей.
По декомпилированному коду я знаю, что OAEP не используется на стороне .net:
this.rsa = new RSACryptoServiceProvider();
Convert.ToBase64String(this.rsa.Encrypt(Encoding.UTF8.GetBytes(strData), false));
Я пробовал ключи разных размеров, режимы заполнения, ... но я 'у меня все из идей сейчас.Я что-то упускаю из виду?Я понимаю, что мы работаем с завязанными глазами, без дополнительной информации.
Код "Полный пример" ниже:
String AES_TRANSFORMATION = "AES/CBC/PKCS5Padding";
String RSA_TRANSFORMATION = "RSA/ECB/PKCS1Padding";
String ALGORITHM = "AES";
String MODULUS = "yBl8llKaMhEeMxI/fyUN07l5GwhQDlhAnNzoui...=";
String EXPONENT = "AQAB";
String USER_NAME = "myusernamehere";
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
keyGenerator.init(keysize);
String AES_KEY = keyGenerator.generateKey();
Cipher AESCipher = Cipher.getInstance(AES_TRANSFORMATION);
private void test() {
BigInteger modulus = new BigInteger(1, Base64.decodeBase64(MODULUS.getBytes(UTF_8)));
BigInteger exponent = new BigInteger(1, Base64.decodeBase64(EXPONENT.getBytes(UTF_8)));
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, exponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
publicKey = fact.generatePublic(rsaPubKey);
String data = aes_encrypt((USER_NAME).getBytes());
String key = rsa_encrypt(AES_KEY.getEncoded(), publicKey);
String iv = rsa_encrypt(AESCipher.getIV(), publicKey);
}
private String aes_encrypt(byte[] data) {
byte[] encryptedData = new byte[0];
AESCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(AES_KEY.getEncoded(), "AES"));
encryptedData = AESCipher.doFinal(data);
return Base64.encodeBase64String(encryptedData);
}
private String rsa_encrypt(byte[] data, PublicKey publicKey) {
byte[] cipherData = new byte[0];
Cipher cipher = Cipher.getInstance(RSA_TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
cipherData = cipher.doFinal(data);
return Base64.encodeBase64String(cipherData);
}