Encrypt token (fix #10)
parent
5ab50fe85d
commit
eb5f998505
|
@ -1,5 +1,6 @@
|
||||||
package gallery.memories.service
|
package gallery.memories.service
|
||||||
|
|
||||||
|
import SecureStorage
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
@ -16,6 +17,8 @@ class AccountService(private val mCtx: MainActivity, private val mHttp: HttpServ
|
||||||
val TAG = AccountService::class.java.simpleName
|
val TAG = AccountService::class.java.simpleName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val store = SecureStorage(mCtx)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login to a server
|
* Login to a server
|
||||||
* @param baseUrl The base URL of the server
|
* @param baseUrl The base URL of the server
|
||||||
|
@ -160,11 +163,7 @@ class AccountService(private val mCtx: MainActivity, private val mHttp: HttpServ
|
||||||
* @param password The password to store
|
* @param password The password to store
|
||||||
*/
|
*/
|
||||||
fun storeCredentials(url: String, user: String, password: String) {
|
fun storeCredentials(url: String, user: String, password: String) {
|
||||||
mCtx.getSharedPreferences("credentials", 0).edit()
|
store.saveCredentials(url, user, password)
|
||||||
.putString("memoriesUrl", url)
|
|
||||||
.putString("user", user)
|
|
||||||
.putString("password", password)
|
|
||||||
.apply()
|
|
||||||
mHttp.setBaseUrl(url)
|
mHttp.setBaseUrl(url)
|
||||||
mHttp.setAuthHeader(Pair(user, password))
|
mHttp.setAuthHeader(Pair(user, password))
|
||||||
}
|
}
|
||||||
|
@ -174,12 +173,10 @@ class AccountService(private val mCtx: MainActivity, private val mHttp: HttpServ
|
||||||
* @return The stored credentials
|
* @return The stored credentials
|
||||||
*/
|
*/
|
||||||
fun getCredentials(): Pair<String, String>? {
|
fun getCredentials(): Pair<String, String>? {
|
||||||
val prefs = mCtx.getSharedPreferences("credentials", 0)
|
val saved = store.getCredentials()
|
||||||
mHttp.setBaseUrl(prefs.getString("memoriesUrl", null))
|
if (saved == null) return null
|
||||||
val user = prefs.getString("user", null)
|
mHttp.setBaseUrl(saved.first)
|
||||||
val password = prefs.getString("password", null)
|
return Pair(saved.second, saved.third)
|
||||||
if (user == null || password == null) return null
|
|
||||||
return Pair(user, password)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,11 +185,7 @@ class AccountService(private val mCtx: MainActivity, private val mHttp: HttpServ
|
||||||
fun deleteCredentials() {
|
fun deleteCredentials() {
|
||||||
mHttp.setAuthHeader(null)
|
mHttp.setAuthHeader(null)
|
||||||
mHttp.setBaseUrl(null)
|
mHttp.setBaseUrl(null)
|
||||||
mCtx.getSharedPreferences("credentials", 0).edit()
|
store.deleteCredentials()
|
||||||
.remove("memoriesUrl")
|
|
||||||
.remove("user")
|
|
||||||
.remove("password")
|
|
||||||
.apply()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
import android.content.Context
|
||||||
|
import android.security.keystore.KeyGenParameterSpec
|
||||||
|
import android.security.keystore.KeyProperties
|
||||||
|
import android.security.keystore.KeyProperties.KEY_ALGORITHM_AES
|
||||||
|
import android.security.keystore.KeyProperties.PURPOSE_DECRYPT
|
||||||
|
import android.security.keystore.KeyProperties.PURPOSE_ENCRYPT
|
||||||
|
import android.util.Base64
|
||||||
|
import java.security.KeyStore
|
||||||
|
import javax.crypto.Cipher
|
||||||
|
import javax.crypto.KeyGenerator
|
||||||
|
import javax.crypto.SecretKey
|
||||||
|
import javax.crypto.spec.IvParameterSpec
|
||||||
|
|
||||||
|
class SecureStorage(private val context: Context) {
|
||||||
|
|
||||||
|
private val keyStore = KeyStore.getInstance("AndroidKeyStore")
|
||||||
|
private val keyAlias = "MemoriesKey"
|
||||||
|
|
||||||
|
init {
|
||||||
|
keyStore.load(null)
|
||||||
|
if (!keyStore.containsAlias(keyAlias)) {
|
||||||
|
generateNewKey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveCredentials(url: String, username: String, token: String) {
|
||||||
|
val cipher = getCipher()
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey())
|
||||||
|
val encryptedToken = cipher.doFinal(token.toByteArray())
|
||||||
|
|
||||||
|
context.getSharedPreferences("credentials", Context.MODE_PRIVATE).edit()
|
||||||
|
.putString("url", url)
|
||||||
|
.putString("username", username)
|
||||||
|
.putString("encryptedToken", Base64.encodeToString(encryptedToken, Base64.DEFAULT))
|
||||||
|
.putString("iv", Base64.encodeToString(cipher.iv, Base64.DEFAULT))
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCredentials(): Triple<String, String, String>? {
|
||||||
|
val sharedPreferences = context.getSharedPreferences("credentials", Context.MODE_PRIVATE)
|
||||||
|
val url = sharedPreferences.getString("url", null)
|
||||||
|
val username = sharedPreferences.getString("username", null)
|
||||||
|
val encryptedToken = sharedPreferences.getString("encryptedToken", null)
|
||||||
|
val ivStr = sharedPreferences.getString("iv", null)
|
||||||
|
|
||||||
|
if (url != null && username != null && encryptedToken != null && ivStr != null) {
|
||||||
|
val iv = Base64.decode(ivStr, Base64.DEFAULT)
|
||||||
|
|
||||||
|
val cipher = getCipher()
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(), IvParameterSpec(iv))
|
||||||
|
|
||||||
|
val token = String(cipher.doFinal(Base64.decode(encryptedToken, Base64.DEFAULT)))
|
||||||
|
return Triple(url, username, token)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteCredentials() {
|
||||||
|
context.getSharedPreferences("credentials", Context.MODE_PRIVATE).edit()
|
||||||
|
.remove("url")
|
||||||
|
.remove("encryptedUsername")
|
||||||
|
.remove("encryptedToken")
|
||||||
|
.remove("iv")
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateNewKey() {
|
||||||
|
val keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM_AES, "AndroidKeyStore")
|
||||||
|
val keyGenSpec = KeyGenParameterSpec.Builder(
|
||||||
|
keyAlias,
|
||||||
|
PURPOSE_ENCRYPT or PURPOSE_DECRYPT
|
||||||
|
)
|
||||||
|
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
|
||||||
|
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
|
||||||
|
.setUserAuthenticationRequired(false) // Change this if needed
|
||||||
|
.build()
|
||||||
|
|
||||||
|
keyGenerator.init(keyGenSpec)
|
||||||
|
keyGenerator.generateKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCipher(): Cipher {
|
||||||
|
val transformation =
|
||||||
|
"$KEY_ALGORITHM_AES/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}"
|
||||||
|
return Cipher.getInstance(transformation)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSecretKey(): SecretKey {
|
||||||
|
return keyStore.getKey(keyAlias, null) as SecretKey
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue