Added cloud data read/write

pull/212/head
M66B 2 years ago
parent b4b17f381e
commit fc77f3c591

@ -43,6 +43,7 @@ import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.Base64;
import android.util.Pair; import android.util.Pair;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -84,6 +85,8 @@ import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
@ -105,10 +108,12 @@ import javax.crypto.Cipher;
import javax.crypto.CipherInputStream; import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream; import javax.crypto.CipherOutputStream;
import javax.crypto.IllegalBlockSizeException; import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
public class FragmentOptionsBackup extends FragmentBase implements SharedPreferences.OnSharedPreferenceChangeListener { public class FragmentOptionsBackup extends FragmentBase implements SharedPreferences.OnSharedPreferenceChangeListener {
@ -212,7 +217,7 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
btnLogin.setOnClickListener(new View.OnClickListener() { btnLogin.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
onLogin(); onCloudLogin();
} }
}); });
@ -240,14 +245,14 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
ibSync.setOnClickListener(new View.OnClickListener() { ibSync.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
// TODO onCloudSync();
} }
}); });
btnLogout.setOnClickListener(new View.OnClickListener() { btnLogout.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
onLogout(); onCloudLogout();
} }
}); });
@ -1478,11 +1483,16 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
return intent; return intent;
} }
private void onLogin() { private void onCloudSync() {
String username = etUser.getText().toString(); Bundle args = new Bundle();
cloud(args);
}
private void onCloudLogin() {
String username = etUser.getText().toString().trim();
String password = tilPassword.getEditText().getText().toString(); String password = tilPassword.getEditText().getText().toString();
if (TextUtils.isEmpty(username.trim())) { if (TextUtils.isEmpty(username)) {
etUser.requestFocus(); etUser.requestFocus();
return; return;
} }
@ -1492,11 +1502,17 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
return; return;
} }
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
prefs.edit()
.putString("cloud_user", username)
.putString("cloud_password", password)
.apply();
Bundle args = new Bundle(); Bundle args = new Bundle();
cloud(args); cloud(args);
} }
private void onLogout() { private void onCloudLogout() {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putBoolean("logout", true); args.putBoolean("logout", true);
args.putBoolean("wipe", cbDelete.isChecked()); args.putBoolean("wipe", cbDelete.isChecked());
@ -1504,8 +1520,10 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
} }
private void cloud(Bundle args) { private void cloud(Bundle args) {
args.putString("user", etUser.getText().toString().trim()); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
args.putString("password", tilPassword.getEditText().getText().toString());
args.putString("user", prefs.getString("cloud_user", null));
args.putString("password", prefs.getString("cloud_password", null));
new SimpleTask<String>() { new SimpleTask<String>() {
@Override @Override
@ -1525,16 +1543,40 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
boolean wipe = args.getBoolean("wipe"); boolean wipe = args.getBoolean("wipe");
byte[] salt = MessageDigest.getInstance("SHA256").digest(user.getBytes()); byte[] salt = MessageDigest.getInstance("SHA256").digest(user.getBytes());
String cloudUser = Helper.hex(MessageDigest.getInstance("SHA256").digest(salt)); byte[] huser = MessageDigest.getInstance("SHA256").digest(salt);
String cloudUser = Base64.encodeToString(huser, Base64.NO_PADDING | Base64.NO_WRAP);
Pair<byte[], byte[]> key = getKeyPair(salt, password); Pair<byte[], byte[]> key = getKeyPair(salt, password);
String cloudPassword = Helper.hex(key.first); String cloudPassword = Base64.encodeToString(key.first, Base64.NO_PADDING | Base64.NO_WRAP);
JSONObject jroot = new JSONObject(); JSONObject jroot = new JSONObject();
jroot.put("username", cloudUser); jroot.put("username", cloudUser);
jroot.put("password", cloudPassword); jroot.put("password", cloudPassword);
jroot.put("wipe", wipe); jroot.put("wipe", wipe);
jroot.put("debug", BuildConfig.DEBUG); jroot.put("debug", BuildConfig.DEBUG);
if (false) {
JSONArray jwrite = new JSONArray();
JSONObject jkv1 = new JSONObject();
jkv1.put("key", encryptValue("key1", key.second));
jkv1.put("value", encryptValue("value1", key.second));
jwrite.put(jkv1);
JSONObject jkv2 = new JSONObject();
jkv2.put("key", encryptValue("key2", key.second));
jkv2.put("value", null);
jwrite.put(jkv2);
jroot.put("write", jwrite);
}
if (true) {
JSONArray jread = new JSONArray();
jread.put(encryptValue("key1", key.second));
jroot.put("read", jread);
}
String request = jroot.toString(); String request = jroot.toString();
Log.i("Cloud request=" + request); Log.i("Cloud request=" + request);
@ -1558,6 +1600,7 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
if (status != HttpsURLConnection.HTTP_OK) { if (status != HttpsURLConnection.HTTP_OK) {
String error = "Error " + status + ": " + connection.getResponseMessage(); String error = "Error " + status + ": " + connection.getResponseMessage();
String detail = Helper.readStream(connection.getErrorStream()); String detail = Helper.readStream(connection.getErrorStream());
Log.w("Cloud error=" + error + " detail=" + detail);
JSONObject jerror = new JSONObject(detail); JSONObject jerror = new JSONObject(detail);
if (status == HttpsURLConnection.HTTP_FORBIDDEN) if (status == HttpsURLConnection.HTTP_FORBIDDEN)
throw new SecurityException(jerror.optString("error")); throw new SecurityException(jerror.optString("error"));
@ -1576,7 +1619,6 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
@Override @Override
protected void onExecuted(Bundle args, String status) { protected void onExecuted(Bundle args, String status) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
if ("ok".equals(status) && !args.getBoolean("logout")) if ("ok".equals(status) && !args.getBoolean("logout"))
prefs.edit() prefs.edit()
.putString("cloud_user", args.getString("user")) .putString("cloud_user", args.getString("user"))
@ -1627,6 +1669,16 @@ public class FragmentOptionsBackup extends FragmentBase implements SharedPrefere
Arrays.copyOfRange(encoded, half, half + half)); Arrays.copyOfRange(encoded, half, half + half));
} }
private String encryptValue(String value, byte[] key)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
SecretKeySpec secret = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
IvParameterSpec ivSpec = new IvParameterSpec(new byte[12]);
cipher.init(Cipher.ENCRYPT_MODE, secret, ivSpec);
byte[] encrypted = cipher.doFinal(value.getBytes());
return Base64.encodeToString(encrypted, Base64.NO_PADDING | Base64.NO_WRAP);
}
public static class FragmentDialogExport extends FragmentDialogBase { public static class FragmentDialogExport extends FragmentDialogBase {
private TextInputLayout tilPassword1; private TextInputLayout tilPassword1;
private TextInputLayout tilPassword2; private TextInputLayout tilPassword2;

Loading…
Cancel
Save