Хранилище ключей Java, Android — предоставляет незашифрованный ключ API или секрет для шифрования

#java #android #encryption #android-keystore

#java #Android #шифрование #android-хранилище ключей

Вопрос:

Поскольку я новичок в Android, я работаю над сокрытием своих ключей API и нашел Android keystore, как это сделать. Но когда я вижу примеры использования хранилища ключей Android, я не понимаю, как предоставить незашифрованный исходный ключ для шифрования? если я сохраняю в коде, разве это не превзойдет цель использования хранилища ключей Android?

из статьи о хранении секретов: https://medium.com/@ericfu/securely-storing-secrets-in-an-android-application-501f030ae5a3

  1. Генерируйте случайный ключ при первом запуске приложения;
  2. Если вы хотите сохранить секрет, извлеките ключ из хранилища ключей, зашифруйте им данные, а затем сохраните зашифрованные данные в настройках.
  3. Если вы хотите прочитать секрет, прочитайте зашифрованные данные из настроек, получите ключ из хранилища ключей, а затем используйте ключ для расшифровки данных

Во втором пункте говорится, что с его помощью шифруются данные. Как предоставить данные, не раскрывая код / приложение? Я прошу прощения, если на это был дан ответ.

Спасибо

Комментарии:

1. Ключи в хранилище ключей Android никогда не покидают это хранилище ключей, поэтому вы не можете хранить там свои ключи API.

Ответ №1:

 private static final String KEYSTORE_PROVIDER = "AndroidKeyStore";
private static final String AES_MODE = "AES/GCM/NoPadding";
private static final String KEY_ALIAS = "MyNiceKey";
  

Загрузите хранилище ключей Android по умолчанию:

 KeyStore keyStore = KeyStore.getInstance(KEYSTORE_PROVIDER);
keyStore.load(null);
  

Создайте ключ AES внутри хранилища ключей, которое в последней версии Android является хранилищем ключей с аппаратной поддержкой; это означает, что очень сложно извлечь из него байты ключа:

 if (!keyStore.containsAlias(KEY_ALIAS)) {
    KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER);
    keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_ALIAS,
            KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
            .setBlockModes(KeyProperties.BLOCK_MODE_GCM)                   
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
            .setRandomizedEncryptionRequired(false) 
            .build());
    keyGenerator.generateKey();
}
  

В любом случае вы должны использовать .setRandomizedEncryptionRequired(true). Нет смысла настраивать ошибочный протокол. В противном случае, если вам нужно зашифровать всего несколько байтов (ваш ключ API), вы можете создать асимметричный открытый / закрытый ключ и зашифровать его с помощью RSA, чтобы вам даже не нужно было предоставлять IV.

Хейнг сказал, что, когда вы получаете секретный ключ из хранилища ключей:

  public static SecretKey getKeyStoreSecretKeyEntry(final String entryAlias)
            throws GeneralSecurityException, IOException {
        return ((KeyStore.SecretKeyEntry) getKeyStore().getEntry(entryAlias, null)).getSecretKey();
    }
  

возвращаемый секретный ключ не содержит материала ключа (реальных байтов ключа), а только его ссылку. Таким образом, вы можете свободно использовать его внутри шифра для шифрования и дешифрования того, что вы хотите. В любом случае ваш ключ API будет открыт enyway, если вы используете его для отправки http-запроса непосредственно к вашей службе. Лучший способ в вашем случае — использовать сервер, такой как Google Firebase

P.s. существует очень простая библиотека от Google, которая сэкономит вам время и головную боль: https://developer.android.com/jetpack/androidx/releases/security

https://developer.android.com/topic/security/data

Вывод: ключ, который вы генерируете в хранилище ключей Android, является собственностью пользователя, и его следует использовать для защиты личных данных пользователя. Поэтому не рекомендуется шифровать ключ API, который является личными данными разработчика, с помощью пользовательского ключа. Используйте сервер для защиты ключа API.

Комментарии:

1. Большое вам спасибо за комментарий. Итак, вы говорите, что храните мой оригинальный ключ API в Google Firebase и извлекаете его, чтобы зашифровать в хранилище ключей. это правильно или я ошибаюсь?

2. Лучше всего было бы сохранить ключ в firebase и использовать функцию firebase для выполнения запроса API и возврата результата в ваше приложение

3. Спасибо, я действительно ценю ваш ответ.

4. Спасибо. Кстати, даже если ключ API предназначен только для аутентификации случайного временного токена для фактического вызова API, его все равно можно получить от клиента приложения, потому что ключ, который вы генерируете для шифрования, должен считаться собственностью пользователя. Таким образом, пользователь может использовать свой ключ для расшифровки ключа API в любое время.