Browse Source

Pin code: add some tests

pull/1592/head
ganfra 11 months ago
parent
commit
d6d553e8e0
  1. 2
      features/lockscreen/impl/build.gradle.kts
  2. 14
      features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt
  3. 53
      features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManagerTest.kt
  4. 59
      features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryPinCodeStore.kt
  5. 27
      libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/AESEncryptionSpecs.kt
  6. 5
      libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/EncryptionDecryptionService.kt
  7. 9
      libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/EncryptionResult.kt
  8. 27
      libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyProvider.kt
  9. 4
      libraries/cryptography/impl/build.gradle.kts
  10. 41
      libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/AESEncryptionDecryptionService.kt
  11. 55
      libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyProvider.kt
  12. 54
      libraries/cryptography/impl/src/test/kotlin/io/element/android/libraries/cryptography/impl/AESEncryptionDecryptionServiceTest.kt
  13. 27
      libraries/cryptography/test/build.gradle.kts
  14. 39
      libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyProvider.kt

2
features/lockscreen/impl/build.gradle.kts

@ -47,6 +47,8 @@ dependencies {
testImplementation(libs.test.truth) testImplementation(libs.test.truth)
testImplementation(libs.test.turbine) testImplementation(libs.test.turbine)
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.cryptography.test)
testImplementation(projects.libraries.cryptography.impl)
ksp(libs.showkase.processor) ksp(libs.showkase.processor)
} }

14
features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManager.kt

