Skip to content

Commit fa8618b

Browse files
committed
use encrypted shared prefs for saving password
1 parent 5a4b561 commit fa8618b

9 files changed

Lines changed: 142 additions & 16 deletions

app/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,6 @@ dependencies {
122122
implementation "net.lingala.zip4j:zip4j:${zip4j_version}"
123123

124124
implementation "androidx.preference:preference:${preference_version}"
125+
126+
implementation 'com.github.yausername:EncryptedSharedPreferences:1.0.0-beta01'
125127
}

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<application
1515
android:name=".App"
1616
android:allowBackup="true"
17+
android:fullBackupContent="@xml/android_auto_backup_rules"
1718
android:icon="@mipmap/ic_launcher"
1819
android:label="@string/app_name"
1920
android:logo="@mipmap/ic_launcher"

app/src/main/java/org/schabi/newpipe/database/BackupRestoreHelper.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,9 @@ public void exportDatabase(String path, char[] password) throws Exception {
6262

6363
private void saveSharedPreferencesToFile(File dst) {
6464
ObjectOutputStream output = null;
65-
SharedPreferences pref = null;
66-
String password = null;
6765
try {
6866
output = new ObjectOutputStream(new FileOutputStream(dst));
69-
pref = PreferenceManager.getDefaultSharedPreferences(ctx);
70-
// remove password from shared prefs before taking backup
71-
password = pref.getString(ctx.getString(R.string.backup_password_key), null);
72-
pref.edit().remove(ctx.getString(R.string.backup_password_key)).apply();
67+
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(ctx);
7368
output.writeObject(pref.getAll());
7469
} catch (FileNotFoundException e) {
7570
e.printStackTrace();
@@ -83,9 +78,6 @@ private void saveSharedPreferencesToFile(File dst) {
8378
}
8479
} catch (IOException ex) {
8580
ex.printStackTrace();
86-
} finally {
87-
// add password again after taking backup
88-
if(pref != null) pref.edit().putString(ctx.getString(R.string.backup_password_key), password).apply();
8981
}
9082
}
9183
}
@@ -158,9 +150,7 @@ else if (v instanceof String)
158150
prefEdit.commit();
159151
} catch (FileNotFoundException e) {
160152
e.printStackTrace();
161-
} catch (IOException e) {
162-
e.printStackTrace();
163-
} catch (ClassNotFoundException e) {
153+
} catch (IOException | ClassNotFoundException e) {
164154
e.printStackTrace();
165155
} finally {
166156
try {

app/src/main/java/org/schabi/newpipe/settings/AutoBackupWorker.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package org.schabi.newpipe.settings;
22

33
import android.content.Context;
4+
import android.content.SharedPreferences;
45
import android.os.Build;
56
import android.text.TextUtils;
67

78
import androidx.annotation.NonNull;
8-
import androidx.preference.PreferenceManager;
99
import androidx.work.Worker;
1010
import androidx.work.WorkerParameters;
1111

@@ -29,7 +29,8 @@ public Result doWork() {
2929
try {
3030
new File(autoBackupPath).mkdirs();
3131
String path = autoBackupPath + File.separator + "NewPipeData-" + Build.MODEL + ".zip";
32-
String password = PreferenceManager.getDefaultSharedPreferences(ctx).getString(ctx.getString(R.string.backup_password_key), null);
32+
SharedPreferences encryptedSharedPreferences = EncryptedSharedPreferencesHelper.create(ctx);
33+
String password = (encryptedSharedPreferences != null) ? encryptedSharedPreferences.getString(ctx.getString(R.string.backup_password_key), null) : null;
3334
if(TextUtils.isEmpty(password)) return Result.failure();
3435
backupRestoreHelper.exportDatabase(path, password.toCharArray());
3536
} catch (Exception e) {

app/src/main/java/org/schabi/newpipe/settings/BackupSettingsFragment.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import android.content.Context;
77
import android.content.DialogInterface;
88
import android.content.Intent;
9+
import android.content.SharedPreferences;
910
import android.net.Uri;
1011
import android.os.Bundle;
1112
import android.text.TextUtils;
@@ -123,6 +124,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
123124
if((Boolean) newValue) PermissionHelper.checkStoragePermissions(getActivity(), BACKUP_STORAGE_PERMISSION_REQUEST_CODE);
124125
return true;
125126
});
127+
126128
Boolean autoBackup = defaultPreferences.getBoolean(getString(R.string.scheduled_backups_key), false);
127129
if(autoBackup) PermissionHelper.checkStoragePermissions(getActivity(), BACKUP_STORAGE_PERMISSION_REQUEST_CODE);
128130

@@ -303,7 +305,8 @@ private void importDatabase(String filePath) {
303305
private void scheduleWork(String tag) {
304306
Boolean autoBackup = defaultPreferences.getBoolean(getString(R.string.scheduled_backups_key), false);
305307
if(autoBackup){
306-
if(TextUtils.isEmpty(defaultPreferences.getString(ctx.getString(R.string.backup_password_key), null))){
308+
SharedPreferences encryptedSharedPreferences = EncryptedSharedPreferencesHelper.create(requireContext());
309+
if(encryptedSharedPreferences == null || TextUtils.isEmpty(encryptedSharedPreferences.getString(ctx.getString(R.string.backup_password_key), null))){
307310
Toast.makeText(ctx, R.string.auto_backup_password_mandatory, Toast.LENGTH_LONG).show();
308311
}
309312
Integer interval = Integer.valueOf(defaultPreferences.getString(getString(R.string.backup_frequency_key), "24"));
@@ -317,6 +320,7 @@ private void scheduleWork(String tag) {
317320
}
318321
}
319322

323+
320324
@Override
321325
public void onPause() {
322326
scheduleWork(TAG_AUTO_BACKUP_WORK);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.schabi.newpipe.settings;
2+
3+
import android.content.Context;
4+
import android.content.SharedPreferences;
5+
import android.os.Build;
6+
import android.util.Log;
7+
8+
import androidx.annotation.NonNull;
9+
import androidx.annotation.Nullable;
10+
11+
import org.schabi.newpipe.MainActivity;
12+
import org.yausername.encryptedsharedpreferences.EncryptedSharedPreferences;
13+
14+
import java.io.IOException;
15+
import java.security.GeneralSecurityException;
16+
17+
public class EncryptedSharedPreferencesHelper {
18+
19+
private static final String TAG = "EncSharedPrefHelper";
20+
private static final boolean DEBUG = MainActivity.DEBUG;
21+
22+
private static final String FILE_NAME = "encryptedPrefs";
23+
private static final String MASTER_KEY_ALIAS = "_newpipe_security_master_key_";
24+
25+
@Nullable
26+
public static SharedPreferences create(@NonNull Context context){
27+
try {
28+
EncryptedSharedPreferences.PrefValueEncryptionScheme prefValueEncryptionScheme;
29+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
30+
prefValueEncryptionScheme = EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM;
31+
}else{
32+
prefValueEncryptionScheme = EncryptedSharedPreferences.PrefValueEncryptionScheme.XCHACHA20_POLY1305;
33+
}
34+
return EncryptedSharedPreferences.create(FILE_NAME, MASTER_KEY_ALIAS, context, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, prefValueEncryptionScheme);
35+
} catch (GeneralSecurityException | IOException e) {
36+
if(DEBUG) Log.e(TAG, "failed to create encrypted preferences", e);
37+
return null;
38+
}
39+
}
40+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package org.schabi.newpipe.settings;
2+
3+
import android.content.Context;
4+
import android.content.SharedPreferences;
5+
import android.text.TextUtils;
6+
import android.util.AttributeSet;
7+
import android.widget.Toast;
8+
9+
import androidx.preference.EditTextPreference;
10+
11+
public class PasswordPreference extends EditTextPreference {
12+
13+
private final SharedPreferences encryptedSharedPreferences;
14+
15+
public PasswordPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
16+
super(context, attrs, defStyleAttr, defStyleRes);
17+
encryptedSharedPreferences = initEncryptedSharedPreferences();
18+
}
19+
20+
public PasswordPreference(Context context, AttributeSet attrs, int defStyleAttr) {
21+
super(context, attrs, defStyleAttr);
22+
encryptedSharedPreferences = initEncryptedSharedPreferences();
23+
}
24+
25+
public PasswordPreference(Context context, AttributeSet attrs) {
26+
super(context, attrs);
27+
encryptedSharedPreferences = initEncryptedSharedPreferences();
28+
}
29+
30+
public PasswordPreference(Context context) {
31+
super(context);
32+
encryptedSharedPreferences = initEncryptedSharedPreferences();
33+
}
34+
35+
private SharedPreferences initEncryptedSharedPreferences(){
36+
return EncryptedSharedPreferencesHelper.create(getContext());
37+
}
38+
39+
@Override
40+
public void setText(String text) {
41+
final boolean wasBlocking = shouldDisableDependents();
42+
43+
setPassword(text);
44+
45+
final boolean isBlocking = shouldDisableDependents();
46+
if (isBlocking != wasBlocking) {
47+
notifyDependencyChange(isBlocking);
48+
}
49+
50+
notifyChanged();
51+
}
52+
53+
@Override
54+
public String getText() {
55+
return getPassword();
56+
}
57+
58+
@Override
59+
protected void onSetInitialValue(Object defaultValue) {
60+
String password = getPassword();
61+
setText(password != null ? password : (String) defaultValue);
62+
}
63+
64+
private String getPassword() {
65+
if (encryptedSharedPreferences == null){
66+
return null;
67+
}
68+
return encryptedSharedPreferences.getString(getKey(), null);
69+
}
70+
71+
private void setPassword(String password){
72+
if(encryptedSharedPreferences == null){
73+
Toast.makeText(getContext(), "Failed to save password", Toast.LENGTH_SHORT).show();
74+
return;
75+
}
76+
encryptedSharedPreferences.edit().putString(getKey(), password).apply();
77+
}
78+
79+
@Override
80+
public boolean shouldDisableDependents() {
81+
return TextUtils.isEmpty(getText()) || !isEnabled();
82+
}
83+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<full-backup-content>
3+
<exclude domain="sharedpref" path="encryptedPrefs.xml"/>
4+
</full-backup-content>

app/src/main/res/xml/backup_restore_settings.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@
2525
android:summary="%s"
2626
android:title="@string/auto_backup_frequency_title"/>
2727

28-
<EditTextPreference
28+
<org.schabi.newpipe.settings.PasswordPreference
2929
app:iconSpaceReserved="false"
30+
android:persistent="false"
3031
android:dialogLayout="@layout/dialog_password"
3132
android:dependency="@string/scheduled_backups_key"
3233
android:key="@string/backup_password_key"

0 commit comments

Comments
 (0)