Comment puis-je utiliser l'Android KeyStore pour stocker de manière sécurisée des chaînes arbitraires?

Je voudrais pouvoir stocker de manière sécurisée certaines chaînes sensibles dans Android KeyStore. Je reçois les chaînes du serveur mais j'ai un cas d'utilisation qui me oblige à les persister. KeyStore ne permettra que l'accès à partir du même UID que celui affecté à mon application, et il va chiffrer les données avec le mot de passe principal de l'appareil, de sorte que je ne suis pas obligé de faire un cryptage supplémentaire pour protéger mes données. Mon problème est que je manque quelque chose de l'écriture des données. Le code que j'ai ci-dessous fonctionne parfaitement, tant que l'appel à KeyStore.store (null) est supprimé. Ce code échoue, et tant que je ne peux pas stocker les données après l'avoir placé sur KeyStore, je ne peux pas le persévérer.

Je pense que je manque quelque chose de l'API KeyStore, mais je ne sais pas quoi. Toute aide appréciée!

  • Désactiver les modifications sur seekbar par client
  • Comment ouvrir l'application Google Play Store directement sans l'intention du choix:
  • Alternatives au BatteryManager Android
  • Problèmes de rendu Android Studio: les classes suivantes n'ont pas pu être trouvées
  • Problèmes générant Google App Engine Backend dans Android Studio
  • Comment utiliser Camera pour prendre une photo en arrière-plan Service sur Android?
  • String metaKey = "ourSecretKey"; String encodedKey = "this is supposed to be a secret"; byte[] encodedKeyBytes = new byte[(int)encodedKey.length()]; encodedKeyBytes = encodedKey.getBytes("UTF-8"); KeyStoreParameter ksp = null; //String algorithm = "DES"; String algorithm = "DESede"; SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithm); SecretKeySpec secretKeySpec = new SecretKeySpec(encodedKeyBytes, algorithm); SecretKey secretKey = secretKeyFactory.generateSecret(secretKeySpec); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); KeyStore.SecretKeyEntry secretKeyEntry = new KeyStore.SecretKeyEntry(secretKey); keyStore.setEntry(metaKey, secretKeyEntry, ksp); keyStore.store(null); String recoveredSecret = ""; if (keyStore.containsAlias(metaKey)) { KeyStore.SecretKeyEntry recoveredEntry = (KeyStore.SecretKeyEntry)keyStore.getEntry(metaKey, ksp); byte[] bytes = recoveredEntry.getSecretKey().getEncoded(); for (byte b : bytes) { recoveredSecret += (char)b; } } Log.v(TAG, "recovered " + recoveredSecret); 

  • Le widget Android ne se met pas à jour - possède une ID de widget incorrecte
  • Comment configurer Android Studio pour fonctionner complètement hors ligne?
  • Comment changer les dispositifs par défaut de mise en page sur Android Studio
  • Crypter avec Node.js Crypto module et décrypter avec Java (dans l'application Android)
  • TexteInputLayout et EditText problème double indice
  • Les éléments ListView ne sont pas cliquables avec HorizontalScrollView à l'intérieur
  • 2 Solutions collect form web for “Comment puis-je utiliser l'Android KeyStore pour stocker de manière sécurisée des chaînes arbitraires?”

    J'ai commencé avec le principe que je pourrais utiliser AndroidKeyStore pour sécuriser des images de données arbitraires et les appeler "clés". Cependant, plus j'ai approfondi cela, plus il est devenu clair que l'API KeyStore est profondément enchevêtrée avec les objets liés à la sécurité: Certificats, KeySpecs, Fournisseurs, etc. Il n'est pas conçu pour stocker des données arbitraires et je ne vois pas un problème direct Chemin pour le plier à cette fin.

    Cependant, l'AndroidKeyStore peut être utilisé pour m'aider à sécuriser mes données sensibles. Je peux l'utiliser pour gérer les clés cryptographiques que je vais utiliser pour chiffrer les données locales dans l'application. En utilisant une combinaison de AndroidKeyStore, CipherOutputStream et CipherInputStream, nous pouvons:

    • Générer, stocker et récupérer des clés de cryptage sur l'appareil
    • Chiffrer des données arbitraires et les enregistrer sur le périphérique (dans le répertoire de l'application, où il sera protégé par les autorisations du système de fichiers)
    • Accédez et décryptez les données pour une utilisation ultérieure.

    Voici un exemple de code qui montre comment cela se réalise.

     try { KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); String alias = "key3"; int nBefore = keyStore.size(); // Create the keys if necessary if (!keyStore.containsAlias(alias)) { Calendar notBefore = Calendar.getInstance(); Calendar notAfter = Calendar.getInstance(); notAfter.add(Calendar.YEAR, 1); KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this) .setAlias(alias) .setKeyType("RSA") .setKeySize(2048) .setSubject(new X500Principal("CN=test")) .setSerialNumber(BigInteger.ONE) .setStartDate(notBefore.getTime()) .setEndDate(notAfter.getTime()) .build(); KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); generator.initialize(spec); KeyPair keyPair = generator.generateKeyPair(); } int nAfter = keyStore.size(); Log.v(TAG, "Before = " + nBefore + " After = " + nAfter); // Retrieve the keys KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null); RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey(); RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey(); Log.v(TAG, "private key = " + privateKey.toString()); Log.v(TAG, "public key = " + publicKey.toString()); // Encrypt the text String plainText = "This text is supposed to be a secret!"; String dataDirectory = getApplicationInfo().dataDir; String filesDirectory = getFilesDir().getAbsolutePath(); String encryptedDataFilePath = filesDirectory + File.separator + "keep_yer_secrets_here"; Log.v(TAG, "plainText = " + plainText); Log.v(TAG, "dataDirectory = " + dataDirectory); Log.v(TAG, "filesDirectory = " + filesDirectory); Log.v(TAG, "encryptedDataFilePath = " + encryptedDataFilePath); Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); inCipher.init(Cipher.ENCRYPT_MODE, publicKey); Cipher outCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL"); outCipher.init(Cipher.DECRYPT_MODE, privateKey); CipherOutputStream cipherOutputStream = new CipherOutputStream( new FileOutputStream(encryptedDataFilePath), inCipher); cipherOutputStream.write(plainText.getBytes("UTF-8")); cipherOutputStream.close(); CipherInputStream cipherInputStream = new CipherInputStream(new FileInputStream(encryptedDataFilePath), outCipher); byte [] roundTrippedBytes = new byte[1000]; // TODO: dynamically resize as we get more data int index = 0; int nextByte; while ((nextByte = cipherInputStream.read()) != -1) { roundTrippedBytes[index] = (byte)nextByte; index++; } String roundTrippedString = new String(roundTrippedBytes, 0, index, "UTF-8"); Log.v(TAG, "round tripped string = " + roundTrippedString); } catch (NoSuchAlgorithmException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchProviderException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (InvalidAlgorithmParameterException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (KeyStoreException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (CertificateException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (IOException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (UnrecoverableEntryException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (NoSuchPaddingException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (InvalidKeyException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (BadPaddingException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (IllegalBlockSizeException e) { Log.e(TAG, Log.getStackTraceString(e)); } catch (UnsupportedOperationException e) { Log.e(TAG, Log.getStackTraceString(e)); } 

    Vous avez peut-être remarqué qu'il y a des problèmes pour gérer différents niveaux d'API avec l'Android Keystore.

    Scytale est une bibliothèque open source qui fournit un wrapper pratique autour de l'Android Keystore afin que vous n'ayez pas de plaque de chaudière d'écriture et que vous puissiez plonger directement dans l'enrycissement / décryptage.

    Exemple de code:

     // Create and save key Store store = new Store(getApplicationContext()); if (!store.hasKey("test")) { SecretKey key = store.generateSymmetricKey("test", null); } ... // Get key SecretKey key = store.getSymmetricKey("test", null); // Encrypt/Decrypt data Crypto crypto = new Crypto(Options.TRANSFORMATION_SYMMETRIC); String text = "Sample text"; String encryptedData = crypto.encrypt(text, key); Log.i("Scytale", "Encrypted data: " + encryptedData); String decryptedData = crypto.decrypt(encryptedData, key); Log.i("Scytale", "Decrypted data: " + decryptedData); 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.