Как исправить «java.security.InvalidKeyException: Неподдерживаемый алгоритм ключа: EC. Поддерживается только RSA» при использовании Keystore в API 18 - PullRequest
0 голосов
/ 23 мая 2019

Мне нужно хранить конфиденциальные данные в локальном хранилище с API 18, я решил использовать хранилище ключей.Я пробую несколько решений, но ни одно из них не сработало.

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

public String decryptString(String alias, String encryptedText) {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
String decryptedText = "";
        try {
            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
            RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();

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

            CipherInputStream cipherInputStream = new CipherInputStream(
                    new ByteArrayInputStream(Base64.decode(encryptedText, Base64.DEFAULT)), output);
            ArrayList<Byte> values = new ArrayList<>();
            int nextByte;
            while ((nextByte = cipherInputStream.read()) != -1) {
                values.add((byte)nextByte);
            }

            byte[] bytes = new byte[values.size()];
            for(int i = 0; i < bytes.length; i++) {
                bytes[i] = values.get(i).byteValue();
            }

            decryptedText = new String(bytes, 0, bytes.length, "UTF-8");

        } catch (Exception e) {
            Log.e(TAG, Log.getStackTraceString(e));
        }
        return decryptedText;
    }
public String encryptString(String alias, String initialText) {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        String encryptedText = "";
        try {
            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
            PublicKey publicKey = privateKeyEntry.getCertificate().getPublicKey();
            // Encrypt the text
            if(initialText.isEmpty()) {
                Log.e(TAG, "initialText is Empty");
                return "";
            }

            Cipher input = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            input.init(Cipher.ENCRYPT_MODE, publicKey);//Need RSA private or public key

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            CipherOutputStream cipherOutputStream = new CipherOutputStream(
                    outputStream, input);
            cipherOutputStream.write(initialText.getBytes("UTF-8"));
            cipherOutputStream.close();

            byte [] vals = outputStream.toByteArray();
            encryptedText = Base64.encodeToString(vals, Base64.DEFAULT);
        } catch (Exception e) {
            Log.e(TAG, Log.getStackTraceString(e));
        }
        return encryptedText;
    }

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

java.security.InvalidKeyException: Unsupported key algorithm: EC. Only RSA supported
at com.cryptor.Cryptor.encryptString(Cryptor.java:108)

1 Ответ

0 голосов
/ 24 мая 2019

Я не вижу, где / когда вы генерируете свой ключ RSA.Со своей стороны я сделал следующие шаги:

  1. Создание / получение Keystore
  2. Создание ключей RSA с помощью KeyPairGenerator (будьте осторожны: другие методы, начиная с Android M)

val generator = KeyPairGenerator.getInstance(ALGORITHM, CryptoConstants.ANDROID_KEY_STORE)

Здесь ALGORITHM = "RSA" , а не "RSA / ECB / PKCS1Padding" и CryptoConstants.ANDROID_KEY_STORE = "AndroidKeyStore" (например)

Сохранить ключи в Keystore Шифровать с открытым ключом Расшифровать с помощью закрытого ключа

С этими шагами мои методы шифрования

fun encrypt(publicKey: PublicKey, rawText: ByteArray): String {
    try {
        val cipher = CipherUtil.getStandardCipherInstance(TRANSFORMATION) // TRANSFORMATION = "RSA/ECB/PKCS1Padding"
        cipher.init(Cipher.ENCRYPT_MODE, publicKey)
        val bytes = cipher.doFinal(rawText)
        return Base64.encodeToString(bytes, BASE64_SETTINGS) // BASE64_SETTINGS = Base64.NO_WRAP
    } catch (e: GeneralSecurityException) {
        throw SecurityException(e)
    }
}

fun decrypt(privateKey: PrivateKey, base64CipherBytes: ByteArray): ByteArray {
    try {
        val cipher = CipherUtil.getStandardCipherInstance(TRANSFORMATION) // TRANSFORMATION = "RSA/ECB/PKCS1Padding"
        cipher.init(Cipher.DECRYPT_MODE, privateKey)
        val encryptedData = Base64.decode(base64CipherBytes, BASE64_SETTINGS) // BASE64_SETTINGS
        return cipher.doFinal(encryptedData)
    } catch (e: GeneralSecurityException) {
        throw SecurityException(e)
    }
}

Кстати, вы можете обойти кодировку Base64, если она вам не нужна.

...