aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/com/zeapo/pwdstore/sshkeygen
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/sshkeygen')
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt69
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt35
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt90
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt77
4 files changed, 271 insertions, 0 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt
new file mode 100644
index 00000000..5f27090f
--- /dev/null
+++ b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/ShowSshKeyFragment.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+package com.zeapo.pwdstore.sshkeygen
+
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.content.ClipData
+import android.content.ClipboardManager
+import android.content.Context
+import android.os.Bundle
+import android.view.View
+import android.widget.TextView
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.DialogFragment
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.zeapo.pwdstore.R
+import java.io.File
+import java.nio.charset.StandardCharsets
+import org.apache.commons.io.FileUtils
+
+class ShowSshKeyFragment : DialogFragment() {
+
+ private lateinit var activity: SshKeyGenActivity
+ private lateinit var builder: MaterialAlertDialogBuilder
+ private lateinit var publicKey: TextView
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ activity = requireActivity() as SshKeyGenActivity
+ builder = MaterialAlertDialogBuilder(activity)
+ }
+
+ @SuppressLint("InflateParams")
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ val view = activity.layoutInflater.inflate(R.layout.fragment_show_ssh_key, null)
+ publicKey = view.findViewById(R.id.public_key)
+ readKeyFromFile()
+ createMaterialDialog(view)
+ val ad = builder.create()
+ ad.setOnShowListener {
+ val b = ad.getButton(AlertDialog.BUTTON_NEUTRAL)
+ b.setOnClickListener {
+ val clipboard = activity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
+ val clip = ClipData.newPlainText("public key", publicKey.text.toString())
+ clipboard.setPrimaryClip(clip)
+ }
+ }
+ return ad
+ }
+
+ private fun createMaterialDialog(view: View) {
+ builder.setView(view)
+ builder.setTitle(getString(R.string.your_public_key))
+ builder.setPositiveButton(getString(R.string.dialog_ok)) { _, _ -> activity.finish() }
+ builder.setNegativeButton(getString(R.string.dialog_cancel), null)
+ builder.setNeutralButton(resources.getString(R.string.ssh_keygen_copy), null)
+ }
+
+ private fun readKeyFromFile() {
+ val file = File(activity.filesDir.toString() + "/.ssh_key.pub")
+ try {
+ publicKey.text = FileUtils.readFileToString(file, StandardCharsets.UTF_8)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+}
diff --git a/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt
new file mode 100644
index 00000000..21d82a3b
--- /dev/null
+++ b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenActivity.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+package com.zeapo.pwdstore.sshkeygen
+
+import android.os.Bundle
+import android.view.MenuItem
+import androidx.appcompat.app.AppCompatActivity
+
+class SshKeyGenActivity : AppCompatActivity() {
+
+ public override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ title = "Generate SSH Key"
+ if (savedInstanceState == null) {
+ supportFragmentManager
+ .beginTransaction()
+ .replace(android.R.id.content, SshKeyGenFragment())
+ .commit()
+ }
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ // The back arrow in the action bar should act the same as the back button.
+ return when (item.itemId) {
+ android.R.id.home -> {
+ onBackPressed()
+ true
+ }
+ else -> super.onOptionsItemSelected(item)
+ }
+ }
+}
diff --git a/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt
new file mode 100644
index 00000000..19011758
--- /dev/null
+++ b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeyGenFragment.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+package com.zeapo.pwdstore.sshkeygen
+
+import android.os.Bundle
+import android.text.InputType
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.view.inputmethod.InputMethodManager
+import android.widget.ArrayAdapter
+import android.widget.Button
+import android.widget.CheckBox
+import android.widget.EditText
+import android.widget.Spinner
+import androidx.core.content.getSystemService
+import androidx.fragment.app.Fragment
+import com.google.android.material.textfield.TextInputEditText
+import com.zeapo.pwdstore.R
+
+class SshKeyGenFragment : Fragment() {
+
+ private lateinit var checkBox: CheckBox
+ private lateinit var comment: EditText
+ private lateinit var generate: Button
+ private lateinit var passphrase: TextInputEditText
+ private lateinit var spinner: Spinner
+ private lateinit var activity: SshKeyGenActivity
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_ssh_keygen, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ activity = requireActivity() as SshKeyGenActivity
+ findViews(view)
+ val lengths = arrayOf(2048, 4096)
+ val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, lengths)
+ spinner.adapter = adapter
+ generate.setOnClickListener { generate() }
+ checkBox.setOnCheckedChangeListener { _, isChecked: Boolean ->
+ val selection = passphrase.selectionEnd
+ if (isChecked) {
+ passphrase.inputType = (
+ InputType.TYPE_CLASS_TEXT
+ or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)
+ } else {
+ passphrase.inputType = (
+ InputType.TYPE_CLASS_TEXT
+ or InputType.TYPE_TEXT_VARIATION_PASSWORD)
+ }
+ passphrase.setSelection(selection)
+ }
+ }
+
+ private fun findViews(view: View) {
+ checkBox = view.findViewById(R.id.show_passphrase)
+ comment = view.findViewById(R.id.comment)
+ generate = view.findViewById(R.id.generate)
+ passphrase = view.findViewById(R.id.passphrase)
+ spinner = view.findViewById(R.id.length)
+ }
+
+ // Invoked when 'Generate' button of SshKeyGenFragment clicked. Generates a
+ // private and public key, then replaces the SshKeyGenFragment with a
+ // ShowSshKeyFragment which displays the public key.
+ fun generate() {
+ val length = (spinner.selectedItem as Int).toString()
+ val passphrase = passphrase.text.toString()
+ val comment = comment.text.toString()
+ KeyGenerateTask(activity).execute(length, passphrase, comment)
+ hideKeyboard()
+ }
+
+ private fun hideKeyboard() {
+ val imm = activity.getSystemService<InputMethodManager>()
+ var view = activity.currentFocus
+ if (view == null) {
+ view = View(activity)
+ }
+ imm?.hideSoftInputFromWindow(view.windowToken, 0)
+ }
+}
diff --git a/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt
new file mode 100644
index 00000000..194d1023
--- /dev/null
+++ b/app/src/main/java/com/zeapo/pwdstore/sshkeygen/SshKeygenTask.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2014-2019 The Android Password Store Authors. All Rights Reserved.
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+package com.zeapo.pwdstore.sshkeygen
+
+import android.app.ProgressDialog
+import android.os.AsyncTask
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.DialogFragment
+import androidx.preference.PreferenceManager
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.jcraft.jsch.JSch
+import com.jcraft.jsch.KeyPair
+import com.zeapo.pwdstore.R
+import java.io.File
+import java.io.FileOutputStream
+import java.lang.ref.WeakReference
+
+class KeyGenerateTask(activity: AppCompatActivity) : AsyncTask<String?, Void?, Exception?>() {
+ private var pd: ProgressDialog? = null
+ private val weakReference = WeakReference(activity)
+ override fun onPreExecute() {
+ super.onPreExecute()
+ pd = ProgressDialog.show(weakReference.get(), "", "Generating keys")
+ }
+
+ override fun doInBackground(vararg strings: String?): Exception? {
+ val length = strings[0]?.toInt()
+ val passphrase = strings[1]
+ val comment = strings[2]
+ val jsch = JSch()
+ try {
+ val kp = length?.let { KeyPair.genKeyPair(jsch, KeyPair.RSA, it) }
+ var file = File(weakReference.get()!!.filesDir.toString() + "/.ssh_key")
+ var out = FileOutputStream(file, false)
+ if (passphrase?.isNotEmpty()!!) {
+ kp?.writePrivateKey(out, passphrase.toByteArray())
+ } else {
+ kp?.writePrivateKey(out)
+ }
+ file = File(weakReference.get()!!.filesDir.toString() + "/.ssh_key.pub")
+ out = FileOutputStream(file, false)
+ kp?.writePublicKey(out, comment)
+ return null
+ } catch (e: Exception) {
+ e.printStackTrace()
+ return e
+ }
+ }
+
+ override fun onPostExecute(e: Exception?) {
+ super.onPostExecute(e)
+ val activity = weakReference.get()
+ if (activity is AppCompatActivity) {
+ pd!!.dismiss()
+ if (e == null) {
+ Toast.makeText(activity, "SSH-key generated", Toast.LENGTH_LONG).show()
+ val df: DialogFragment = ShowSshKeyFragment()
+ df.show(activity.supportFragmentManager, "public_key")
+ val prefs = PreferenceManager.getDefaultSharedPreferences(weakReference.get())
+ val editor = prefs.edit()
+ editor.putBoolean("use_generated_key", true)
+ editor.apply()
+ } else {
+ MaterialAlertDialogBuilder(weakReference.get())
+ .setTitle(activity.getString(R.string.error_generate_ssh_key))
+ .setMessage(activity.getString(R.string.ssh_key_error_dialog_text) + e.message)
+ .setPositiveButton(activity.getString(R.string.dialog_ok), null)
+ .show()
+ }
+ } else {
+ // TODO: When activity is destroyed
+ }
+ }
+}