Android KeyStore用于存储SecretKey以进行加密/解密

时间:2016-03-31 04:19:35

标签: android android-keystore

我正试图在应用程序中保密(String),无论如何,除此之外!所以我想出了这个想法,使用keyStore来存储密钥,只用它来加密和解密我的秘密。以下是我保存(加密)我的秘密的方法:

        public static boolean setKeyStoreString(String strToStore, Context context) {

            if (strToStore == null) return false;
            if (strToStore.length() == 0) return false;
            Log.e(TAG, strToStore);
            try {
                KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
                keyStore.load(null);
                int nBefore = keyStore.size();
                // Create the keys if necessary
                if (!keyStore.containsAlias("phrase")) {
                    KeyGenerator generator = KeyGenerator.getInstance(
                            KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
                    KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder("phrase", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                            .setKeySize(256)
                            .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                            .setUserAuthenticationValidityDurationSeconds(-1)
                            .setRandomizedEncryptionRequired(false)
                            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                            .setUserAuthenticationRequired(false)
                            .build();
                    generator.init(spec);
                    generator.generateKey(); 
                }
                int nAfter = keyStore.size();
                Log.v(TAG, "Before = " + nBefore + " After = " + nAfter);


                String filesDirectory = context.getFilesDir().getAbsolutePath();
                String encryptedDataFilePath = filesDirectory + File.separator + "my_phrase";
    //            Log.v(TAG, "strPhrase = " + strToStore);
    //            Log.v(TAG, "dataDirectory = " + dataDirectory);
    //            Log.v(TAG, "filesDirectory = " + filesDirectory);
    //            Log.v(TAG, "encryptedDataFilePath = " + encryptedDataFilePath);

                SecretKey secret = (SecretKey) keyStore.getKey("phrase", null);
                Cipher inCipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
                inCipher.init(Cipher.ENCRYPT_MODE, secret);
                CipherOutputStream cipherOutputStream = new CipherOutputStream(
                        new FileOutputStream(encryptedDataFilePath), inCipher);
                byte[] bytesToStore = strToStore.getBytes("UTF-8");

                cipherOutputStream.write(bytesToStore);
                try {
                    cipherOutputStream.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                return true;
            } catch (Exception e) {
                Log.e(TAG, Log.getStackTraceString(e));
            }
            return false;
        }

以下是我尝试检索它的方法:

public static String getKeyStoreString(final Context context) {

        KeyStore keyStore;
        String recoveredSecret = "";
        String filesDirectory = context.getFilesDir().getAbsolutePath();
        String encryptedDataFilePath = filesDirectory + File.separator + "my_phrase";
        try {
            keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey)
                    keyStore.getKey("phrase", null);
            if (secretKey == null) throw new RuntimeException("secretKey is null");

            Cipher outCipher;
            outCipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            outCipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(
                    new byte[outCipher.getBlockSize()]));

            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++;
            }
            recoveredSecret = new String(roundTrippedBytes, 0, index, "UTF-8");
            Log.e(TAG, "round tripped string = " + recoveredSecret);
        } catch (Exception e) {
            e.printStackTrace();
        }

        Log.e(TAG, "recovered: " + recoveredSecret);
        return recoveredSecret;
    }

问题是 - 结果在开始时有点受损,

  

即:一些用于提取的酷文本>>>>> �k��X�&�ALqM,A�文本   提取

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,我使用Base64.encode(your byte[], Base64.DEFAULT);进行编码,Base64.decode(your byte[], Base64.DEFAULT)进行解码

尝试放byte[] encode = Base64.encode(bytesToStore, Base64.DEFAULT)byte[] bytesToStore = strToStore.getBytes("UTF-8");之后 在public static boolean setKeyStoreString()中并检入" encode"日志