RSA Encryption Исключительный размер блока - PullRequest
0 голосов
/ 24 ноября 2018

Я пытаюсь создать чат с сквозным шифрованием, но я получаю javax.crypto. IllegalBlockSizeException в этой строке byte[] decryptedMessage = cipher.doFinal(decodedMessage);

Я получаю открытый ключ другого человека с этим:

CollectionReference userCollection = FirebaseFirestore.getInstance().collection("users");

userCollection.whereEqualTo("userID", targetFriendID).get().addOnCompleteListener(new OnCompleteListener < QuerySnapshot > () {@Override
    public void onComplete(@NonNull Task < QuerySnapshot > task) {

        if (task.isSuccessful()) {

            for (QueryDocumentSnapshot doc: task.getResult()) {

                User tempUser = doc.toObject(User.class);

                targetFriendSDK = tempUser.getSDK();

                String keyString = tempUser.getPublicKey();

                byte[] keyBytes = Base64.decode(keyString, Base64.NO_WRAP);

                try {

                    friendPublicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyBytes));

                    dialog.cancel();

                } catch(Exception e) {
                    dialog.cancel();
                    Toast.makeText(ChatRoom.this, "Error, try again", Toast.LENGTH_SHORT).show();
                }

            }

        } else {
            dialog.cancel();
            Toast.makeText(ChatRoom.this, "Error", Toast.LENGTH_SHORT).show();
        }

    }
});

Расшифровка выполняется следующим образом:

String encodedMessage = cloudMessage.getMessage();
Date date = cloudMessage.getDate();
tring senderID = cloudMessage.getSenderID();
String receivID = cloudMessage.getReceiverID();

int sdk = Build.VERSION.SDK_INT;

byte[] decodedMessage = Base64.decode(encodedMessage, Base64.NO_WRAP);

String finalMessage;

try {

    if (sdk >= Build.VERSION_CODES.M) {

        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");

        OAEPParameterSpec sp = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSource.PSpecified.DEFAULT);

        cipher.init(Cipher.DECRYPT_MODE, privateKey, sp);

        byte[] decryptedMessage = cipher.doFinal(decodedMessage);

        finalMessage = new String(decryptedMessage);

    } else {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] decryptedMessage = cipher.doFinal(decodedMessage);

        finalMessage = new String(decryptedMessage);

    }

И шифрование:

byte[] messageBytes = messageText.getBytes();

String encodedMessage;

try {

    if (targetFriendSDK >= Build.VERSION_CODES.M) {

        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");

        OAEPParameterSpec sp = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSource.PSpecified.DEFAULT);

        cipher.init(Cipher.ENCRYPT_MODE, friendPublicKey, sp);

        byte[] cipherText = cipher.doFinal(messageBytes);

        encodedMessage = Base64.encodeToString(cipherText, Base64.NO_WRAP);

    } else {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, friendPublicKey);

        byte[] cipherText = cipher.doFinal(messageBytes);

        encodedMessage = Base64.encodeToString(cipherText, Base64.NO_WRAP);

    } 

Я делаю в основном то же самое, но с одним пользователем в другой деятельности, и всеработает, единственное различие между этими действиями состоит в том, что в этом я пытаюсь получить открытый ключ других пользователей.

1 Ответ

0 голосов
/ 24 ноября 2018

Хорошо, я нашел решение, похоже, оно было совсем не там, где я ожидал.

На самом деле проблема была в этой строке if (targetFriendSDK >= Build.VERSION_CODES.M), где я проверял версию Android для других пользователей, чтобы различать типы шифрования, которые я должен использовать.Я понял, что он всегда возвращал 0 из-за проблемы с именованием Firestore.

Я создал User документ, разбирающий пользовательский класс User для создания документа, и одно из полей, поле sdk, было названо private int SDK; с заглавнойбуквы, но в реальном Firestore он был сохранен как sdk с маленькими буквами, и когда я получал пользователя из Firestore, я использовал .toObject(User.class);, и это, вероятно, где он искал sdk, как в базе данных, нонайдено только SDK, поэтому поле не соответствует, и оно оставлено как 0.

Вывод: не используйте заглавные буквы при именовании полей в Firestore, потому что оно изменит их на маленькиев базе данных, и это вызовет проблемы при попытке вернуть документ как класс объекта из Firestore.

...