diff --git a/core/src/main/java/org/futo/circles/core/provider/KeyStoreProvider.kt b/core/src/main/java/org/futo/circles/core/provider/KeyStoreProvider.kt
index 9582fa1411991aee4d214f8d19aa3d3cf596d698..d292d9e640fd6a5d7037bad02f992dc9f2fcf0c3 100644
--- a/core/src/main/java/org/futo/circles/core/provider/KeyStoreProvider.kt
+++ b/core/src/main/java/org/futo/circles/core/provider/KeyStoreProvider.kt
@@ -1,37 +1,81 @@
 package org.futo.circles.core.provider
 
+import android.security.keystore.KeyGenParameterSpec
+import android.security.keystore.KeyProperties
+import android.util.Base64
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import java.security.KeyStore
+import javax.crypto.Cipher
+import javax.crypto.KeyGenerator
 import javax.crypto.SecretKey
-import javax.crypto.spec.SecretKeySpec
+import javax.crypto.spec.GCMParameterSpec
 import javax.inject.Inject
 
-class KeyStoreProvider @Inject constructor() {
 
-    private val keyStore = KeyStore.getInstance("AndroidKeyStore")
+class KeyStoreProvider @Inject constructor(
+    private val preferencesProvider: PreferencesProvider
+) {
+    private val keyStore
+        get() = KeyStore.getInstance(ANDROID_KEYS_TORE).apply { load(null) }
 
     fun storeBsSpekePrivateKey(keyBytes: ByteArray, keyId: String) {
-        storeKey(keyBytes, "$ORG_FUTO_SSSS_KEY_PREFIX.$keyId")
+        tryOrNull {
+            val alias = "$ORG_FUTO_SSSS_KEY_PREFIX.$keyId"
+            val masterKey = getOrGenerateMasterKeyIfNotExist(alias)
+                ?: throw IllegalArgumentException("Failed to get master key")
+            val encrypted = encryptData(keyBytes, masterKey)
+            preferencesProvider.storeBSspekeEncryptedPrivateKeyBase64(alias, encrypted)
+        }
     }
 
-    fun getBsSpekePrivateKey(keyId: String): ByteArray? = getKey("$ORG_FUTO_SSSS_KEY_PREFIX.$keyId")
+    fun getBsSpekePrivateKey(keyId: String): ByteArray? = tryOrNull {
+        val alias = "$ORG_FUTO_SSSS_KEY_PREFIX.$keyId"
+        val masterKey = getOrGenerateMasterKeyIfNotExist(alias)
+            ?: throw IllegalArgumentException("Failed to get master key")
+        val encrypted = preferencesProvider.getBSspekeEncryptedPrivateKeyBase64(alias)
+            ?: throw IllegalArgumentException("Not saved in preferences $alias")
+        decryptData(encrypted, masterKey)
+    }
 
-    private fun storeKey(keyBytes: ByteArray, alias: String) = tryOrNull {
-        val secretKey: SecretKey = SecretKeySpec(keyBytes, "AES")
-        keyStore.load(null)
-        val protectionParameter = KeyStore.PasswordProtection(null)
-        val secretKeyEntry = KeyStore.SecretKeyEntry(secretKey)
-        keyStore.setEntry(alias, secretKeyEntry, protectionParameter)
+    private fun getOrGenerateMasterKeyIfNotExist(alias: String): SecretKey? {
+        if (!keyStore.containsAlias(alias)) {
+            KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYS_TORE).apply {
+                init(
+                    KeyGenParameterSpec.Builder(
+                        alias, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
+                    )
+                        .setKeySize(KEY_SIZE)
+                        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                        .build()
+                )
+                generateKey()
+            }
+        }
+        return keyStore.getKey(alias, null) as? SecretKey
     }
 
+    private fun encryptData(data: ByteArray, masterKey: SecretKey): String {
+        val cipher = Cipher.getInstance(AES_NO_PADDING)
+        cipher.init(Cipher.ENCRYPT_MODE, masterKey)
+        val ivString = Base64.encodeToString(cipher.iv, Base64.DEFAULT)
+        val encryptedBytes: ByteArray = cipher.doFinal(data)
+        return ivString + IV_SEPARATOR + Base64.encodeToString(encryptedBytes, Base64.DEFAULT)
+    }
 
-    private fun getKey(alias: String): ByteArray? = tryOrNull {
-        keyStore.load(null)
-        val secretKey = keyStore.getKey(alias, null) as SecretKey
-        secretKey.encoded
+    private fun decryptData(encryptedData: String, masterKey: SecretKey): ByteArray {
+        val (iv64, encrypted64) = encryptedData.split(IV_SEPARATOR)
+        val cipher = Cipher.getInstance(AES_NO_PADDING)
+        val spec = GCMParameterSpec(KEY_SIZE, Base64.decode(iv64, Base64.DEFAULT))
+        cipher.init(Cipher.DECRYPT_MODE, masterKey, spec)
+        return cipher.doFinal(Base64.decode(encrypted64, Base64.DEFAULT))
     }
 
     companion object {
+        private const val AES_NO_PADDING = "AES/GCM/NoPadding"
+        private const val IV_SEPARATOR = "]"
+        private const val KEY_SIZE = 128
+        private const val ANDROID_KEYS_TORE = "AndroidKeyStore"
         private const val ORG_FUTO_SSSS_KEY_PREFIX = "org.futo.ssss.key"
     }
 }
diff --git a/core/src/main/java/org/futo/circles/core/provider/PreferencesProvider.kt b/core/src/main/java/org/futo/circles/core/provider/PreferencesProvider.kt
index 0be15e3a30d79d65e19254235a2eb961e332b530..5ba08a31f400e2f5de1e7ad76f3fecd0ef39e9f5 100644
--- a/core/src/main/java/org/futo/circles/core/provider/PreferencesProvider.kt
+++ b/core/src/main/java/org/futo/circles/core/provider/PreferencesProvider.kt
@@ -95,6 +95,15 @@ class PreferencesProvider @Inject constructor(
         getSharedPreferences().edit(true) { putStringSet(NOT_RESTORED_SESSION, set) }
     }
 
+    fun getBSspekeEncryptedPrivateKeyBase64(alias: String): String? {
+        return getSharedPreferences().getString(alias, null)
+    }
+
+    fun storeBSspekeEncryptedPrivateKeyBase64(alias: String, key: String) {
+        getSharedPreferences().edit { putString(alias, key) }
+    }
+
+
     companion object {
         private const val PREFERENCES_NAME = "circles_preferences"
         private const val DEV_MODE_KEY = "developer_mode"