@ -18,8 +18,9 @@ package io.element.android.features.lockscreen.impl.pin
import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.lockscreen.impl.pin.storage.PinCodeStore import io.element.android.features.lockscreen.impl.pin.storage.PinCodeStore
import io.element.android.libraries.cryptography.api.CryptoService import io.element.android.libraries.cryptography.api.EncryptionDecryptionService
import io.element.android.libraries.cryptography.api.EncryptionResult import io.element.android.libraries.cryptography.api.EncryptionResult
import io.element.android.libraries.cryptography.api.SecretKeyProvider
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import javax.inject.Inject import javax.inject.Inject
@ -27,7 +28,8 @@ private const val SECRET_KEY_ALIAS = "SECRET_KEY_ALIAS_PIN_CODE"
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultPinCodeManager @Inject constructor( class DefaultPinCodeManager @Inject constructor(
private val cryptoService: CryptoService, private val secretKeyProvider: SecretKeyProvider,
private val encryptionDecryptionService: EncryptionDecryptionService,
private val pinCodeStore: PinCodeStore, private val pinCodeStore: PinCodeStore,
) : PinCodeManager { ) : PinCodeManager {
@ -36,16 +38,16 @@ class DefaultPinCodeManager @Inject constructor(
} }
override suspend fun createPinCode(pinCode: String) { override suspend fun createPinCode(pinCode: String) {
val secretKey = cryptoService.getOrCreateSecretKey(SECRET_KEY_ALIAS) val secretKey = secretKeyProvider.getOrCreateKey(SECRET_KEY_ALIAS)
val encryptedPinCode = cryptoService.encrypt(secretKey, pinCode.toByteArray()).toBase64() val encryptedPinCode = encryptionDecryptionService.encrypt(secretKey, pinCode.toByteArray()).toBase64()
pinCodeStore.saveEncryptedPinCode(encryptedPinCode) pinCodeStore.saveEncryptedPinCode(encryptedPinCode)
} }
override suspend fun verifyPinCode(pinCode: String): Boolean { override suspend fun verifyPinCode(pinCode: String): Boolean {
val encryptedPinCode = pinCodeStore.getEncryptedCode() ?: return false val encryptedPinCode = pinCodeStore.getEncryptedCode() ?: return false
return try { return try {
val secretKey = cryptoService.getOrCreateSecretKey(SECRET_KEY_ALIAS) val secretKey = secretKeyProvider.getOrCreateKey(SECRET_KEY_ALIAS)
val decryptedPinCode = cryptoService.decrypt(secretKey, EncryptionResult.fromBase64(encryptedPinCode)) val decryptedPinCode = encryptionDecryptionService.decrypt(secretKey, EncryptionResult.fromBase64(encryptedPinCode))
decryptedPinCode.contentEquals(pinCode.toByteArray()) decryptedPinCode.contentEquals(pinCode.toByteArray())
} catch (failure: Throwable) { } catch (failure: Throwable) {
false false

53
features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/DefaultPinCodeManagerTest.kt

@ -0,0 +1,53 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.lockscreen.impl.pin
import com.google.common.truth.Truth.assertThat
import io.element.android.features.lockscreen.impl.pin.storage.InMemoryPinCodeStore
import io.element.android.libraries.cryptography.impl.AESEncryptionDecryptionService
import io.element.android.libraries.cryptography.test.SimpleSecretKeyProvider
import kotlinx.coroutines.test.runTest
import org.junit.Test
class DefaultPinCodeManagerTest {
private val pinCodeStore = InMemoryPinCodeStore()
private val secretKeyProvider = SimpleSecretKeyProvider()
private val encryptionDecryptionService = AESEncryptionDecryptionService()
private val pinCodeManager = DefaultPinCodeManager(secretKeyProvider, encryptionDecryptionService, pinCodeStore)
@Test
fun given_a_pin_code_when_create_and_delete_assert_no_pin_code_left() = runTest {
pinCodeManager.createPinCode("1234")
assertThat(pinCodeManager.isPinCodeAvailable()).isTrue()
pinCodeManager.deletePinCode()
assertThat(pinCodeManager.isPinCodeAvailable()).isFalse()
}
@Test
fun given_a_pin_code_when_create_and_verify_with_the_same_pin_succeed() = runTest {
val pinCode = "1234"
pinCodeManager.createPinCode(pinCode)
assertThat(pinCodeManager.verifyPinCode(pinCode)).isTrue()
}
@Test
fun given_a_pin_code_when_create_and_verify_with_a_different_pin_fails() = runTest {
pinCodeManager.createPinCode("1234")
assertThat(pinCodeManager.verifyPinCode("1235")).isFalse()
}
}

59
features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/pin/storage/InMemoryPinCodeStore.kt

@ -0,0 +1,59 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.lockscreen.impl.pin.storage
class InMemoryPinCodeStore : PinCodeStore {
private var pinCode: String? = null
private var remainingAttempts: Int = 3
override suspend fun getRemainingPinCodeAttemptsNumber(): Int {
return remainingAttempts
}
override suspend fun onWrongPin(): Int {
return remainingAttempts--
}
override suspend fun resetCounter() {
remainingAttempts = 3
}
override fun addListener(listener: PinCodeStore.Listener) {
// no-op
}
override fun removeListener(listener: PinCodeStore.Listener) {
// no-op
}
override suspend fun getEncryptedCode(): String? {
return pinCode
}
override suspend fun saveEncryptedPinCode(pinCode: String) {
this.pinCode = pinCode
}
override suspend fun deleteEncryptedPinCode() {
pinCode = null
}
override suspend fun hasPinCode(): Boolean {
return pinCode != null
}
}

27
libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/AESEncryptionSpecs.kt

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.cryptography.api
import android.security.keystore.KeyProperties
object AESEncryptionSpecs {
const val BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM
const val PADDINGS = KeyProperties.ENCRYPTION_PADDING_NONE
const val ALGORITHM = KeyProperties.KEY_ALGORITHM_AES
const val KEY_SIZE = 128
const val CIPHER_TRANSFORMATION = "$ALGORITHM/$BLOCK_MODE/$PADDINGS"
}

5
libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/CryptoService.kt → libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/EncryptionDecryptionService.kt

@ -20,10 +20,9 @@ import javax.crypto.Cipher
import javax.crypto.SecretKey import javax.crypto.SecretKey
/** /**
* Simple service to provide cryptographic operations. * Simple service to provide encryption and decryption operations.
*/ */
interface CryptoService { interface EncryptionDecryptionService {
fun getOrCreateSecretKey(alias: String): SecretKey
fun createEncryptionCipher(key: SecretKey): Cipher fun createEncryptionCipher(key: SecretKey): Cipher
fun createDecryptionCipher(key: SecretKey, initializationVector: ByteArray): Cipher fun createDecryptionCipher(key: SecretKey, initializationVector: ByteArray): Cipher
fun encrypt(key: SecretKey, input: ByteArray): EncryptionResult fun encrypt(key: SecretKey, input: ByteArray): EncryptionResult

9
libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/EncryptionResult.kt

@ -14,10 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
@file:OptIn(ExperimentalEncodingApi::class)
package io.element.android.libraries.cryptography.api package io.element.android.libraries.cryptography.api
import android.util.Base64
import java.nio.ByteBuffer import java.nio.ByteBuffer
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi
/** /**
* Holds the result of an encryption operation. * Holds the result of an encryption operation.
@ -34,7 +37,7 @@ class EncryptionResult(
.put(initializationVector) .put(initializationVector)
.put(encryptedByteArray) .put(encryptedByteArray)
.array() .array()
return Base64.encodeToString(cipherTextWithIv, Base64.NO_WRAP) return Base64.encode(cipherTextWithIv)
} }
companion object { companion object {
@ -43,7 +46,7 @@ class EncryptionResult(
* @return the [EncryptionResult] from the base64 representation. * @return the [EncryptionResult] from the base64 representation.
*/ */
fun fromBase64(base64: String): EncryptionResult { fun fromBase64(base64: String): EncryptionResult {
val cipherTextWithIv = Base64.decode(base64, Base64.NO_WRAP) val cipherTextWithIv = Base64.decode(base64)
val buffer = ByteBuffer.wrap(cipherTextWithIv) val buffer = ByteBuffer.wrap(cipherTextWithIv)
val initializationVectorSize = buffer.int val initializationVectorSize = buffer.int
val initializationVector = ByteArray(initializationVectorSize) val initializationVector = ByteArray(initializationVectorSize)

27
libraries/cryptography/api/src/main/kotlin/io/element/android/libraries/cryptography/api/SecretKeyProvider.kt

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.cryptography.api
import javax.crypto.SecretKey
/**
* Simple interface to get or create a secret key for a given alias.
* Implementation should be able to store the generated key securely.
*/
interface SecretKeyProvider {
fun getOrCreateKey(alias: String): SecretKey
}

4
libraries/cryptography/impl/build.gradle.kts

@ -29,7 +29,11 @@ anvil {
dependencies { dependencies {
anvil(projects.anvilcodegen) anvil(projects.anvilcodegen)
implementation(libs.dagger)
implementation(projects.anvilannotations) implementation(projects.anvilannotations)
implementation(projects.libraries.di) implementation(projects.libraries.di)
implementation(projects.libraries.cryptography.api) implementation(projects.libraries.cryptography.api)
testImplementation(libs.test.junit)
testImplementation(libs.test.truth)
} }

41
libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/DefaultCryptoService.kt → libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/AESEncryptionDecryptionService.kt

@ -16,56 +16,31 @@
package io.element.android.libraries.cryptography.impl package io.element.android.libraries.cryptography.impl
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.cryptography.api.CryptoService import io.element.android.libraries.cryptography.api.AESEncryptionSpecs
import io.element.android.libraries.cryptography.api.EncryptionDecryptionService
import io.element.android.libraries.cryptography.api.EncryptionResult import io.element.android.libraries.cryptography.api.EncryptionResult
import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.AppScope
import java.security.KeyStore
import javax.crypto.Cipher import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey import javax.crypto.SecretKey
import javax.crypto.spec.GCMParameterSpec import javax.crypto.spec.GCMParameterSpec
import javax.inject.Inject import javax.inject.Inject
private const val ANDROID_KEYSTORE = "AndroidKeyStore" /**
private const val ENCRYPTION_BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM * Default implementation of [EncryptionDecryptionService] using AES encryption.
private const val ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_NONE */
private const val ENCRYPTION_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES
private const val ENCRYPTION_AES_TRANSFORMATION = "$ENCRYPTION_ALGORITHM/$ENCRYPTION_BLOCK_MODE/$ENCRYPTION_PADDING"
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultCryptoService @Inject constructor() : CryptoService { class AESEncryptionDecryptionService @Inject constructor() : EncryptionDecryptionService {
override fun getOrCreateSecretKey(alias: String): SecretKey {
val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
val secretKeyEntry = (keyStore.getEntry(alias, null) as? KeyStore.SecretKeyEntry)
?.secretKey
return if (secretKeyEntry == null) {
val generator = KeyGenerator.getInstance(ENCRYPTION_ALGORITHM, ANDROID_KEYSTORE)
val keyGenSpec = KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(ENCRYPTION_BLOCK_MODE)
.setEncryptionPaddings(ENCRYPTION_PADDING)
.setKeySize(128)
.build()
generator.init(keyGenSpec)
generator.generateKey()
} else secretKeyEntry
}
override fun createEncryptionCipher(key: SecretKey): Cipher { override fun createEncryptionCipher(key: SecretKey): Cipher {
return Cipher.getInstance(ENCRYPTION_AES_TRANSFORMATION).apply { return Cipher.getInstance(AESEncryptionSpecs.CIPHER_TRANSFORMATION).apply {
init(Cipher.ENCRYPT_MODE, key) init(Cipher.ENCRYPT_MODE, key)
} }
} }
override fun createDecryptionCipher(key: SecretKey, initializationVector: ByteArray): Cipher { override fun createDecryptionCipher(key: SecretKey, initializationVector: ByteArray): Cipher {
val spec = GCMParameterSpec(128, initializationVector) val spec = GCMParameterSpec(128, initializationVector)
return Cipher.getInstance(ENCRYPTION_AES_TRANSFORMATION).apply { return Cipher.getInstance(AESEncryptionSpecs.CIPHER_TRANSFORMATION).apply {
init(Cipher.DECRYPT_MODE, key, spec) init(Cipher.DECRYPT_MODE, key, spec)
} }
} }

55
libraries/cryptography/impl/src/main/kotlin/io/element/android/libraries/cryptography/impl/KeyStoreSecretKeyProvider.kt

@ -0,0 +1,55 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.cryptography.impl
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import io.element.android.libraries.cryptography.api.AESEncryptionSpecs
import io.element.android.libraries.cryptography.api.SecretKeyProvider
import java.security.KeyStore
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
private const val ANDROID_KEYSTORE = "AndroidKeyStore"
/**
* Default implementation of [SecretKeyProvider] that uses the Android Keystore to store the keys.
* The generated key uses AES algorithm, with a key size of 128 bits, and the GCM block mode.
*/
class KeyStoreSecretKeyProvider : SecretKeyProvider {
override fun getOrCreateKey(alias: String): SecretKey {
val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
val secretKeyEntry = (keyStore.getEntry(alias, null) as? KeyStore.SecretKeyEntry)
?.secretKey
return if (secretKeyEntry == null) {
val generator = KeyGenerator.getInstance(AESEncryptionSpecs.ALGORITHM, ANDROID_KEYSTORE)
val keyGenSpec = KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(AESEncryptionSpecs.BLOCK_MODE)
.setEncryptionPaddings(AESEncryptionSpecs.PADDINGS)
.setKeySize(AESEncryptionSpecs.KEY_SIZE)
.build()
generator.init(keyGenSpec)
generator.generateKey()
} else {
secretKeyEntry
}
}
}

54
libraries/cryptography/impl/src/test/kotlin/io/element/android/libraries/cryptography/impl/AESEncryptionDecryptionServiceTest.kt

@ -0,0 +1,54 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.cryptography.impl
import android.security.keystore.KeyProperties
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.assertThrows
import org.junit.Test
import java.security.GeneralSecurityException
import javax.crypto.KeyGenerator
class AESEncryptionDecryptionServiceTest {
private val encryptionDecryptionService = AESEncryptionDecryptionService()
@Test
fun given_a_valid_key_then_encrypt_decrypt_work() {
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES)
keyGenerator.init(128)
val key = keyGenerator.generateKey()
val input = "Hello World".toByteArray()
val encryptionResult = encryptionDecryptionService.encrypt(key, input)
val decrypted = encryptionDecryptionService.decrypt(key, encryptionResult)
assertThat(decrypted).isEqualTo(input)
}
@Test
fun given_a_wrong_key_then_decrypt_fail() {
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES)
keyGenerator.init(128)
val encryptionKey = keyGenerator.generateKey()
val input = "Hello World".toByteArray()
val encryptionResult = encryptionDecryptionService.encrypt(encryptionKey, input)
val decryptionKey = keyGenerator.generateKey()
assertThrows(GeneralSecurityException::class.java) {
encryptionDecryptionService.decrypt(decryptionKey, encryptionResult)
}
}
}

27
libraries/cryptography/test/build.gradle.kts

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
plugins {
id("io.element.android-library")
}
android {
namespace = "io.element.android.libraries.cryptography.test"
dependencies {
api(projects.libraries.cryptography.api)
}
}

39
libraries/cryptography/test/src/main/kotlin/io/element/android/libraries/cryptography/test/SimpleSecretKeyProvider.kt

@ -0,0 +1,39 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.cryptography.test
import io.element.android.libraries.cryptography.api.AESEncryptionSpecs
import io.element.android.libraries.cryptography.api.SecretKeyProvider
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
class SimpleSecretKeyProvider : SecretKeyProvider {
private var secretKeyForAlias = HashMap<String, SecretKey>()
override fun getOrCreateKey(alias: String): SecretKey {
return secretKeyForAlias.getOrPut(alias) {
generateKey()
}
}
private fun generateKey(): SecretKey {
val keyGenerator = KeyGenerator.getInstance(AESEncryptionSpecs.ALGORITHM)
keyGenerator.init(AESEncryptionSpecs.KEY_SIZE)
return keyGenerator.generateKey()
}
}
Loading…
Cancel
Save