Другое шифрование Android против чистого Java - RSA / ECB / OAEPWithMD5AndMGF1Padding - PullRequest
1 голос
/ 30 мая 2020

Я шифрую строку в Android ключом publi c. Однако я получаю исключение «Ошибка дешифрования», когда пытаюсь расшифровать зашифрованную строку закрытым ключом в чистом коде Java. Может ли кто-нибудь помочь найти проблему?

Android код для шифрования

import android.util.Base64;
public static String encryptMessage(final String plainText, final PublicKey publicKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithAndMGF1Padding");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    return Base64.encodeToString(cipher.doFinal(plainText.getBytes()), Base64.NO_WRAP);
}

Чистый Java код для расшифровки

import java.util.Base64;
public static String decryptMessage(final String encryptedText, final PrivateKey privateKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithAndMGF1Padding");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);

    Base64.Decoder decoder = Base64.getDecoder();
    byte[] byteArray = decoder.decode(encryptedText);
    byte[] decryptedArray = cipher.doFinal(byteArray);  // throw exception here
    String plainText = new String(decryptedArray);
    return plainText;
}

Вы можете заметить, что у меня использовать разные API Base64 в Android и чистом Java. Я попробовал "RSA / ECB / PKCS1Padding", и он может правильно расшифровать без исключения. Пробовал "RSA / ECB / OAEPWithSHA-256AndMGF1Padding" тоже, но получил то же исключение.

1 Ответ

3 голосов
/ 31 мая 2020

OAEP использует два дайджеста, один для метки OAEP, а второй как основу для MGF1, см. RF C 8017, 7.1. РСАЭС-ОАЭП , B.1. Ha sh Функции и B.2. Функции создания маски .

Проблема вызвана тем, что поставщики, используемые с обеих сторон кода OP (Android / API уровня 28 и Java 8), применяют разные дайджесты MGF1 для OAEPWithMD5AndMGF1Padding .

С обеих сторон соответствующие параметры (поставщик, дайджест OAEP, MGF, дайджест MGF1) могут быть определены после инициализации шифра, например, с помощью:

OAEPParameterSpec parameterSpec = cipher.getParameters().getParameterSpec(OAEPParameterSpec.class);
System.out.println("Provider: " + cipher.getProvider().getName());          
System.out.println("OAEP digest: " + parameterSpec.getDigestAlgorithm());  
System.out.println("OAEP MGF : " + parameterSpec.getMGFAlgorithm());        
System.out.println("OAEP MGF1 digest: " + ((MGF1ParameterSpec)parameterSpec.getMGFParameters()).getDigestAlgorithm()); 

При этом определяется MD5 как дайджест MGF1 на стороне Android и SHA-1 на стороне Java. С обеих сторон MD5 используется как дайджест OAEP. Проблема может быть решена, если дайджесты явно заданы как OAEPParameterSpec, так что одни и те же дайджесты используются с обеих сторон.

Например, следующий код на стороне Java гарантирует, что MD5 используется как дайджест OAEP и MGF1, аналогично стороне Android.

OAEPParameterSpec oaepParameterSpecDec = new OAEPParameterSpec("MD5", "MGF1", new MGF1ParameterSpec("MD5"), PSource.PSpecified.DEFAULT);
cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParameterSpecDec);

То же самое относится к OAEPWithSHA-256AndMGF1Padding.

Обратите внимание, что RF C 8017 в B.1. Ha sh Functions рекомендует SHA-1 и SHA-2 для RSAES-OAEP, но не MD5.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...