🔐 Store credentials
This commit is contained in:
parent
34eb6f2ec4
commit
7d89a8d409
2 changed files with 109 additions and 33 deletions
|
@ -1,11 +1,13 @@
|
||||||
package com.mylloon.mobidl
|
package com.mylloon.mobidl
|
||||||
|
|
||||||
|
import android.content.Context.MODE_PRIVATE
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.security.keystore.KeyProperties
|
import android.security.keystore.KeyProperties
|
||||||
import javax.crypto.Cipher
|
import javax.crypto.Cipher
|
||||||
import android.security.keystore.KeyGenParameterSpec
|
import android.security.keystore.KeyGenParameterSpec
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import java.security.*
|
import java.security.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class Credentials {
|
class Credentials {
|
||||||
|
@ -13,6 +15,7 @@ class Credentials {
|
||||||
private val provider = "AndroidKeyStore" // location of the key
|
private val provider = "AndroidKeyStore" // location of the key
|
||||||
private val aliasKeyStore = "MobiDL" // name of the key
|
private val aliasKeyStore = "MobiDL" // name of the key
|
||||||
private val transformation = "RSA/ECB/PKCS1Padding" // 'type' of the key
|
private val transformation = "RSA/ECB/PKCS1Padding" // 'type' of the key
|
||||||
|
private val sharedPref = "com.mylloon.MobiDL" // shared pref name
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
@RequiresApi(Build.VERSION_CODES.M)
|
||||||
fun generateKey() { // generate RSA Keys
|
fun generateKey() { // generate RSA Keys
|
||||||
|
@ -56,4 +59,43 @@ class Credentials {
|
||||||
val decryptedBytes = cipher.doFinal(message)
|
val decryptedBytes = cipher.doFinal(message)
|
||||||
return decryptedBytes.decodeToString()
|
return decryptedBytes.decodeToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun store(user: String, password: String) { // Store combo encrypted user/pass in shared preferences
|
||||||
|
val userEncrypted = encrypt(user) // encrypt user
|
||||||
|
val passwordEncrypted = encrypt(password) // encrypt password
|
||||||
|
val context = MainActivity.applicationContext() // get app context
|
||||||
|
|
||||||
|
// show key : Base64.getEncoder().encodeToString(encryptedData)
|
||||||
|
|
||||||
|
// write encrypted data to the app preference
|
||||||
|
val sharedPref = context.getSharedPreferences(sharedPref, MODE_PRIVATE)
|
||||||
|
with(sharedPref?.edit()) {
|
||||||
|
this?.putString("username", userEncrypted.contentToString())
|
||||||
|
this?.putString("password", passwordEncrypted.contentToString())
|
||||||
|
this?.apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(type: Int): String? { // type 0 -> username | type 1 -> password [ return null if there is nothing
|
||||||
|
val context = MainActivity.applicationContext() // get app context
|
||||||
|
|
||||||
|
// read encrypted data from the app preference
|
||||||
|
val sharedPref = context.getSharedPreferences(sharedPref, MODE_PRIVATE)
|
||||||
|
var data: String? = null
|
||||||
|
when (type) {
|
||||||
|
0 -> { data = sharedPref.getString("username", null) }
|
||||||
|
1 -> { data = sharedPref.getString("password", null) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (data != null) {
|
||||||
|
val split: List<String> =
|
||||||
|
data.substring(1, data.length - 1).split(", ")
|
||||||
|
val array = ByteArray(split.size)
|
||||||
|
for (i in split.indices) {
|
||||||
|
array[i] = split[i].toByte()
|
||||||
|
}
|
||||||
|
decrypt(array)
|
||||||
|
} else null
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ package com.mylloon.mobidl
|
||||||
|
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
@ -24,6 +25,18 @@ class MainActivity : AppCompatActivity() {
|
||||||
private var inSettings: Boolean = false // by default your not in settings page
|
private var inSettings: Boolean = false // by default your not in settings page
|
||||||
var prefs: SharedPreferences? = null // first run detection
|
var prefs: SharedPreferences? = null // first run detection
|
||||||
|
|
||||||
|
init {
|
||||||
|
instance = this
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private var instance: MainActivity? = null
|
||||||
|
|
||||||
|
fun applicationContext() : Context {
|
||||||
|
return instance!!.applicationContext
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun toggleSettingsButtonVisibility() { // Change Settings button visibility
|
private fun toggleSettingsButtonVisibility() { // Change Settings button visibility
|
||||||
val visibility: Boolean = settingsButton?.findItem(R.id.settingsButton)?.isVisible == true
|
val visibility: Boolean = settingsButton?.findItem(R.id.settingsButton)?.isVisible == true
|
||||||
settingsButton?.findItem(R.id.settingsButton)?.isVisible = !visibility
|
settingsButton?.findItem(R.id.settingsButton)?.isVisible = !visibility
|
||||||
|
@ -32,39 +45,61 @@ class MainActivity : AppCompatActivity() {
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
override fun onCreate(savedInstanceState: Bundle?) { // Main function
|
override fun onCreate(savedInstanceState: Bundle?) { // Main function
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_login) // show login page
|
|
||||||
|
|
||||||
prefs = getSharedPreferences("com.mylloon.MobiDL", MODE_PRIVATE)
|
prefs = getSharedPreferences("com.mylloon.MobiDL", MODE_PRIVATE)
|
||||||
|
|
||||||
val userInput = findViewById<EditText>(R.id.usernameInput)
|
fun loginPage() {
|
||||||
val passwordInput = findViewById<EditText>(R.id.passwordInput)
|
setContentView(R.layout.activity_login) // show login page
|
||||||
val buttonInput = findViewById<Button>(R.id.loginButton)
|
|
||||||
|
|
||||||
fun changeButtonStatus() { // function who enable/disable the login button
|
val userInput = findViewById<EditText>(R.id.usernameInput)
|
||||||
val text1: String = userInput.text.toString()
|
val passwordInput = findViewById<EditText>(R.id.passwordInput)
|
||||||
val text2: String = passwordInput.text.toString()
|
val buttonInput = findViewById<Button>(R.id.loginButton)
|
||||||
buttonInput.isEnabled = text1.isNotEmpty() && text2.isNotEmpty()
|
|
||||||
|
fun changeButtonStatus() { // function who enable/disable the login button
|
||||||
|
val text1: String = userInput.text.toString()
|
||||||
|
val text2: String = passwordInput.text.toString()
|
||||||
|
buttonInput.isEnabled = text1.isNotEmpty() && text2.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
userInput.addTextChangedListener(object : TextWatcher { // looking user input changes
|
||||||
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun afterTextChanged(editable: Editable) {
|
||||||
|
changeButtonStatus()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
passwordInput.addTextChangedListener(object :
|
||||||
|
TextWatcher { // looking password input changes
|
||||||
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun afterTextChanged(editable: Editable) {
|
||||||
|
changeButtonStatus()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
buttonInput.setOnClickListener { // show main page when clicking the login button
|
||||||
|
val user = userInput.text.toString()
|
||||||
|
val password = passwordInput.text.toString()
|
||||||
|
|
||||||
|
Credentials().store(user, password)
|
||||||
|
mainPage()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (Credentials().get(0) == null) { // test if credentials have already been registered
|
||||||
userInput.addTextChangedListener(object : TextWatcher { // looking user input changes
|
loginPage() // if no ask for
|
||||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
} else {
|
||||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
mainPage() // if yes go to main page
|
||||||
override fun afterTextChanged(editable: Editable) { changeButtonStatus() }
|
|
||||||
})
|
|
||||||
|
|
||||||
passwordInput.addTextChangedListener(object : TextWatcher { // looking password input changes
|
|
||||||
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
|
||||||
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
|
||||||
override fun afterTextChanged(editable: Editable) { changeButtonStatus() }
|
|
||||||
})
|
|
||||||
|
|
||||||
buttonInput.setOnClickListener { // show main page when clicking the login button
|
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
toggleSettingsButtonVisibility()
|
|
||||||
callScript() // call script
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun mainPage() {
|
||||||
|
setContentView(R.layout.activity_main)
|
||||||
|
toggleSettingsButtonVisibility()
|
||||||
|
// user = Credentials().get(0).toString()
|
||||||
|
// password = Credentials().get(1).toString()
|
||||||
|
// callScript(user, password) // call script
|
||||||
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
@RequiresApi(Build.VERSION_CODES.M)
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
@ -72,7 +107,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
println("Generate RSA keys...")
|
println("Generate RSA keys...")
|
||||||
Credentials().generateKey()
|
Credentials().generateKey()
|
||||||
println("Done!")
|
println("Done!")
|
||||||
prefs!!.edit().putBoolean("firstrun", false).commit() // first run done, now the next ones won't be "first".
|
prefs!!.edit().putBoolean("firstrun", false).apply() // first run done, now the next ones won't be "first".
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,20 +130,19 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onBackPressed() { // allow user to use back button to go back to main page
|
override fun onBackPressed() { // allow user to use back button to go back to main page
|
||||||
if (inSettings) {
|
if (inSettings) {
|
||||||
setContentView(R.layout.activity_main)
|
mainPage()
|
||||||
toggleSettingsButtonVisibility()
|
|
||||||
inSettings = false
|
inSettings = false
|
||||||
} else super.onBackPressed()
|
} else super.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun callScript() {
|
private fun callScript(user: String, password: String) {
|
||||||
if(ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.INTERNET)
|
if(ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.INTERNET)
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
Toast.makeText(this@MainActivity, "No permission to use internet", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@MainActivity, "No permission to use internet", Toast.LENGTH_SHORT).show()
|
||||||
this.finishAffinity()
|
this.finishAffinity()
|
||||||
} else {
|
} else {
|
||||||
println("test du script")
|
println("test du script")
|
||||||
Scraper("Mylloon", "Hd59NGB4Me8WSM", app = "Plex", debug = true).search()
|
Scraper(user, password, app = "Plex", debug = true).search()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in a new issue