33 private static final String KEYSTORE_PROVIDER =
"AndroidKeyStore";
34 private static final String KEY_ALIAS =
"freerdp_db_master_key";
35 private static final String PREFS_NAME =
"freerdp_security_prefs";
36 private static final String PREF_ENCRYPTED_DB_KEY =
"encrypted_db_key";
37 private static final String CIPHER_TRANSFORMATION =
"AES/GCM/NoPadding";
38 private static final int GCM_IV_LENGTH = 12;
39 private static final int GCM_TAG_LENGTH = 128;
40 private static final int DB_KEY_LENGTH = 32;
44 private final Context applicationContext;
48 this.applicationContext = context.getApplicationContext();
68 SharedPreferences prefs =
69 applicationContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
70 String encoded = prefs.getString(PREF_ENCRYPTED_DB_KEY,
null);
74 return decryptDbKey(encoded);
77 byte[] rawKey =
new byte[DB_KEY_LENGTH];
78 new SecureRandom().nextBytes(rawKey);
79 String encrypted = encryptDbKey(rawKey);
80 prefs.edit().putString(PREF_ENCRYPTED_DB_KEY, encrypted).apply();
88 SecretKey masterKey = getOrCreateMasterKey();
89 Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
90 cipher.init(Cipher.ENCRYPT_MODE, masterKey);
91 byte[] iv = cipher.getIV();
92 byte[] ciphertext = cipher.doFinal(rawKey);
95 byte[] packed =
new byte[GCM_IV_LENGTH + ciphertext.length];
96 System.arraycopy(iv, 0, packed, 0, GCM_IV_LENGTH);
97 System.arraycopy(ciphertext, 0, packed, GCM_IV_LENGTH, ciphertext.length);
98 return Base64.encodeToString(packed, Base64.NO_WRAP);
110 byte[] packed = Base64.decode(encoded, Base64.NO_WRAP);
111 byte[] iv =
new byte[GCM_IV_LENGTH];
112 byte[] ciphertext =
new byte[packed.length - GCM_IV_LENGTH];
113 System.arraycopy(packed, 0, iv, 0, GCM_IV_LENGTH);
114 System.arraycopy(packed, GCM_IV_LENGTH, ciphertext, 0, ciphertext.length);
116 SecretKey masterKey = getOrCreateMasterKey();
117 Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
118 cipher.init(Cipher.DECRYPT_MODE, masterKey,
new GCMParameterSpec(GCM_TAG_LENGTH, iv));
119 return cipher.doFinal(ciphertext);
127 private SecretKey getOrCreateMasterKey()
throws Exception
129 KeyStore keyStore = KeyStore.getInstance(KEYSTORE_PROVIDER);
132 if (keyStore.containsAlias(KEY_ALIAS))
134 return ((KeyStore.SecretKeyEntry)keyStore.getEntry(KEY_ALIAS,
null)).getSecretKey();
137 KeyGenerator keyGen =
138 KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER);
140 new KeyGenParameterSpec
141 .Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
143 .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
144 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
146 return keyGen.generateKey();
153 super(message, cause);