Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Update KeyManager to implement KeyManagerInterface from rust #25

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 29 additions & 21 deletions MobileSdk/src/main/java/com/spruceid/mobile/sdk/KeyManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import android.security.keystore.KeyProperties
import android.util.Base64
import android.util.Log
import androidx.annotation.RequiresApi
import com.spruceid.mobile.sdk.rs.EncryptedPayload
import com.spruceid.mobile.sdk.rs.Key
import com.spruceid.mobile.sdk.rs.KeyManagerException
import com.spruceid.mobile.sdk.rs.KeyManagerInterface
import java.security.KeyPairGenerator
import java.security.KeyStore
import java.security.Signature
Expand All @@ -19,7 +23,7 @@ import javax.crypto.spec.GCMParameterSpec
/**
* Implementation of the secure key management with Strongbox and TEE as backup.
*/
class KeyManager {
class KeyManager: KeyManagerInterface {

/**
* Returns the Android Keystore.
Expand Down Expand Up @@ -51,11 +55,13 @@ class KeyManager {
/**
* Resets the Keystore by removing all of the keys.
*/
fun reset() {
override fun reset(): Boolean {
val ks = getKeyStore()
ks.aliases().iterator().forEach {
ks.deleteEntry(it)
}

return true
}

/**
Expand All @@ -64,21 +70,21 @@ class KeyManager {
* @property id of the secret key.
* @returns KeyManagerEnvironment indicating the environment used to generate the key.
*/
fun generateSigningKey(id: String): KeyManagerEnvironment {
override fun generateSigningKey(id: Key): Boolean {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
generateSigningKeyWithStrongbox(id)

return KeyManagerEnvironment.Strongbox
return true
} else {
generateSigningKeyTEE(id)

return KeyManagerEnvironment.TEE
return true
}
} catch (e: Exception) {
generateSigningKeyTEE(id)

return KeyManagerEnvironment.TEE
return true
}
}

Expand Down Expand Up @@ -152,7 +158,7 @@ class KeyManager {
* @property id of the secret key.
* @return the JWK as a string.
*/
fun getJwk(id: String): String? {
override fun getJwk(id: String): String {
val ks = getKeyStore()
val key = ks.getEntry(id, null)

Expand All @@ -176,15 +182,15 @@ class KeyManager {
}
}

return null
throw KeyManagerException.KeyNotFound()
}

/**
* Checks to see if a key already exists.
* @property id of the secret key.
* @return indication if the key exists.
*/
fun keyExists(id: String): Boolean {
override fun keyExists(id: String): Boolean {
val ks = getKeyStore()
return ks.containsAlias(id) && ks.isKeyEntry(id)
}
Expand All @@ -195,14 +201,14 @@ class KeyManager {
* @property payload to be signed.
* @return the signed payload.
*/
fun signPayload(id: String, payload: ByteArray): ByteArray? {
override fun signPayload(id: String, payload: ByteArray): ByteArray {
val ks = getKeyStore()
val entry: KeyStore.Entry = ks.getEntry(id, null)
if (entry !is KeyStore.PrivateKeyEntry) {
Log.w("KEYMAN", "Not an instance of a PrivateKeyEntry")
return null
throw KeyManagerException.KeyInvalid()
}

return Signature.getInstance("SHA256withECDSA").run {
initSign(entry.privateKey)
update(payload)
Expand All @@ -215,21 +221,21 @@ class KeyManager {
* @property id of the secret key.
* @returns KeyManagerEnvironment indicating the environment used to generate the key.
*/
fun generateEncryptionKey(id: String): KeyManagerEnvironment {
override fun generateEncryptionKey(id: String): Boolean {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
generateEncryptionKeyWithStrongbox(id)

return KeyManagerEnvironment.Strongbox
return true
} else {
generateEncryptionKeyWithTEE(id)

return KeyManagerEnvironment.TEE
return true
}
} catch (e: Exception) {
generateEncryptionKeyWithTEE(id)

return KeyManagerEnvironment.TEE
return true
}
}

Expand Down Expand Up @@ -281,20 +287,21 @@ class KeyManager {
generator.generateKey()
}


/**
* Encrypts payload by a key referenced by key id.
* @property id of the secret key.
* @property payload to be encrypted.
* @return initialization vector with the encrypted payload.
*/
fun encryptPayload(id: String, payload: ByteArray): Pair<ByteArray, ByteArray> {
override fun encryptPayload(id: String, payload: ByteArray): EncryptedPayload {
val secretKey = getSecretKey(id)

val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
val iv = cipher.iv
val encrypted = cipher.doFinal(payload)
return Pair(iv, encrypted)
return EncryptedPayload(iv, encrypted)
}

/**
Expand All @@ -304,11 +311,12 @@ class KeyManager {
* @property payload to be encrypted.
* @return the decrypted payload.
*/
fun decryptPayload(id: String, iv: ByteArray, payload: ByteArray): ByteArray? {
override fun decryptPayload(id: Key, encryptedPayload: EncryptedPayload): ByteArray {
val secretKey = getSecretKey(id)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val spec = GCMParameterSpec(128, iv)
val spec = GCMParameterSpec(128, encryptedPayload.iv())
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec)
return cipher.doFinal(payload)
return cipher.doFinal(encryptedPayload.ciphertext())
}
}

Loading