Шифрование открытого ключа Android

В моем приложении для Android реализовано шифрование RSA, однако бэкэнд не может расшифровать токен, созданный приложением. Вот код, начальная и конечная строки открытого ключа были удалены перед выполнением вызовов, что может быть проблемой?

String encryptedToken = Base64.encodeToString(encrypt(publicKey, "4111111111111111"), Base64.NO_WRAP);

public static byte[] encrypt(String publicKey, String data) {
        if (TextUtils.isEmpty(publicKey) || TextUtils.isEmpty(data)) {
            return null;
        }
        try {
            // Decode the modified public key into a byte[]
            byte[] publicKeyByteArray = Base64.decode(publicKey.getBytes("UTF-8"),Base64.NO_WRAP);

            Cipher mCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyByteArray);
            Key key = keyFactory.generatePublic(x509KeySpec);
            mCipher.init(Cipher.ENCRYPT_MODE, key);
            return mCipher.doFinal(data.getBytes("UTF-8"));
        }
        catch (UnsupportedEncodingException e) {
            Log.e("RSAKEY", e.getMessage());
        }
        catch (NoSuchPaddingException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (NoSuchAlgorithmException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (InvalidKeyException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (InvalidKeySpecException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (IllegalBlockSizeException e) {
            Log.e("RSAKEY", e.getMessage());
        } catch (BadPaddingException e) {
            Log.e("RSAKEY", e.getMessage());
        }
        return null;
    }

Бэкэнд-команда предоставила приведенный ниже пример кода, который работает, но он предназначен для java рабочего стола. В библиотеке Android нет метода Base64.getEncoder. это очень похоже на то, что я написал, но мой просто не работает.

 // Decode the modified public key into a byte[]
            byte[] publicKeyByteArray = Base64.getDecoder().decode(publicKey.getBytes(StandardCharsets.UTF_8));

            // Create a PublicKey from the byte array
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByteArray);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey pubKey = keyFactory.generatePublic(keySpec);

            // Get an instance of the Cipher and perform the encryption
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            byte[] cipherText = cipher.doFinal(ccNum.getBytes(StandardCharsets.UTF_8));

            // Get the encrypted value as a Base64-encoded String
            String encodeToStr = Base64.getEncoder().encodeToString(cipherText);

            // Print out the encoded, encrypted string
            System.out.println("Encrypted and Encoded String: " + encodeToStr);

Я сравнивал значения массива байтов на каждом шаге. Шифр настольного компьютера и шифр android получили одинаковые входные данные. Однако результаты из кода шифрования Android.doFinal не могут быть расшифрованы бэкэнд. Если я помещаю результаты рабочего стола в тело вызова REST, они работают нормально, поэтому это не вызвано вызовом REST.

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

Ответ 1

Наконец, кто-то из команды взломал это. Причина в том, что ОС Android использует замок Bouncy, бэкэнд использует Sun в качестве провайдера, это заставило бэкэнд выбрасывать исключение BadPaddingException. Чтобы заставить его работать, шифр должен быть инициализирован таким образом на Android:

 mCipher.init(Cipher.ENCRYPT_MODE, key, new
                    OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1,
                    PSource.PSpecified.DEFAULT));

Проверить дополнительную информацию в этом сообщении: http://bouncy-castle.1462172.n4.nabble.com/Problems-with-OAEP-SHA-256-hash-crypto-td1466852.html