|
@@ -20,532 +20,539 @@
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
*/
|
|
-package com.owncloud.android.ui.dialog;
|
|
|
|
-
|
|
|
|
-import android.accounts.AccountManager;
|
|
|
|
-import android.app.Dialog;
|
|
|
|
-import android.content.Context;
|
|
|
|
-import android.content.DialogInterface;
|
|
|
|
-import android.content.Intent;
|
|
|
|
-import android.os.AsyncTask;
|
|
|
|
-import android.os.Bundle;
|
|
|
|
-import android.view.LayoutInflater;
|
|
|
|
-import android.view.View;
|
|
|
|
-import android.widget.Button;
|
|
|
|
-
|
|
|
|
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
|
|
|
-import com.nextcloud.client.account.User;
|
|
|
|
-import com.nextcloud.client.di.Injectable;
|
|
|
|
-import com.owncloud.android.R;
|
|
|
|
-import com.owncloud.android.databinding.SetupEncryptionDialogBinding;
|
|
|
|
-import com.owncloud.android.datamodel.ArbitraryDataProvider;
|
|
|
|
-import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
|
|
|
|
-import com.owncloud.android.lib.common.accounts.AccountUtils;
|
|
|
|
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|
|
|
-import com.owncloud.android.lib.common.utils.Log_OC;
|
|
|
|
-import com.owncloud.android.lib.resources.users.DeletePublicKeyOperation;
|
|
|
|
-import com.owncloud.android.lib.resources.users.GetPrivateKeyOperation;
|
|
|
|
-import com.owncloud.android.lib.resources.users.GetPublicKeyOperation;
|
|
|
|
-import com.owncloud.android.lib.resources.users.SendCSROperation;
|
|
|
|
-import com.owncloud.android.lib.resources.users.StorePrivateKeyOperation;
|
|
|
|
-import com.owncloud.android.utils.CsrHelper;
|
|
|
|
-import com.owncloud.android.utils.EncryptionUtils;
|
|
|
|
-import com.owncloud.android.utils.theme.ViewThemeUtils;
|
|
|
|
-
|
|
|
|
-import java.io.IOException;
|
|
|
|
-import java.lang.ref.WeakReference;
|
|
|
|
-import java.security.KeyPair;
|
|
|
|
-import java.security.PrivateKey;
|
|
|
|
-import java.util.ArrayList;
|
|
|
|
-import java.util.Arrays;
|
|
|
|
-import java.util.Locale;
|
|
|
|
-
|
|
|
|
-import javax.inject.Inject;
|
|
|
|
-
|
|
|
|
-import androidx.annotation.NonNull;
|
|
|
|
-import androidx.annotation.VisibleForTesting;
|
|
|
|
-import androidx.appcompat.app.AlertDialog;
|
|
|
|
-import androidx.fragment.app.DialogFragment;
|
|
|
|
-import androidx.fragment.app.Fragment;
|
|
|
|
-
|
|
|
|
-import static com.owncloud.android.utils.EncryptionUtils.MNEMONIC;
|
|
|
|
-import static com.owncloud.android.utils.EncryptionUtils.decodeStringToBase64Bytes;
|
|
|
|
-import static com.owncloud.android.utils.EncryptionUtils.decryptStringAsymmetric;
|
|
|
|
-import static com.owncloud.android.utils.EncryptionUtils.encodeBytesToBase64String;
|
|
|
|
-import static com.owncloud.android.utils.EncryptionUtils.generateKey;
|
|
|
|
|
|
+package com.owncloud.android.ui.dialog
|
|
|
|
+
|
|
|
|
+import android.accounts.AccountManager
|
|
|
|
+import android.annotation.SuppressLint
|
|
|
|
+import android.app.Dialog
|
|
|
|
+import android.content.Context
|
|
|
|
+import android.content.DialogInterface
|
|
|
|
+import android.content.Intent
|
|
|
|
+import android.os.AsyncTask
|
|
|
|
+import android.os.Build
|
|
|
|
+import android.os.Bundle
|
|
|
|
+import android.view.View
|
|
|
|
+import androidx.annotation.VisibleForTesting
|
|
|
|
+import androidx.appcompat.app.AlertDialog
|
|
|
|
+import androidx.fragment.app.DialogFragment
|
|
|
|
+import com.google.android.material.button.MaterialButton
|
|
|
|
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
|
|
+import com.nextcloud.client.account.User
|
|
|
|
+import com.nextcloud.client.di.Injectable
|
|
|
|
+import com.owncloud.android.R
|
|
|
|
+import com.owncloud.android.databinding.SetupEncryptionDialogBinding
|
|
|
|
+import com.owncloud.android.datamodel.ArbitraryDataProvider
|
|
|
|
+import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
|
|
|
|
+import com.owncloud.android.lib.common.accounts.AccountUtils
|
|
|
|
+import com.owncloud.android.lib.common.utils.Log_OC
|
|
|
|
+import com.owncloud.android.lib.resources.users.DeletePublicKeyOperation
|
|
|
|
+import com.owncloud.android.lib.resources.users.GetPrivateKeyOperation
|
|
|
|
+import com.owncloud.android.lib.resources.users.GetPublicKeyOperation
|
|
|
|
+import com.owncloud.android.lib.resources.users.SendCSROperation
|
|
|
|
+import com.owncloud.android.lib.resources.users.StorePrivateKeyOperation
|
|
|
|
+import com.owncloud.android.utils.CsrHelper
|
|
|
|
+import com.owncloud.android.utils.EncryptionUtils
|
|
|
|
+import com.owncloud.android.utils.theme.ViewThemeUtils
|
|
|
|
+import java.io.IOException
|
|
|
|
+import java.lang.ref.WeakReference
|
|
|
|
+import java.util.Arrays
|
|
|
|
+import javax.inject.Inject
|
|
|
|
|
|
/*
|
|
/*
|
|
* Dialog to setup encryption
|
|
* Dialog to setup encryption
|
|
*/
|
|
*/
|
|
-public class SetupEncryptionDialogFragment extends DialogFragment implements Injectable {
|
|
|
|
-
|
|
|
|
- public static final String SUCCESS = "SUCCESS";
|
|
|
|
- public static final int SETUP_ENCRYPTION_RESULT_CODE = 101;
|
|
|
|
- public static final int SETUP_ENCRYPTION_REQUEST_CODE = 100;
|
|
|
|
- public static final String SETUP_ENCRYPTION_DIALOG_TAG = "SETUP_ENCRYPTION_DIALOG_TAG";
|
|
|
|
- public static final String ARG_POSITION = "ARG_POSITION";
|
|
|
|
-
|
|
|
|
- public static final String RESULT_REQUEST_KEY = "RESULT_REQUEST";
|
|
|
|
- public static final String RESULT_KEY_CANCELLED = "IS_CANCELLED";
|
|
|
|
-
|
|
|
|
- private static final String ARG_USER = "ARG_USER";
|
|
|
|
- private static final String TAG = SetupEncryptionDialogFragment.class.getSimpleName();
|
|
|
|
-
|
|
|
|
- private static final String KEY_CREATED = "KEY_CREATED";
|
|
|
|
- private static final String KEY_EXISTING_USED = "KEY_EXISTING_USED";
|
|
|
|
- private static final String KEY_FAILED = "KEY_FAILED";
|
|
|
|
- private static final String KEY_GENERATE = "KEY_GENERATE";
|
|
|
|
-
|
|
|
|
- @Inject ViewThemeUtils viewThemeUtils;
|
|
|
|
-
|
|
|
|
- private User user;
|
|
|
|
- private ArbitraryDataProvider arbitraryDataProvider;
|
|
|
|
- private Button positiveButton;
|
|
|
|
- private Button neutralButton;
|
|
|
|
- private DownloadKeysAsyncTask task;
|
|
|
|
- private String keyResult;
|
|
|
|
- private ArrayList<String> keyWords;
|
|
|
|
- private SetupEncryptionDialogBinding binding;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Public factory method to create new SetupEncryptionDialogFragment instance
|
|
|
|
- *
|
|
|
|
- * @return Dialog ready to show.
|
|
|
|
- */
|
|
|
|
- public static SetupEncryptionDialogFragment newInstance(User user, int position) {
|
|
|
|
- SetupEncryptionDialogFragment fragment = new SetupEncryptionDialogFragment();
|
|
|
|
- Bundle args = new Bundle();
|
|
|
|
- args.putParcelable(ARG_USER, user);
|
|
|
|
- args.putInt(ARG_POSITION, position);
|
|
|
|
- fragment.setArguments(args);
|
|
|
|
- return fragment;
|
|
|
|
- }
|
|
|
|
|
|
+class SetupEncryptionDialogFragment : DialogFragment(), Injectable {
|
|
|
|
+
|
|
|
|
+ @JvmField
|
|
|
|
+ @Inject
|
|
|
|
+ var viewThemeUtils: ViewThemeUtils? = null
|
|
|
|
+
|
|
|
|
+ private var user: User? = null
|
|
|
|
+ private var arbitraryDataProvider: ArbitraryDataProvider? = null
|
|
|
|
+ private var positiveButton: MaterialButton? = null
|
|
|
|
+ private var negativeButton: MaterialButton? = null
|
|
|
|
+ private var task: DownloadKeysAsyncTask? = null
|
|
|
|
+ private var keyResult: String? = null
|
|
|
|
+ private var keyWords: ArrayList<String>? = null
|
|
|
|
+
|
|
|
|
+ private lateinit var binding: SetupEncryptionDialogBinding
|
|
|
|
+
|
|
|
|
+ override fun onStart() {
|
|
|
|
+ super.onStart()
|
|
|
|
|
|
- @Override
|
|
|
|
- public void onStart() {
|
|
|
|
- super.onStart();
|
|
|
|
|
|
+ setupAlertDialog()
|
|
|
|
+ executeTask()
|
|
|
|
+ }
|
|
|
|
|
|
- AlertDialog alertDialog = (AlertDialog) getDialog();
|
|
|
|
|
|
+ private fun setupAlertDialog() {
|
|
|
|
+ val alertDialog = dialog as AlertDialog?
|
|
|
|
|
|
if (alertDialog != null) {
|
|
if (alertDialog != null) {
|
|
- positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
|
|
|
- neutralButton = alertDialog.getButton(AlertDialog.BUTTON_NEUTRAL);
|
|
|
|
- viewThemeUtils.platform.colorTextButtons(positiveButton, neutralButton);
|
|
|
|
|
|
+ positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) as MaterialButton?
|
|
|
|
+ negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) as MaterialButton?
|
|
|
|
+
|
|
|
|
+ if (positiveButton != null) {
|
|
|
|
+ viewThemeUtils?.material?.colorMaterialButtonPrimaryTonal(positiveButton!!)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (negativeButton != null) {
|
|
|
|
+ viewThemeUtils?.material?.colorMaterialButtonPrimaryBorderless(negativeButton!!)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- task = new DownloadKeysAsyncTask(requireContext());
|
|
|
|
- task.execute();
|
|
|
|
|
|
+ private fun executeTask() {
|
|
|
|
+ task = DownloadKeysAsyncTask(requireContext())
|
|
|
|
+ task?.execute()
|
|
}
|
|
}
|
|
|
|
|
|
- @NonNull
|
|
|
|
- @Override
|
|
|
|
- public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
|
|
- if (getArguments() == null) {
|
|
|
|
- throw new IllegalStateException("Arguments may not be null");
|
|
|
|
|
|
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
|
|
+ checkNotNull(arguments) { "Arguments may not be null" }
|
|
|
|
+
|
|
|
|
+ user = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
|
|
+ requireArguments().getParcelable(ARG_USER, User::class.java)
|
|
|
|
+ } else {
|
|
|
|
+ @Suppress("DEPRECATION")
|
|
|
|
+ requireArguments().getParcelable(ARG_USER)
|
|
}
|
|
}
|
|
- user = getArguments().getParcelable(ARG_USER);
|
|
|
|
|
|
|
|
if (savedInstanceState != null) {
|
|
if (savedInstanceState != null) {
|
|
- keyWords = savedInstanceState.getStringArrayList(MNEMONIC);
|
|
|
|
|
|
+ keyWords = savedInstanceState.getStringArrayList(EncryptionUtils.MNEMONIC)
|
|
}
|
|
}
|
|
|
|
|
|
- arbitraryDataProvider = new ArbitraryDataProviderImpl(getContext());
|
|
|
|
|
|
+ arbitraryDataProvider = ArbitraryDataProviderImpl(context)
|
|
|
|
|
|
// Inflate the layout for the dialog
|
|
// Inflate the layout for the dialog
|
|
- LayoutInflater inflater = requireActivity().getLayoutInflater();
|
|
|
|
- binding = SetupEncryptionDialogBinding.inflate(inflater, null, false);
|
|
|
|
|
|
+ val inflater = requireActivity().layoutInflater
|
|
|
|
+ binding = SetupEncryptionDialogBinding.inflate(inflater, null, false)
|
|
|
|
|
|
// Setup layout
|
|
// Setup layout
|
|
- viewThemeUtils.material.colorTextInputLayout(binding.encryptionPasswordInputContainer);
|
|
|
|
|
|
+ viewThemeUtils?.material?.colorTextInputLayout(binding.encryptionPasswordInputContainer)
|
|
|
|
|
|
- return createDialog(binding.getRoot());
|
|
|
|
|
|
+ return createDialog(binding.root)
|
|
}
|
|
}
|
|
|
|
|
|
- @NonNull
|
|
|
|
- private Dialog createDialog(View v) {
|
|
|
|
- MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(v.getContext());
|
|
|
|
- builder.setView(v).setPositiveButton(R.string.common_ok, null)
|
|
|
|
- .setNeutralButton(R.string.common_cancel, (dialog, which) -> {
|
|
|
|
- dialog.cancel();
|
|
|
|
- })
|
|
|
|
- .setTitle(R.string.end_to_end_encryption_title);
|
|
|
|
-
|
|
|
|
- viewThemeUtils.dialog.colorMaterialAlertDialogBackground(v.getContext(), builder);
|
|
|
|
-
|
|
|
|
- Dialog dialog = builder.create();
|
|
|
|
- dialog.setCanceledOnTouchOutside(false);
|
|
|
|
-
|
|
|
|
- dialog.setOnShowListener(dialog1 -> {
|
|
|
|
-
|
|
|
|
- Button button = ((AlertDialog) dialog1).getButton(AlertDialog.BUTTON_POSITIVE);
|
|
|
|
- button.setOnClickListener(view -> {
|
|
|
|
- switch (keyResult) {
|
|
|
|
- case KEY_CREATED:
|
|
|
|
- Log_OC.d(TAG, "New keys generated and stored.");
|
|
|
|
-
|
|
|
|
- dialog1.dismiss();
|
|
|
|
-
|
|
|
|
- notifyResult();
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case KEY_EXISTING_USED:
|
|
|
|
- Log_OC.d(TAG, "Decrypt private key");
|
|
|
|
|
|
+ private fun createDialog(v: View): Dialog {
|
|
|
|
|
|
- binding.encryptionStatus.setText(R.string.end_to_end_encryption_decrypting);
|
|
|
|
|
|
+ val builder = MaterialAlertDialogBuilder(v.context)
|
|
|
|
|
|
- try {
|
|
|
|
- String privateKey = task.get();
|
|
|
|
- String mnemonicUnchanged = binding.encryptionPasswordInput.getText().toString();
|
|
|
|
- String mnemonic = binding.encryptionPasswordInput.getText().toString().replaceAll("\\s", "")
|
|
|
|
- .toLowerCase(Locale.ROOT);
|
|
|
|
- String decryptedPrivateKey = EncryptionUtils.decryptPrivateKey(privateKey,
|
|
|
|
- mnemonic);
|
|
|
|
|
|
+ builder
|
|
|
|
+ .setView(v)
|
|
|
|
+ .setPositiveButton(R.string.common_ok, null)
|
|
|
|
+ .setNegativeButton(R.string.common_cancel) { dialog: DialogInterface, _: Int -> dialog.cancel() }
|
|
|
|
+ .setTitle(R.string.end_to_end_encryption_title)
|
|
|
|
|
|
- arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
|
|
|
|
- EncryptionUtils.PRIVATE_KEY, decryptedPrivateKey);
|
|
|
|
|
|
+ viewThemeUtils?.dialog?.colorMaterialAlertDialogBackground(v.context, builder)
|
|
|
|
|
|
- dialog1.dismiss();
|
|
|
|
- Log_OC.d(TAG, "Private key successfully decrypted and stored");
|
|
|
|
-
|
|
|
|
- arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
|
|
|
|
- EncryptionUtils.MNEMONIC,
|
|
|
|
- mnemonicUnchanged);
|
|
|
|
-
|
|
|
|
- // check if private key and public key match
|
|
|
|
- String publicKey = arbitraryDataProvider.getValue(user.getAccountName(),
|
|
|
|
- EncryptionUtils.PUBLIC_KEY);
|
|
|
|
-
|
|
|
|
- byte[] key1 = generateKey();
|
|
|
|
- String base64encodedKey = encodeBytesToBase64String(key1);
|
|
|
|
-
|
|
|
|
- String encryptedString = EncryptionUtils.encryptStringAsymmetric(base64encodedKey,
|
|
|
|
- publicKey);
|
|
|
|
- String decryptedString = decryptStringAsymmetric(encryptedString,
|
|
|
|
- decryptedPrivateKey);
|
|
|
|
-
|
|
|
|
- byte[] key2 = decodeStringToBase64Bytes(decryptedString);
|
|
|
|
-
|
|
|
|
- if (!Arrays.equals(key1, key2)) {
|
|
|
|
- throw new Exception("Keys do not match");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- notifyResult();
|
|
|
|
-
|
|
|
|
- } catch (Exception e) {
|
|
|
|
- binding.encryptionStatus.setText(R.string.end_to_end_encryption_wrong_password);
|
|
|
|
- Log_OC.d(TAG, "Error while decrypting private key: " + e.getMessage());
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
|
|
+ val dialog: Dialog = builder.create()
|
|
|
|
+ dialog.setCanceledOnTouchOutside(false)
|
|
|
|
+ dialog.setOnShowListener { dialog1: DialogInterface ->
|
|
|
|
+ val button = (dialog1 as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)
|
|
|
|
+ button.setOnClickListener { positiveButtonOnClick(dialog) }
|
|
|
|
+ }
|
|
|
|
|
|
- case KEY_GENERATE:
|
|
|
|
- binding.encryptionPassphrase.setVisibility(View.GONE);
|
|
|
|
- positiveButton.setVisibility(View.GONE);
|
|
|
|
- neutralButton.setVisibility(View.GONE);
|
|
|
|
- getDialog().setTitle(R.string.end_to_end_encryption_storing_keys);
|
|
|
|
|
|
+ return dialog
|
|
|
|
+ }
|
|
|
|
|
|
- GenerateNewKeysAsyncTask newKeysTask = new GenerateNewKeysAsyncTask(requireContext());
|
|
|
|
- newKeysTask.execute();
|
|
|
|
- break;
|
|
|
|
|
|
+ private fun positiveButtonOnClick(dialog: DialogInterface) {
|
|
|
|
+ when (keyResult) {
|
|
|
|
+ KEY_CREATED -> {
|
|
|
|
+ Log_OC.d(TAG, "New keys generated and stored.")
|
|
|
|
+ dialog.dismiss()
|
|
|
|
+ notifyResult()
|
|
|
|
+ }
|
|
|
|
+ KEY_EXISTING_USED -> {
|
|
|
|
+ decryptPrivateKey(dialog)
|
|
|
|
+ }
|
|
|
|
|
|
- default:
|
|
|
|
- dialog1.dismiss();
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
- return dialog;
|
|
|
|
|
|
+ KEY_GENERATE -> {
|
|
|
|
+ generateKey()
|
|
|
|
+ }
|
|
|
|
+ else -> dialog.dismiss()
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- private void notifyResult() {
|
|
|
|
- final Fragment targetFragment = getTargetFragment();
|
|
|
|
- if (targetFragment != null) {
|
|
|
|
- targetFragment.onActivityResult(getTargetRequestCode(),
|
|
|
|
- SETUP_ENCRYPTION_RESULT_CODE, getResultIntent());
|
|
|
|
|
|
+ private fun decryptPrivateKey(dialog: DialogInterface) {
|
|
|
|
+ Log_OC.d(TAG, "Decrypt private key")
|
|
|
|
+ binding.encryptionStatus.setText(R.string.end_to_end_encryption_decrypting)
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ val privateKey = task?.get()
|
|
|
|
+ val mnemonicUnchanged = binding.encryptionPasswordInput.text.toString()
|
|
|
|
+ val mnemonic =
|
|
|
|
+ binding.encryptionPasswordInput.text.toString().replace("\\s".toRegex(), "")
|
|
|
|
+ .lowercase()
|
|
|
|
+ val decryptedPrivateKey = EncryptionUtils.decryptPrivateKey(
|
|
|
|
+ privateKey,
|
|
|
|
+ mnemonic
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ val accountName = user?.accountName ?: return
|
|
|
|
+
|
|
|
|
+ arbitraryDataProvider?.storeOrUpdateKeyValue(
|
|
|
|
+ accountName,
|
|
|
|
+ EncryptionUtils.PRIVATE_KEY, decryptedPrivateKey
|
|
|
|
+ )
|
|
|
|
+ dialog.dismiss()
|
|
|
|
+
|
|
|
|
+ Log_OC.d(TAG, "Private key successfully decrypted and stored")
|
|
|
|
+
|
|
|
|
+ arbitraryDataProvider?.storeOrUpdateKeyValue(
|
|
|
|
+ accountName,
|
|
|
|
+ EncryptionUtils.MNEMONIC,
|
|
|
|
+ mnemonicUnchanged
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ // check if private key and public key match
|
|
|
|
+ val publicKey = arbitraryDataProvider?.getValue(
|
|
|
|
+ accountName,
|
|
|
|
+ EncryptionUtils.PUBLIC_KEY
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ val firstKey = EncryptionUtils.generateKey()
|
|
|
|
+ val base64encodedKey = EncryptionUtils.encodeBytesToBase64String(firstKey)
|
|
|
|
+ val encryptedString = EncryptionUtils.encryptStringAsymmetric(
|
|
|
|
+ base64encodedKey,
|
|
|
|
+ publicKey
|
|
|
|
+ )
|
|
|
|
+ val decryptedString = EncryptionUtils.decryptStringAsymmetric(
|
|
|
|
+ encryptedString,
|
|
|
|
+ decryptedPrivateKey
|
|
|
|
+ )
|
|
|
|
+ val secondKey = EncryptionUtils.decodeStringToBase64Bytes(decryptedString)
|
|
|
|
+
|
|
|
|
+ if (!Arrays.equals(firstKey, secondKey)) {
|
|
|
|
+ throw Exception("Keys do not match")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ notifyResult()
|
|
|
|
+ } catch (e: Exception) {
|
|
|
|
+ binding.encryptionStatus.setText(R.string.end_to_end_encryption_wrong_password)
|
|
|
|
+ Log_OC.d(TAG, "Error while decrypting private key: " + e.message)
|
|
}
|
|
}
|
|
- getParentFragmentManager().setFragmentResult(RESULT_REQUEST_KEY, getResultBundle());
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- @NonNull
|
|
|
|
- private Intent getResultIntent() {
|
|
|
|
- Intent intentCreated = new Intent();
|
|
|
|
- intentCreated.putExtra(SUCCESS, true);
|
|
|
|
- intentCreated.putExtra(ARG_POSITION, getArguments().getInt(ARG_POSITION));
|
|
|
|
- return intentCreated;
|
|
|
|
|
|
+ private fun generateKey() {
|
|
|
|
+ binding.encryptionPassphrase.visibility = View.GONE
|
|
|
|
+ positiveButton?.visibility = View.GONE
|
|
|
|
+ negativeButton?.visibility = View.GONE
|
|
|
|
+
|
|
|
|
+ dialog?.setTitle(R.string.end_to_end_encryption_storing_keys)
|
|
|
|
+
|
|
|
|
+ val newKeysTask = GenerateNewKeysAsyncTask(requireContext())
|
|
|
|
+ newKeysTask.execute()
|
|
}
|
|
}
|
|
|
|
|
|
- @NonNull
|
|
|
|
- private Bundle getResultBundle() {
|
|
|
|
- final Bundle bundle = new Bundle();
|
|
|
|
- bundle.putBoolean(SUCCESS, true);
|
|
|
|
- bundle.putInt(ARG_POSITION, getArguments().getInt(ARG_POSITION));
|
|
|
|
- return bundle;
|
|
|
|
|
|
+ private fun notifyResult() {
|
|
|
|
+ val targetFragment = targetFragment
|
|
|
|
+ targetFragment?.onActivityResult(
|
|
|
|
+ targetRequestCode,
|
|
|
|
+ SETUP_ENCRYPTION_RESULT_CODE, resultIntent
|
|
|
|
+ )
|
|
|
|
+ parentFragmentManager.setFragmentResult(RESULT_REQUEST_KEY, resultBundle)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private val resultIntent: Intent
|
|
|
|
+ get() {
|
|
|
|
+ val intentCreated = Intent()
|
|
|
|
+ intentCreated.putExtra(SUCCESS, true)
|
|
|
|
+ intentCreated.putExtra(ARG_POSITION, requireArguments().getInt(ARG_POSITION))
|
|
|
|
+ return intentCreated
|
|
|
|
+ }
|
|
|
|
+ private val resultBundle: Bundle
|
|
|
|
+ get() {
|
|
|
|
+ val bundle = Bundle()
|
|
|
|
+ bundle.putBoolean(SUCCESS, true)
|
|
|
|
+ bundle.putInt(ARG_POSITION, requireArguments().getInt(ARG_POSITION))
|
|
|
|
+ return bundle
|
|
|
|
+ }
|
|
|
|
|
|
- @Override
|
|
|
|
- public void onCancel(@NonNull DialogInterface dialog) {
|
|
|
|
- super.onCancel(dialog);
|
|
|
|
- final Bundle bundle = new Bundle();
|
|
|
|
- bundle.putBoolean(RESULT_KEY_CANCELLED, true);
|
|
|
|
- getParentFragmentManager().setFragmentResult(RESULT_REQUEST_KEY, bundle);
|
|
|
|
|
|
+ override fun onCancel(dialog: DialogInterface) {
|
|
|
|
+ super.onCancel(dialog)
|
|
|
|
+ val bundle = Bundle()
|
|
|
|
+ bundle.putBoolean(RESULT_KEY_CANCELLED, true)
|
|
|
|
+ parentFragmentManager.setFragmentResult(RESULT_REQUEST_KEY, bundle)
|
|
}
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
|
- public void onSaveInstanceState(@NonNull Bundle outState) {
|
|
|
|
- outState.putStringArrayList(MNEMONIC, keyWords);
|
|
|
|
- super.onSaveInstanceState(outState);
|
|
|
|
|
|
+ override fun onSaveInstanceState(outState: Bundle) {
|
|
|
|
+ outState.putStringArrayList(EncryptionUtils.MNEMONIC, keyWords)
|
|
|
|
+ super.onSaveInstanceState(outState)
|
|
}
|
|
}
|
|
|
|
|
|
- public class DownloadKeysAsyncTask extends AsyncTask<Void, Void, String> {
|
|
|
|
- private final WeakReference<Context> mWeakContext;
|
|
|
|
-
|
|
|
|
- public DownloadKeysAsyncTask(Context context) {
|
|
|
|
- mWeakContext = new WeakReference<>(context);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- protected void onPreExecute() {
|
|
|
|
- super.onPreExecute();
|
|
|
|
|
|
+ @SuppressLint("StaticFieldLeak")
|
|
|
|
+ inner class DownloadKeysAsyncTask(context: Context) : AsyncTask<Void?, Void?, String?>() {
|
|
|
|
+ private val mWeakContext: WeakReference<Context>
|
|
|
|
|
|
- binding.encryptionStatus.setText(R.string.end_to_end_encryption_retrieving_keys);
|
|
|
|
- positiveButton.setVisibility(View.INVISIBLE);
|
|
|
|
|
|
+ init {
|
|
|
|
+ mWeakContext = WeakReference(context)
|
|
}
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
|
- protected String doInBackground(Void... voids) {
|
|
|
|
|
|
+ @Deprecated("Deprecated in Java")
|
|
|
|
+ override fun doInBackground(vararg params: Void?): String? {
|
|
// fetch private/public key
|
|
// fetch private/public key
|
|
// if available
|
|
// if available
|
|
// - store public key
|
|
// - store public key
|
|
// - decrypt private key, store unencrypted private key in database
|
|
// - decrypt private key, store unencrypted private key in database
|
|
-
|
|
|
|
- Context context = mWeakContext.get();
|
|
|
|
- GetPublicKeyOperation publicKeyOperation = new GetPublicKeyOperation();
|
|
|
|
- if (user != null) {
|
|
|
|
- RemoteOperationResult<String> publicKeyResult = publicKeyOperation.execute(user, context);
|
|
|
|
-
|
|
|
|
- if (publicKeyResult.isSuccess()) {
|
|
|
|
- Log_OC.d(TAG, "public key successful downloaded for " + user.getAccountName());
|
|
|
|
-
|
|
|
|
- String publicKeyFromServer = publicKeyResult.getResultData();
|
|
|
|
- if (arbitraryDataProvider != null) {
|
|
|
|
- arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
|
|
|
|
- EncryptionUtils.PUBLIC_KEY,
|
|
|
|
- publicKeyFromServer);
|
|
|
|
- } else {
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
|
|
+ val context = mWeakContext.get()
|
|
|
|
+ val publicKeyOperation = GetPublicKeyOperation()
|
|
|
|
+ val user = user ?: return null
|
|
|
|
+
|
|
|
|
+ val publicKeyResult = publicKeyOperation.execute(user, context)
|
|
|
|
+
|
|
|
|
+ if (publicKeyResult.isSuccess) {
|
|
|
|
+ Log_OC.d(TAG, "public key successful downloaded for " + user.accountName)
|
|
|
|
+
|
|
|
|
+ val publicKeyFromServer = publicKeyResult.resultData
|
|
|
|
+ if (arbitraryDataProvider != null) {
|
|
|
|
+ arbitraryDataProvider?.storeOrUpdateKeyValue(
|
|
|
|
+ user.accountName,
|
|
|
|
+ EncryptionUtils.PUBLIC_KEY,
|
|
|
|
+ publicKeyFromServer
|
|
|
|
+ )
|
|
} else {
|
|
} else {
|
|
- return null;
|
|
|
|
|
|
+ return null
|
|
}
|
|
}
|
|
|
|
+ } else {
|
|
|
|
+ return null
|
|
|
|
+ }
|
|
|
|
|
|
- RemoteOperationResult<com.owncloud.android.lib.ocs.responses.PrivateKey> privateKeyResult =
|
|
|
|
- new GetPrivateKeyOperation().execute(user, context);
|
|
|
|
|
|
+ val privateKeyResult = GetPrivateKeyOperation().execute(user, context)
|
|
|
|
+ if (privateKeyResult.isSuccess) {
|
|
|
|
+ Log_OC.d(TAG, "private key successful downloaded for " + user!!.accountName)
|
|
|
|
+ keyResult = KEY_EXISTING_USED
|
|
|
|
+ return privateKeyResult.resultData.getKey()
|
|
|
|
+ }
|
|
|
|
|
|
- if (privateKeyResult.isSuccess()) {
|
|
|
|
- Log_OC.d(TAG, "private key successful downloaded for " + user.getAccountName());
|
|
|
|
|
|
+ return null
|
|
|
|
+ }
|
|
|
|
|
|
- keyResult = KEY_EXISTING_USED;
|
|
|
|
- return privateKeyResult.getResultData().getKey();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
|
|
+ @Deprecated("Deprecated in Java")
|
|
|
|
+ override fun onPreExecute() {
|
|
|
|
+ super.onPreExecute()
|
|
|
|
+
|
|
|
|
+ binding.encryptionStatus.setText(R.string.end_to_end_encryption_retrieving_keys)
|
|
|
|
+ positiveButton?.visibility = View.INVISIBLE
|
|
}
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
|
- protected void onPostExecute(String privateKey) {
|
|
|
|
- super.onPostExecute(privateKey);
|
|
|
|
|
|
+ @Deprecated("Deprecated in Java")
|
|
|
|
+ override fun onPostExecute(privateKey: String?) {
|
|
|
|
+ super.onPostExecute(privateKey)
|
|
|
|
|
|
- Context context = mWeakContext.get();
|
|
|
|
|
|
+ val context = mWeakContext.get()
|
|
if (context == null) {
|
|
if (context == null) {
|
|
- Log_OC.e(TAG, "Context lost after fetching private keys.");
|
|
|
|
- return;
|
|
|
|
|
|
+ Log_OC.e(TAG, "Context lost after fetching private keys.")
|
|
|
|
+ return
|
|
}
|
|
}
|
|
-
|
|
|
|
if (privateKey == null) {
|
|
if (privateKey == null) {
|
|
// first show info
|
|
// first show info
|
|
try {
|
|
try {
|
|
- if (keyWords == null || keyWords.isEmpty()) {
|
|
|
|
- keyWords = EncryptionUtils.getRandomWords(12, context);
|
|
|
|
|
|
+ if (keyWords == null || keyWords!!.isEmpty()) {
|
|
|
|
+ keyWords = EncryptionUtils.getRandomWords(12, context)
|
|
}
|
|
}
|
|
- showMnemonicInfo();
|
|
|
|
- } catch (IOException e) {
|
|
|
|
- binding.encryptionStatus.setText(R.string.common_error);
|
|
|
|
|
|
+ showMnemonicInfo()
|
|
|
|
+ } catch (e: IOException) {
|
|
|
|
+ binding.encryptionStatus.setText(R.string.common_error)
|
|
}
|
|
}
|
|
- } else if (!privateKey.isEmpty()) {
|
|
|
|
- binding.encryptionStatus.setText(R.string.end_to_end_encryption_enter_password);
|
|
|
|
- binding.encryptionPasswordInputContainer.setVisibility(View.VISIBLE);
|
|
|
|
- positiveButton.setVisibility(View.VISIBLE);
|
|
|
|
|
|
+ } else if (privateKey.isNotEmpty()) {
|
|
|
|
+ binding.encryptionStatus.setText(R.string.end_to_end_encryption_enter_password)
|
|
|
|
+ binding.encryptionPasswordInputContainer.visibility = View.VISIBLE
|
|
|
|
+ positiveButton?.visibility = View.VISIBLE
|
|
} else {
|
|
} else {
|
|
- Log_OC.e(TAG, "Got empty private key string");
|
|
|
|
|
|
+ Log_OC.e(TAG, "Got empty private key string")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- public class GenerateNewKeysAsyncTask extends AsyncTask<Void, Void, String> {
|
|
|
|
|
|
+ @SuppressLint("StaticFieldLeak")
|
|
|
|
+ inner class GenerateNewKeysAsyncTask(context: Context) : AsyncTask<Void?, Void?, String>() {
|
|
|
|
+ private val mWeakContext: WeakReference<Context>
|
|
|
|
|
|
- private final WeakReference<Context> mWeakContext;
|
|
|
|
-
|
|
|
|
- public GenerateNewKeysAsyncTask(Context context) {
|
|
|
|
- mWeakContext = new WeakReference<>(context);
|
|
|
|
|
|
+ init {
|
|
|
|
+ mWeakContext = WeakReference(context)
|
|
}
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
|
- protected void onPreExecute() {
|
|
|
|
- super.onPreExecute();
|
|
|
|
-
|
|
|
|
- binding.encryptionStatus.setText(R.string.end_to_end_encryption_generating_keys);
|
|
|
|
|
|
+ @Deprecated("Deprecated in Java")
|
|
|
|
+ override fun onPreExecute() {
|
|
|
|
+ super.onPreExecute()
|
|
|
|
+ binding.encryptionStatus.setText(R.string.end_to_end_encryption_generating_keys)
|
|
}
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
|
- protected String doInBackground(Void... voids) {
|
|
|
|
|
|
+ @Deprecated("Deprecated in Java")
|
|
|
|
+ override fun doInBackground(vararg voids: Void?): String {
|
|
// - create CSR, push to server, store returned public key in database
|
|
// - create CSR, push to server, store returned public key in database
|
|
// - encrypt private key, push key to server, store unencrypted private key in database
|
|
// - encrypt private key, push key to server, store unencrypted private key in database
|
|
-
|
|
|
|
try {
|
|
try {
|
|
- Context context = mWeakContext.get();
|
|
|
|
-
|
|
|
|
- String publicKeyString;
|
|
|
|
|
|
+ val context = mWeakContext.get()
|
|
|
|
+ val publicKeyString: String
|
|
|
|
|
|
// Create public/private key pair
|
|
// Create public/private key pair
|
|
- KeyPair keyPair = EncryptionUtils.generateKeyPair();
|
|
|
|
|
|
+ val keyPair = EncryptionUtils.generateKeyPair()
|
|
|
|
|
|
// create CSR
|
|
// create CSR
|
|
- AccountManager accountManager = AccountManager.get(context);
|
|
|
|
- String userId = accountManager.getUserData(user.toPlatformAccount(), AccountUtils.Constants.KEY_USER_ID);
|
|
|
|
- String urlEncoded = CsrHelper.generateCsrPemEncodedString(keyPair, userId);
|
|
|
|
|
|
+ val accountManager = AccountManager.get(context)
|
|
|
|
+ val user = user ?: return ""
|
|
|
|
|
|
- SendCSROperation operation = new SendCSROperation(urlEncoded);
|
|
|
|
- RemoteOperationResult result = operation.execute(user, context);
|
|
|
|
-
|
|
|
|
- if (result.isSuccess()) {
|
|
|
|
- publicKeyString = (String) result.getData().get(0);
|
|
|
|
|
|
+ val userId = accountManager.getUserData(user.toPlatformAccount(), AccountUtils.Constants.KEY_USER_ID)
|
|
|
|
+ val urlEncoded = CsrHelper.generateCsrPemEncodedString(keyPair, userId)
|
|
|
|
+ val operation = SendCSROperation(urlEncoded)
|
|
|
|
+ val result = operation.execute(user, context)
|
|
|
|
|
|
|
|
+ if (result.isSuccess) {
|
|
|
|
+ publicKeyString = result.data[0] as String
|
|
if (!EncryptionUtils.isMatchingKeys(keyPair, publicKeyString)) {
|
|
if (!EncryptionUtils.isMatchingKeys(keyPair, publicKeyString)) {
|
|
- throw new RuntimeException("Wrong CSR returned");
|
|
|
|
|
|
+ throw RuntimeException("Wrong CSR returned")
|
|
}
|
|
}
|
|
-
|
|
|
|
- Log_OC.d(TAG, "public key success");
|
|
|
|
|
|
+ Log_OC.d(TAG, "public key success")
|
|
} else {
|
|
} else {
|
|
- keyResult = KEY_FAILED;
|
|
|
|
- return "";
|
|
|
|
|
|
+ keyResult = KEY_FAILED
|
|
|
|
+ return ""
|
|
}
|
|
}
|
|
|
|
|
|
- PrivateKey privateKey = keyPair.getPrivate();
|
|
|
|
- String privateKeyString = EncryptionUtils.encodeBytesToBase64String(privateKey.getEncoded());
|
|
|
|
- String privatePemKeyString = EncryptionUtils.privateKeyToPEM(privateKey);
|
|
|
|
- String encryptedPrivateKey = EncryptionUtils.encryptPrivateKey(privatePemKeyString,
|
|
|
|
- generateMnemonicString(false));
|
|
|
|
|
|
+ val privateKey = keyPair.private
|
|
|
|
+ val privateKeyString = EncryptionUtils.encodeBytesToBase64String(privateKey.encoded)
|
|
|
|
+ val privatePemKeyString = EncryptionUtils.privateKeyToPEM(privateKey)
|
|
|
|
+ val encryptedPrivateKey = EncryptionUtils.encryptPrivateKey(
|
|
|
|
+ privatePemKeyString,
|
|
|
|
+ generateMnemonicString(false)
|
|
|
|
+ )
|
|
|
|
|
|
// upload encryptedPrivateKey
|
|
// upload encryptedPrivateKey
|
|
- StorePrivateKeyOperation storePrivateKeyOperation = new StorePrivateKeyOperation(encryptedPrivateKey);
|
|
|
|
- RemoteOperationResult storePrivateKeyResult = storePrivateKeyOperation.execute(user, context);
|
|
|
|
-
|
|
|
|
- if (storePrivateKeyResult.isSuccess()) {
|
|
|
|
- Log_OC.d(TAG, "private key success");
|
|
|
|
-
|
|
|
|
- arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
|
|
|
|
- EncryptionUtils.PRIVATE_KEY,
|
|
|
|
- privateKeyString);
|
|
|
|
- arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
|
|
|
|
- EncryptionUtils.PUBLIC_KEY,
|
|
|
|
- publicKeyString);
|
|
|
|
- arbitraryDataProvider.storeOrUpdateKeyValue(user.getAccountName(),
|
|
|
|
- EncryptionUtils.MNEMONIC,
|
|
|
|
- generateMnemonicString(true));
|
|
|
|
-
|
|
|
|
- keyResult = KEY_CREATED;
|
|
|
|
- return (String) storePrivateKeyResult.getData().get(0);
|
|
|
|
|
|
+ val storePrivateKeyOperation = StorePrivateKeyOperation(encryptedPrivateKey)
|
|
|
|
+ val storePrivateKeyResult = storePrivateKeyOperation.execute(user, context)
|
|
|
|
+ if (storePrivateKeyResult.isSuccess) {
|
|
|
|
+ Log_OC.d(TAG, "private key success")
|
|
|
|
+ arbitraryDataProvider!!.storeOrUpdateKeyValue(
|
|
|
|
+ user.accountName,
|
|
|
|
+ EncryptionUtils.PRIVATE_KEY,
|
|
|
|
+ privateKeyString
|
|
|
|
+ )
|
|
|
|
+ arbitraryDataProvider!!.storeOrUpdateKeyValue(
|
|
|
|
+ user.accountName,
|
|
|
|
+ EncryptionUtils.PUBLIC_KEY,
|
|
|
|
+ publicKeyString
|
|
|
|
+ )
|
|
|
|
+ arbitraryDataProvider!!.storeOrUpdateKeyValue(
|
|
|
|
+ user.accountName,
|
|
|
|
+ EncryptionUtils.MNEMONIC,
|
|
|
|
+ generateMnemonicString(true)
|
|
|
|
+ )
|
|
|
|
+ keyResult = KEY_CREATED
|
|
|
|
+
|
|
|
|
+ return storePrivateKeyResult.data[0] as String
|
|
} else {
|
|
} else {
|
|
- DeletePublicKeyOperation deletePublicKeyOperation = new DeletePublicKeyOperation();
|
|
|
|
- deletePublicKeyOperation.execute(user, context);
|
|
|
|
|
|
+ val deletePublicKeyOperation = DeletePublicKeyOperation()
|
|
|
|
+ deletePublicKeyOperation.execute(user, context)
|
|
}
|
|
}
|
|
- } catch (Exception e) {
|
|
|
|
- Log_OC.e(TAG, e.getMessage());
|
|
|
|
|
|
+ } catch (e: Exception) {
|
|
|
|
+ Log_OC.e(TAG, e.message)
|
|
}
|
|
}
|
|
-
|
|
|
|
- keyResult = KEY_FAILED;
|
|
|
|
- return "";
|
|
|
|
|
|
+ keyResult = KEY_FAILED
|
|
|
|
+ return ""
|
|
}
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
|
- protected void onPostExecute(String s) {
|
|
|
|
- super.onPostExecute(s);
|
|
|
|
-
|
|
|
|
- Context context = mWeakContext.get();
|
|
|
|
|
|
+ @Deprecated("Deprecated in Java")
|
|
|
|
+ override fun onPostExecute(s: String) {
|
|
|
|
+ super.onPostExecute(s)
|
|
|
|
+ val context = mWeakContext.get()
|
|
if (context == null) {
|
|
if (context == null) {
|
|
- Log_OC.e(TAG, "Context lost after generating new private keys.");
|
|
|
|
- return;
|
|
|
|
|
|
+ Log_OC.e(TAG, "Context lost after generating new private keys.")
|
|
|
|
+ return
|
|
}
|
|
}
|
|
-
|
|
|
|
if (s.isEmpty()) {
|
|
if (s.isEmpty()) {
|
|
- errorSavingKeys();
|
|
|
|
|
|
+ errorSavingKeys()
|
|
} else {
|
|
} else {
|
|
- if (getDialog() == null) {
|
|
|
|
- Log_OC.e(TAG, "Dialog is null cannot proceed further.");
|
|
|
|
- return;
|
|
|
|
|
|
+ if (dialog == null) {
|
|
|
|
+ Log_OC.e(TAG, "Dialog is null cannot proceed further.")
|
|
|
|
+ return
|
|
}
|
|
}
|
|
-
|
|
|
|
- requireDialog().dismiss();
|
|
|
|
- notifyResult();
|
|
|
|
|
|
+ requireDialog().dismiss()
|
|
|
|
+ notifyResult()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private String generateMnemonicString(boolean withWhitespace) {
|
|
|
|
- StringBuilder stringBuilder = new StringBuilder();
|
|
|
|
-
|
|
|
|
- for (String string : keyWords) {
|
|
|
|
- stringBuilder.append(string);
|
|
|
|
|
|
+ private fun generateMnemonicString(withWhitespace: Boolean): String {
|
|
|
|
+ val stringBuilder = StringBuilder()
|
|
|
|
+ for (string in keyWords!!) {
|
|
|
|
+ stringBuilder.append(string)
|
|
if (withWhitespace) {
|
|
if (withWhitespace) {
|
|
- stringBuilder.append(' ');
|
|
|
|
|
|
+ stringBuilder.append(' ')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- return stringBuilder.toString();
|
|
|
|
|
|
+ return stringBuilder.toString()
|
|
}
|
|
}
|
|
|
|
|
|
@VisibleForTesting
|
|
@VisibleForTesting
|
|
- public void showMnemonicInfo() {
|
|
|
|
- if (getDialog() == null) {
|
|
|
|
- Log_OC.e(TAG, "Dialog is null cannot proceed further.");
|
|
|
|
- return;
|
|
|
|
|
|
+ fun showMnemonicInfo() {
|
|
|
|
+ if (dialog == null) {
|
|
|
|
+ Log_OC.e(TAG, "Dialog is null cannot proceed further.")
|
|
|
|
+ return
|
|
}
|
|
}
|
|
- requireDialog().setTitle(R.string.end_to_end_encryption_passphrase_title);
|
|
|
|
-
|
|
|
|
- binding.encryptionStatus.setText(R.string.end_to_end_encryption_keywords_description);
|
|
|
|
- viewThemeUtils.material.colorTextInputLayout(binding.encryptionPasswordInputContainer);
|
|
|
|
-
|
|
|
|
- binding.encryptionPassphrase.setText(generateMnemonicString(true));
|
|
|
|
-
|
|
|
|
- binding.encryptionPassphrase.setVisibility(View.VISIBLE);
|
|
|
|
- positiveButton.setText(R.string.end_to_end_encryption_confirm_button);
|
|
|
|
- positiveButton.setVisibility(View.VISIBLE);
|
|
|
|
-
|
|
|
|
- neutralButton.setVisibility(View.VISIBLE);
|
|
|
|
- viewThemeUtils.platform.colorTextButtons(positiveButton, neutralButton);
|
|
|
|
-
|
|
|
|
- keyResult = KEY_GENERATE;
|
|
|
|
|
|
+ requireDialog().setTitle(R.string.end_to_end_encryption_passphrase_title)
|
|
|
|
+ binding.encryptionStatus.setText(R.string.end_to_end_encryption_keywords_description)
|
|
|
|
+ viewThemeUtils!!.material.colorTextInputLayout(binding.encryptionPasswordInputContainer)
|
|
|
|
+ binding.encryptionPassphrase.text = generateMnemonicString(true)
|
|
|
|
+ binding.encryptionPassphrase.visibility = View.VISIBLE
|
|
|
|
+ positiveButton!!.setText(R.string.end_to_end_encryption_confirm_button)
|
|
|
|
+ positiveButton!!.visibility = View.VISIBLE
|
|
|
|
+ negativeButton!!.visibility = View.VISIBLE
|
|
|
|
+ viewThemeUtils!!.platform.colorTextButtons(positiveButton!!, negativeButton!!)
|
|
|
|
+ keyResult = KEY_GENERATE
|
|
}
|
|
}
|
|
|
|
|
|
@VisibleForTesting
|
|
@VisibleForTesting
|
|
- public void errorSavingKeys() {
|
|
|
|
- if (getDialog() == null) {
|
|
|
|
- Log_OC.e(TAG, "Dialog is null cannot proceed further.");
|
|
|
|
- return;
|
|
|
|
|
|
+ fun errorSavingKeys() {
|
|
|
|
+ if (dialog == null) {
|
|
|
|
+ Log_OC.e(TAG, "Dialog is null cannot proceed further.")
|
|
|
|
+ return
|
|
}
|
|
}
|
|
|
|
|
|
- keyResult = KEY_FAILED;
|
|
|
|
|
|
+ keyResult = KEY_FAILED
|
|
|
|
+ requireDialog().setTitle(R.string.common_error)
|
|
|
|
+ binding.encryptionStatus.setText(R.string.end_to_end_encryption_unsuccessful)
|
|
|
|
+ binding.encryptionPassphrase.visibility = View.GONE
|
|
|
|
+
|
|
|
|
+ positiveButton?.setText(R.string.end_to_end_encryption_dialog_close)
|
|
|
|
+ positiveButton?.visibility = View.VISIBLE
|
|
|
|
|
|
- requireDialog().setTitle(R.string.common_error);
|
|
|
|
- binding.encryptionStatus.setText(R.string.end_to_end_encryption_unsuccessful);
|
|
|
|
- binding.encryptionPassphrase.setVisibility(View.GONE);
|
|
|
|
- positiveButton.setText(R.string.end_to_end_encryption_dialog_close);
|
|
|
|
- positiveButton.setVisibility(View.VISIBLE);
|
|
|
|
- viewThemeUtils.platform.colorTextButtons(positiveButton);
|
|
|
|
|
|
+ if (positiveButton != null) {
|
|
|
|
+ viewThemeUtils?.platform?.colorTextButtons(positiveButton!!)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@VisibleForTesting
|
|
@VisibleForTesting
|
|
- public void setMnemonic(ArrayList<String> keyWords) {
|
|
|
|
- this.keyWords = keyWords;
|
|
|
|
|
|
+ fun setMnemonic(keyWords: ArrayList<String>?) {
|
|
|
|
+ this.keyWords = keyWords
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ companion object {
|
|
|
|
+ const val SUCCESS = "SUCCESS"
|
|
|
|
+ const val SETUP_ENCRYPTION_RESULT_CODE = 101
|
|
|
|
+ const val SETUP_ENCRYPTION_REQUEST_CODE = 100
|
|
|
|
+ const val SETUP_ENCRYPTION_DIALOG_TAG = "SETUP_ENCRYPTION_DIALOG_TAG"
|
|
|
|
+ const val ARG_POSITION = "ARG_POSITION"
|
|
|
|
+ const val RESULT_REQUEST_KEY = "RESULT_REQUEST"
|
|
|
|
+ const val RESULT_KEY_CANCELLED = "IS_CANCELLED"
|
|
|
|
+ private const val ARG_USER = "ARG_USER"
|
|
|
|
+ private val TAG = SetupEncryptionDialogFragment::class.java.simpleName
|
|
|
|
+ private const val KEY_CREATED = "KEY_CREATED"
|
|
|
|
+ private const val KEY_EXISTING_USED = "KEY_EXISTING_USED"
|
|
|
|
+ private const val KEY_FAILED = "KEY_FAILED"
|
|
|
|
+ private const val KEY_GENERATE = "KEY_GENERATE"
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Public factory method to create new SetupEncryptionDialogFragment instance
|
|
|
|
+ *
|
|
|
|
+ * @return Dialog ready to show.
|
|
|
|
+ */
|
|
|
|
+ @JvmStatic
|
|
|
|
+ fun newInstance(user: User?, position: Int): SetupEncryptionDialogFragment {
|
|
|
|
+ val fragment = SetupEncryptionDialogFragment()
|
|
|
|
+ val args = Bundle()
|
|
|
|
+ args.putParcelable(ARG_USER, user)
|
|
|
|
+ args.putInt(ARG_POSITION, position)
|
|
|
|
+ fragment.arguments = args
|
|
|
|
+ return fragment
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
+}
|