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)
+            )
+        }
+    }
 }