diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt index bdbbd3ea846cbf4b4f3235090d60b08fceaa06b4..1f3dc4bba09be00d5480c2049bcbfa990463a2fb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SharedSecretStorageService.kt @@ -136,4 +136,14 @@ interface SharedSecretStorageService { fun checkShouldBeAbleToAccessSecrets(secretNames: List<String>, keyId: String?): IntegrityResult suspend fun requestSecret(name: String, myOtherDeviceId: String) + + suspend fun generateKeyWithPassphrase( + keyId: String, + keyName: String, + passphrase: String, + keySigner: KeySigner, + progressListener: ProgressListener?, + userName: String? = null, + isBsSpeke: Boolean = false + ): SsssKeyCreationInfo } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt index 35a67b086578214d6af5cbae7600d9bc7fcf1603..a9248c5762d08c3185fb7986cce8bc796b0081e7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.securestorage import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey +import org.matrix.android.sdk.internal.crypto.keysbackup.BCryptManager import org.matrix.android.sdk.internal.crypto.keysbackup.deriveKey /** Tag class. */ @@ -47,6 +48,19 @@ data class RawBytesKeySpec( ) } } + + fun fromPassphrase(passphrase: String, salt: String, iterations: Int, + progressListener: ProgressListener?, isBsSpeke: Boolean = false): RawBytesKeySpec { + return RawBytesKeySpec( + privateKey = if (isBsSpeke) BCryptManager.retrievePrivateKeyWithPassword(passphrase, salt, iterations) + else deriveKey( + passphrase, + salt, + iterations, + progressListener + ) + ) + } } override fun equals(other: Any?): Boolean { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt index ddb048a912a87ed70c102faff312838f884915a6..4c149e59d5b1178bda32c3a675b049d77c2d4508 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt @@ -42,6 +42,7 @@ import org.matrix.android.sdk.api.session.securestorage.SsssPassphrase import org.matrix.android.sdk.api.util.fromBase64 import org.matrix.android.sdk.api.util.toBase64NoPadding import org.matrix.android.sdk.internal.crypto.SecretShareManager +import org.matrix.android.sdk.internal.crypto.keysbackup.BCryptManager import org.matrix.android.sdk.internal.crypto.keysbackup.generatePrivateKeyWithPassword import org.matrix.android.sdk.internal.crypto.tools.HkdfSha256 import org.matrix.android.sdk.internal.crypto.tools.withOlmDecryption @@ -179,7 +180,7 @@ internal class DefaultSharedSecretStorageService @Inject constructor( throw SharedSecretStorageError.UnknownAlgorithm(key.keyInfo.content.algorithm ?: "") } } - is KeyInfoResult.Error -> throw key.error + is KeyInfoResult.Error -> throw key.error } } @@ -388,4 +389,41 @@ internal class DefaultSharedSecretStorageService @Inject constructor( override suspend fun requestSecret(name: String, myOtherDeviceId: String) { secretShareManager.requestSecretTo(myOtherDeviceId, name) } + + override suspend fun generateKeyWithPassphrase( + keyId: String, + keyName: String, + passphrase: String, + keySigner: KeySigner, + progressListener: ProgressListener?, + userName: String?, + isBsSpeke: Boolean + ): SsssKeyCreationInfo { + return withContext(cryptoCoroutineScope.coroutineContext + coroutineDispatchers.computation) { + val privatePart = if (isBsSpeke) BCryptManager.generateBcryptPrivateKeyWithPassword(userName ?: "", passphrase) + else generatePrivateKeyWithPassword(passphrase, progressListener) + + val storageKeyContent = SecretStorageKeyContent( + algorithm = SSSS_ALGORITHM_AES_HMAC_SHA2, + passphrase = SsssPassphrase(algorithm = "m.pbkdf2", iterations = privatePart.iterations, salt = privatePart.salt) + ) + + val signedContent = keySigner.sign(storageKeyContent.canonicalSignable())?.let { + storageKeyContent.copy( + signatures = it + ) + } ?: storageKeyContent + + accountDataService.updateUserAccountData( + "$KEY_ID_BASE.$keyId", + signedContent.toContent() + ) + SsssKeyCreationInfo( + keyId = keyId, + content = storageKeyContent, + recoveryKey = computeRecoveryKey(privatePart.privateKey), + keySpec = RawBytesKeySpec(privatePart.privateKey) + ) + } + } }