Skip to content

Commit

Permalink
Library upgrades with lint clean up
Browse files Browse the repository at this point in the history
Change Preferences save from apply() to commit()
  • Loading branch information
jchau207 committed Oct 14, 2022
1 parent 7905a89 commit 9bd332b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 78 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
ext.kotlin_version = '1.6.10'
ext.kotlin_version = '1.7.10'
repositories {
google()
jcenter()
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Wed Feb 09 11:51:17 JST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
distributionUrl=https://services.gradle.org/distributions/gradle-7.1-all.zip
12 changes: 6 additions & 6 deletions securepreferences/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

group = 'com.github.Bitcoin-com'
version = '1.2.3'
version = '1.2.4'

android {
compileSdkVersion 31
compileSdkVersion 32

defaultConfig {
targetSdkVersion 31
targetSdkVersion 32
minSdkVersion 23
versionCode 10203
versionName "1.2.3"
versionCode 10204
versionName "1.2.4"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand All @@ -34,7 +34,7 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

// For @RequiresApi
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'androidx.appcompat:appcompat:1.5.1'
testImplementation 'junit:junit:4.13.2'
// Robolectric environment
testImplementation 'androidx.test:core:1.4.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package com.bitcoin.securepreferences
import android.app.KeyguardManager
import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKeys
import org.json.JSONObject
Expand All @@ -31,16 +29,11 @@ class SecureStringEncrypter(context: Context, private val namespace: String) {
val keyguardManager: KeyguardManager? =
context.getSystemService(Context.KEYGUARD_SERVICE) as? KeyguardManager
if (keyguardManager != null) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
deviceIsSecure = keyguardManager.isDeviceSecure
} else {
deviceIsSecure = keyguardManager.isKeyguardSecure
}
deviceIsSecure = keyguardManager.isDeviceSecure
}

mDeviceIsSecure = deviceIsSecure
Log.d(TAG, "Device is secure: ${mDeviceIsSecure}")
Log.d(TAG, "Device is secure: $mDeviceIsSecure")
}

@Synchronized
Expand All @@ -53,11 +46,7 @@ class SecureStringEncrypter(context: Context, private val namespace: String) {
when (versionOverride) {
VERSION_UNENCRYPTED -> encryptionPassthroughOfString(value)
VERSION_KEY_STORE_AES -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
encryptStringUsingKeystoreAes(value)
} else {
throw Exception("SDK version ${Build.VERSION.SDK_INT} is not supported ")
}
encryptStringUsingKeystoreAes(value)
}
VERSION_AES_KEY_ENCRYPTED_PREFERENCE -> encryptStringUsingAesThenEncryptedPreference(
value
Expand All @@ -77,18 +66,7 @@ class SecureStringEncrypter(context: Context, private val namespace: String) {

@Synchronized
fun encryptString(value: String): String {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
encryptStringUsingKeystoreAes(value)
}
mDeviceIsSecure -> {
encryptStringUsingAesThenKeystoreRsa(value)
}
else -> {
// TODO: What is the right thing to do here?
encryptStringUsingAesThenKeystoreRsa(value)
}
}
return encryptStringUsingKeystoreAes(value)
}

private fun getEncryptedSharedPreference(): SharedPreferences {
Expand All @@ -109,92 +87,73 @@ class SecureStringEncrypter(context: Context, private val namespace: String) {

val sharedPreferences = getEncryptedSharedPreference()
val keyRef = UUID.randomUUID().toString()
sharedPreferences.edit().putString(keyRef, Base64.toBase64String(aesEncrypted.key)).apply()
sharedPreferences.edit().putString(keyRef, Base64.toBase64String(aesEncrypted.key)).commit()
encrypted.put(JSON_KEY, keyRef)
encrypted.put(JSON_VALUE, aesEncrypted.encrypted)

val container = JSONObject()
container.put(JSON_VERSION, VERSION_AES_KEY_ENCRYPTED_PREFERENCE)
container.put(JSON_ENCRYPTED, encrypted)
val jsonToSave = container.toString()

return jsonToSave
return container.toString()
}

private fun encryptStringUsingAesThenKeystoreRsa(value: String): String {
val aesEncrypted: AesEncryptionResult = encryptUsingAesWithoutKeystore(value)
//Log.d(TAG, "aesEncrypted: ${aesEncrypted}")

val rsaEncrypted: JSONObject =
encryptWithVersionUsingRsa(mApplicationContext, aesEncrypted.key, namespace)
val encrypted: JSONObject = JSONObject()
val encrypted = JSONObject()
encrypted.put(JSON_KEY, rsaEncrypted)
encrypted.put(JSON_VALUE, aesEncrypted.encrypted)

val container: JSONObject = JSONObject()
val container = JSONObject()
container.put(JSON_VERSION, VERSION_AES_KEY_STORE_RSA)
container.put(JSON_ENCRYPTED, encrypted)
val jsonToSave: String = container.toString()

return jsonToSave
return container.toString()
}

@RequiresApi(Build.VERSION_CODES.M)
private fun encryptStringUsingKeystoreAes(value: String): String {
val encrypted: JSONObject = encryptUsingAesWithKeystore(value, namespace)
//Log.d(TAG, "aesEncrypted: ${encrypted}")

val container: JSONObject = JSONObject()
container.put(JSON_VERSION, VERSION_KEY_STORE_AES)
container.put(JSON_ENCRYPTED, encrypted)
val jsonToSave: String = container.toString()

return jsonToSave
return container.toString()
}

fun encryptionPassthroughOfString(value: String): String {
private fun encryptionPassthroughOfString(value: String): String {
val container: JSONObject = JSONObject()
container.put(JSON_VERSION, VERSION_UNENCRYPTED)
container.put(JSON_VALUE, value)
val jsonToSave: String = container.toString()

return jsonToSave
return container.toString()
}

@Synchronized
fun decryptString(json: String): String {
val parsed: JSONObject = JSONObject(json)
val version: Int? = parsed.optInt(JSON_VERSION)
if (version == null) {
throw Exception("Format of encrypted data not recognised.")
}
when (version) {
val parsed = JSONObject(json)
when (val version: Int = parsed.optInt(JSON_VERSION)) {
VERSION_UNENCRYPTED -> {
val value: String? = parsed.optString(JSON_VALUE)
if (value == null) {
throw Exception("Value for encrypted data version $version not found.")
}
return value
return parsed.optString(JSON_VALUE)
?: throw Exception("Value for encrypted data version $version not found.")
}
VERSION_AES_KEY_STORE_RSA -> {
val encrypted: JSONObject? = parsed.optJSONObject(JSON_ENCRYPTED)
if (encrypted == null) {
throw Exception("Encrypted value for encrypted data version $version not found.")
}
val encrypted: JSONObject = parsed.optJSONObject(JSON_ENCRYPTED)
?: throw Exception("Encrypted value for encrypted data version $version not found.")
return decryptStringEncryptedUsingAesThenKeyStoreRsa(encrypted)
}
VERSION_KEY_STORE_AES -> {
val encrypted: JSONObject? = parsed.optJSONObject(JSON_ENCRYPTED)
if (encrypted == null) {
throw Exception("Encrypted value for encrypted data version $version not found.")
}
val encrypted: JSONObject = parsed.optJSONObject(JSON_ENCRYPTED)
?: throw Exception("Encrypted value for encrypted data version $version not found.")
return getStringEncryptedUsingKeyStoreAes(encrypted)
}
VERSION_AES_KEY_ENCRYPTED_PREFERENCE -> {
val encrypted = parsed.optJSONObject(JSON_ENCRYPTED)
if (encrypted == null) {
throw Exception("Encrypted value for encrypted data version $version not found.")
}
?: throw Exception("Encrypted value for encrypted data version $version not found.")
return decryptStringEncryptedUsingAesEncryptedSharedPreference(encrypted)
}

Expand All @@ -205,7 +164,7 @@ class SecureStringEncrypter(context: Context, private val namespace: String) {
private fun decryptStringEncryptedUsingAesEncryptedSharedPreference(jsonObj: JSONObject): String {
val keyRef = jsonObj.optString(JSON_KEY)
val aesEncrypted = jsonObj.optJSONObject(JSON_VALUE)
if (keyRef == null || aesEncrypted == null) {
if (aesEncrypted == null) {
throw Exception("Fetching JSON failed: keyRef: $keyRef EncryptedValue: $aesEncrypted")
}
val sharedPreferences = getEncryptedSharedPreference()
Expand All @@ -217,9 +176,7 @@ class SecureStringEncrypter(context: Context, private val namespace: String) {

val aesKey = Base64.decode(base64Key)

val plainText = decryptUsingAesWithoutKeyStore(aesKey, aesEncrypted)

return plainText
return decryptUsingAesWithoutKeyStore(aesKey, aesEncrypted)
}

private fun decryptStringEncryptedUsingAesThenKeyStoreRsa(jsonObj: JSONObject): String {
Expand All @@ -230,14 +187,12 @@ class SecureStringEncrypter(context: Context, private val namespace: String) {
}

val aesKey: ByteArray = decryptWithVersionUsingRsa(rsaEncryptedKey, namespace)
val plaintext: String = decryptUsingAesWithoutKeyStore(aesKey, aesEncrypted)

return plaintext
return decryptUsingAesWithoutKeyStore(aesKey, aesEncrypted)
}

private fun getStringEncryptedUsingKeyStoreAes(json: JSONObject): String {
val plaintext: String = decryptUsingAesWithKeyStore(json, namespace)
return plaintext
return decryptUsingAesWithKeyStore(json, namespace)
}

companion object {
Expand Down

0 comments on commit 9bd332b

Please sign in to comment.