27 private static final String KEYSTORE_PROVIDER =
"AndroidKeyStore";
28 private static final String KEY_ALIAS =
"freerdp_db_master_key";
29 private static final String PREFS_NAME =
"freerdp_security_prefs";
30 private static final String PREF_ENCRYPTED_DB_KEY =
"encrypted_db_key";
31 private static final String CIPHER_TRANSFORMATION =
"AES/GCM/NoPadding";
32 private static final int GCM_IV_LENGTH = 12;
33 private static final int GCM_TAG_LENGTH = 128;
34 private static final int DB_KEY_LENGTH = 32;
38 private final Context applicationContext;
42 this.applicationContext = context.getApplicationContext();
62 SharedPreferences prefs =
63 applicationContext.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
64 String encoded = prefs.getString(PREF_ENCRYPTED_DB_KEY,
null);
68 return decryptDbKey(encoded);
71 byte[] rawKey =
new byte[DB_KEY_LENGTH];
72 new SecureRandom().nextBytes(rawKey);
73 String encrypted = encryptDbKey(rawKey);
74 prefs.edit().putString(PREF_ENCRYPTED_DB_KEY, encrypted).apply();
82 SecretKey masterKey = getOrCreateMasterKey();
83 Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
84 cipher.init(Cipher.ENCRYPT_MODE, masterKey);
85 byte[] iv = cipher.getIV();
86 byte[] ciphertext = cipher.doFinal(rawKey);
89 byte[] packed =
new byte[GCM_IV_LENGTH + ciphertext.length];
90 System.arraycopy(iv, 0, packed, 0, GCM_IV_LENGTH);
91 System.arraycopy(ciphertext, 0, packed, GCM_IV_LENGTH, ciphertext.length);
92 return Base64.encodeToString(packed, Base64.NO_WRAP);
104 byte[] packed = Base64.decode(encoded, Base64.NO_WRAP);
105 byte[] iv =
new byte[GCM_IV_LENGTH];
106 byte[] ciphertext =
new byte[packed.length - GCM_IV_LENGTH];
107 System.arraycopy(packed, 0, iv, 0, GCM_IV_LENGTH);
108 System.arraycopy(packed, GCM_IV_LENGTH, ciphertext, 0, ciphertext.length);
110 SecretKey masterKey = getOrCreateMasterKey();
111 Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
112 cipher.init(Cipher.DECRYPT_MODE, masterKey,
new GCMParameterSpec(GCM_TAG_LENGTH, iv));
113 return cipher.doFinal(ciphertext);
121 private SecretKey getOrCreateMasterKey()
throws Exception
123 KeyStore keyStore = KeyStore.getInstance(KEYSTORE_PROVIDER);
126 if (keyStore.containsAlias(KEY_ALIAS))
128 return ((KeyStore.SecretKeyEntry)keyStore.getEntry(KEY_ALIAS,
null)).getSecretKey();
131 KeyGenerator keyGen =
132 KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER);
134 new KeyGenParameterSpec
135 .Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
137 .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
138 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
140 return keyGen.generateKey();
147 super(message, cause);