2016-12-12 2 views
0

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

В основном, я на основе этой ссылки:

https://medium.com/@ericfu/securely-storing-secrets-in-an-android-application-501f030ae5a3#.80y72xi61

Я написал эту обертку с помощью другого потока я отправил из другого вопроса

java.lang.IllegalArgumentException: bad base-64 when decrypting string

Тем не менее, все пробы код, который я нахожу, шифрует и дешифрует во время одного и того же приложения. Это никогда не бывает полезным. Мне нужно зашифровать мою строку, сохранить где-нибудь и расшифровать ее позже. Таким образом, эта обертка пытается инициализировать KeyStore как таковой:

@TargetApi(Build.VERSION_CODES.M) 
public KeyStoreHelper(boolean encrypt) { 
    try { 
     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
       KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"); 
     if (encrypt) { 
      keyPairGenerator.initialize(
        new KeyGenParameterSpec.Builder(
          MY_KEY_NAME_INSIDE_KEYSTORE, 
          KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 
          .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 
          .build()); 
     } else { 
      keyPairGenerator.initialize(
        new KeyGenParameterSpec.Builder(
          MY_KEY_NAME_INSIDE_KEYSTORE, 
          KeyProperties.PURPOSE_DECRYPT) 
          .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) 
          .build()); 
     } 
     KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
     String provider = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? "AndroidOpenSSL" : "AndroidKeyStoreBCWorkaround"; 

     if (encrypt) { 
      PublicKey publicKey = keyPair.getPublic(); 
      mInCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); 
      mInCipher.init(Cipher.ENCRYPT_MODE, publicKey); 
     } else { 
      PrivateKey privateKey = keyPair.getPrivate(); 
      mOutCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider); 
      mOutCipher.init(Cipher.DECRYPT_MODE, privateKey); 
     } 
    } catch (Exception e) { 
     Log.e(ERROR_TAG, Log.getStackTraceString(e)); 
    } 
} 
public static KeyStoreHelper getInstance(boolean encrypt) { 
    if (mKeyStoreHelperInstance == null) { 
     mKeyStoreHelperInstance = new KeyStoreHelper(encrypt); 
    } 
    return mKeyStoreHelperInstance; 
} 

Затем я попытался зашифровать некоторые строки сохранить в настройках, как показано ниже

private SharedPreferences mSharedPreferences;  
private void testKeystoreHelper(boolean encrypt) { 
    KeyStoreHelper keyStoreHelper; 
    initSharedPreferences(); 
    final String sharedPreferencesAlias = "mysecret"; 
    String plainText; 
    String secretString; 
    if (encrypt) { 
     plainText = "my secret string"; 
     keyStoreHelper = KeyStoreHelper.getInstance(true); 
     secretString = keyStoreHelper.encrypt(plainText); 
     Log.v(TAG, "Encrypted = " + secretString); 
     mSharedPreferences.edit().putString(sharedPreferencesAlias, secretString).apply(); 
    } else { 
     keyStoreHelper = KeyStoreHelper.getInstance(false); 
     secretString = mSharedPreferences.getString(sharedPreferencesAlias, null); 
     plainText = keyStoreHelper.decrypt(secretString); 
     Log.v(TAG, "Decrypted" + plainText); 
    } 
} 

наконец я один проход с этим:

testKeystoreHelper(true); 

я выйти из приложения и запустить снова с этим:

testKeystoreHelper (ложь);

Но это никогда не работает давая мне:

E/Error: java.io.IOException: Error while finalizing cipher at 
javax.crypto.CipherInputStream.fillBuffer(CipherInputStream.java:104) 

Потому что каждый раз, когда приложение запускается, хотя ИМЯКЛАВИШИ одно и то же эти пары всегда разные:

KeyPair keyPair = keyPairGenerator.generateKeyPair(); 

Поскольку я инициализирую ключ каждый раз, когда , Но как еще я могу получить KeyPair без их инициализации?

Итак, я пропустил главный момент, короткая короткая история может привести меня к следующему базовому алгоритму?

  1. Init хранилище ключей
  2. получить пар
  3. ecrypt строку и сохранить в настройках
  4. бросить курить приложение
  5. Init хранилище ключей получать правильные пары ключей для дешифровки
  6. Получить зашифрованы строку из предпочтений
  7. дешифровать его в памяти

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

спасибо!

ответ

0

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

Используйте этот код для загрузки AndroidKeyStore и получить секретный ключ

KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 
keyStore.load(null); 
KeyStore.Entry entry = keyStore.getEntry(MY_KEY_NAME_INSIDE_KEYSTORE, null); 
PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); 

Не генерировать ключ, если он был создан. Проверьте, существуют ли с

keyStore.containsAlias(MY_KEY_NAME_INSIDE_KEYSTORE); 

Восстановление открытого ключа с

PublicKey publicKey = keyStore.getCertificate(MY_KEY_NAME_INSIDE_KEYSTORE).getPublicKey(); 
Смежные вопросы