Skip to content

Commit a7f0903

Browse files
committed
Recreate shared prefs on failure
1 parent dfd909d commit a7f0903

File tree

2 files changed

+96
-14
lines changed

2 files changed

+96
-14
lines changed

OpenScienceJournal/whistlepunk_library/src/main/java/com/google/android/apps/forscience/whistlepunk/accounts/arduino/ArduinoAccountProvider.java

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,21 @@
1616
import com.google.android.apps.forscience.whistlepunk.accounts.AppAccount;
1717
import com.google.android.apps.forscience.whistlepunk.remote.StringUtils;
1818

19+
import java.io.File;
1920
import java.io.IOException;
2021
import java.security.GeneralSecurityException;
22+
import java.security.KeyStore;
2123

2224
public class ArduinoAccountProvider extends AbstractAccountsProvider {
2325

2426
private static final String LOG_TAG = "ArduinoAccountProvider";
27+
private static final String SHARED_PREFS_FILENAME = "ArduinoSharedPreferences";
2528

2629
private ArduinoAccount arduinoAccount;
2730

2831
public ArduinoAccountProvider(final Context context) {
2932
super(context);
33+
3034
final SharedPreferences prefs = getSharedPreferences();
3135
final String jsonToken = prefs.getString("token", null);
3236
if (!StringUtils.isEmpty(jsonToken)) {
@@ -100,27 +104,59 @@ public void showAddAccountDialog(Activity activity) {
100104
public void showAccountSwitcherDialog(Fragment fragment, int requestCode) {
101105
}
102106

103-
private SharedPreferences getSharedPreferences() {
107+
private SharedPreferences getBrandNewSharedPreferences() {
104108
MasterKey masterKey = null;
109+
105110
try {
111+
File sharedPrefsFile = new File(applicationContext.getFilesDir().getParent() + "/shared_prefs/" + SHARED_PREFS_FILENAME + ".xml");
112+
boolean deleted = sharedPrefsFile.delete();
113+
114+
Log.d(LOG_TAG, String.format("Shared prefs file deleted: %s", deleted));
115+
116+
// delete MasterKey
117+
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
118+
keyStore.load(null);
119+
keyStore.deleteEntry(MasterKey.DEFAULT_MASTER_KEY_ALIAS);
120+
121+
// build MasterKey
106122
masterKey = new MasterKey.Builder(applicationContext, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
107123
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
108124
.build();
109125

126+
// create shared preferences
110127
return EncryptedSharedPreferences.create(
111128
applicationContext,
112-
"ArduinoSharedPreferences",
129+
SHARED_PREFS_FILENAME,
113130
masterKey,
114131
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
115132
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
116133
);
117-
} catch (GeneralSecurityException e) {
118-
Log.e(LOG_TAG, "Unable to retrieve encrypted shared preferences", e);
119-
throw new RuntimeException("Unable to retrieve encrypted shared preferences", e);
120-
} catch (IOException e) {
134+
} catch (GeneralSecurityException | IOException e) {
121135
Log.e(LOG_TAG, "Unable to retrieve encrypted shared preferences", e);
122136
throw new RuntimeException("Unable to retrieve encrypted shared preferences", e);
123137
}
124138
}
125139

140+
private SharedPreferences getSharedPreferences() {
141+
MasterKey masterKey = null;
142+
try {
143+
// build MasterKey
144+
masterKey = new MasterKey.Builder(applicationContext, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
145+
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
146+
.build();
147+
148+
// get or create shared preferences
149+
return EncryptedSharedPreferences.create(
150+
applicationContext,
151+
SHARED_PREFS_FILENAME,
152+
masterKey,
153+
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
154+
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
155+
);
156+
} catch (GeneralSecurityException | IOException e) {
157+
Log.e(LOG_TAG, "Unable to retrieve encrypted shared preferences, regenerating master key.", e);
158+
return this.getBrandNewSharedPreferences();
159+
}
160+
}
161+
126162
}

OpenScienceJournal/whistlepunk_library/src/main/java/com/google/android/apps/forscience/whistlepunk/gdrivesync/GDriveShared.java

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22

33
import android.content.Context;
44
import android.content.SharedPreferences;
5+
import android.util.Log;
56

67
import androidx.security.crypto.EncryptedSharedPreferences;
7-
import androidx.security.crypto.MasterKeys;
8+
import androidx.security.crypto.MasterKey;
9+
10+
import java.io.File;
11+
import java.io.IOException;
12+
import java.security.GeneralSecurityException;
13+
import java.security.KeyStore;
814

915
public class GDriveShared {
16+
private static final String LOG_TAG = "GDriveShared";
1017

1118
private static boolean mAccountLoaded = false;
1219

@@ -54,23 +61,62 @@ public static GDriveAccount getCredentials(final Context context) {
5461
return mAccount;
5562
}
5663

57-
private static SharedPreferences getSharedPreferences(final Context context) {
64+
private static SharedPreferences getBrandNewSharedPreferences(Context context) {
65+
MasterKey masterKey = null;
66+
5867
try {
59-
final String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
68+
File sharedPrefsFile = new File(context.getFilesDir().getParent() + "/shared_prefs/" + SHARED_PREFS_FILENAME + ".xml");
69+
boolean deleted = sharedPrefsFile.delete();
70+
71+
Log.d(LOG_TAG, String.format("Shared prefs file deleted: %s", deleted));
72+
73+
// delete MasterKey
74+
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
75+
keyStore.load(null);
76+
keyStore.deleteEntry(MasterKey.DEFAULT_MASTER_KEY_ALIAS);
77+
78+
// build MasterKey
79+
masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
80+
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
81+
.build();
82+
83+
// create shared preferences
6084
return EncryptedSharedPreferences.create(
61-
PREFS_NAME,
62-
masterKeyAlias,
6385
context,
86+
SHARED_PREFS_FILENAME,
87+
masterKey,
6488
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
6589
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
6690
);
67-
} catch (Exception e) {
68-
throw new RuntimeException(e);
91+
} catch (GeneralSecurityException | IOException e) {
92+
Log.e(LOG_TAG, "Unable to retrieve encrypted shared preferences", e);
93+
throw new RuntimeException("Unable to retrieve encrypted shared preferences", e);
6994
}
7095
}
7196

72-
private static final String PREFS_NAME = "GoogleDriveSync";
97+
private static SharedPreferences getSharedPreferences(final Context context) {
98+
MasterKey masterKey = null;
99+
try {
100+
// build MasterKey
101+
masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
102+
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
103+
.build();
104+
105+
// get or create shared preferences
106+
return EncryptedSharedPreferences.create(
107+
context,
108+
SHARED_PREFS_FILENAME,
109+
masterKey,
110+
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
111+
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
112+
);
113+
} catch (GeneralSecurityException | IOException e) {
114+
Log.e(LOG_TAG, "Unable to retrieve encrypted shared preferences, regenerating master key.", e);
115+
return getBrandNewSharedPreferences(context);
116+
}
117+
}
73118

119+
private static final String SHARED_PREFS_FILENAME = "GoogleDriveSync";
74120
private static final String KEY_ACCOUNT_ID = "account_id";
75121
private static final String KEY_EMAIL = "email";
76122
private static final String KEY_TOKEN = "token";

0 commit comments

Comments
 (0)