diff --git a/app/src/androidTest/java/com/futo/polycentric/core/EncryptionProviderTests.kt b/app/src/androidTest/java/com/futo/polycentric/core/EncryptionProviderTests.kt
deleted file mode 100644
index 5498d3dba34896f41edd349763b45d24a2bac845..0000000000000000000000000000000000000000
--- a/app/src/androidTest/java/com/futo/polycentric/core/EncryptionProviderTests.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.futo.polycentric.core
-
-import org.junit.Assert.assertArrayEquals
-import org.junit.Assert.assertEquals
-import org.junit.Test
-
-class EncryptionProviderTests {
-    @Test
-    fun roundtripString() {
-        val input = "test"
-        assertEquals(input, EncryptionProvider.instance.decrypt(EncryptionProvider.instance.encrypt(input)))
-    }
-
-    @Test
-    fun roundtripBytes() {
-        val input = byteArrayOf(1, 2, 3, 10)
-        assertArrayEquals(input, EncryptionProvider.instance.decrypt(EncryptionProvider.instance.encrypt(input)))
-    }
-}
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/futo/polycentric/core/PEncryptionProviderV0Tests.kt b/app/src/androidTest/java/com/futo/polycentric/core/PEncryptionProviderV0Tests.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5fb0bf17e62f162d3f897b1c546cf24c35f0a8b3
--- /dev/null
+++ b/app/src/androidTest/java/com/futo/polycentric/core/PEncryptionProviderV0Tests.kt
@@ -0,0 +1,44 @@
+package com.futo.polycentric.core
+
+import junit.framework.TestCase.assertEquals
+import org.junit.Test
+
+class PEncryptionProviderV0Tests {
+    @Test
+    fun testEncryptDecrypt() {
+        val encryptionProvider = PEncryptionProviderV0.instance
+        val plaintext = "This is a test string."
+
+        // Encrypt the plaintext
+        val ciphertext = encryptionProvider.encrypt(plaintext)
+
+        // Decrypt the ciphertext
+        val decrypted = encryptionProvider.decrypt(ciphertext)
+
+        // The decrypted string should be equal to the original plaintext
+        assertEquals(plaintext, decrypted)
+    }
+
+
+    @Test
+    fun testEncryptDecryptBytes() {
+        val encryptionProvider = PEncryptionProviderV0.instance
+        val bytes = "This is a test string.".toByteArray();
+
+        // Encrypt the plaintext
+        val ciphertext = encryptionProvider.encrypt(bytes)
+
+        // Decrypt the ciphertext
+        val decrypted = encryptionProvider.decrypt(ciphertext)
+
+        // The decrypted string should be equal to the original plaintext
+        assertArrayEquals(bytes, decrypted);
+    }
+
+    private fun assertArrayEquals(a: ByteArray, b: ByteArray) {
+        assertEquals(a.size, b.size);
+        for(i in 0 until a.size) {
+            assertEquals(a[i], b[i]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/futo/polycentric/core/PEncryptionProviderV1Tests.kt b/app/src/androidTest/java/com/futo/polycentric/core/PEncryptionProviderV1Tests.kt
new file mode 100644
index 0000000000000000000000000000000000000000..03e74da3ac08cfea027270f36c9eec34d1c14882
--- /dev/null
+++ b/app/src/androidTest/java/com/futo/polycentric/core/PEncryptionProviderV1Tests.kt
@@ -0,0 +1,44 @@
+package com.futo.polycentric.core
+
+import junit.framework.TestCase.assertEquals
+import org.junit.Test
+
+class PEncryptionProviderV1Tests {
+    @Test
+    fun testEncryptDecrypt() {
+        val encryptionProvider = PEncryptionProviderV1.instance
+        val plaintext = "This is a test string."
+
+        // Encrypt the plaintext
+        val ciphertext = encryptionProvider.encrypt(plaintext)
+
+        // Decrypt the ciphertext
+        val decrypted = encryptionProvider.decrypt(ciphertext)
+
+        // The decrypted string should be equal to the original plaintext
+        assertEquals(plaintext, decrypted)
+    }
+
+
+    @Test
+    fun testEncryptDecryptBytes() {
+        val encryptionProvider = PEncryptionProviderV1.instance
+        val bytes = "This is a test string.".toByteArray();
+
+        // Encrypt the plaintext
+        val ciphertext = encryptionProvider.encrypt(bytes)
+
+        // Decrypt the ciphertext
+        val decrypted = encryptionProvider.decrypt(ciphertext)
+
+        // The decrypted string should be equal to the original plaintext
+        assertArrayEquals(bytes, decrypted);
+    }
+
+    private fun assertArrayEquals(a: ByteArray, b: ByteArray) {
+        assertEquals(a.size, b.size);
+        for(i in 0 until a.size) {
+            assertEquals(a[i], b[i]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/polycentric/core/PEncryptionProvider.kt b/app/src/main/java/com/futo/polycentric/core/PEncryptionProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ba621730c29dbd873cb745d11d9d5829f26110e0
--- /dev/null
+++ b/app/src/main/java/com/futo/polycentric/core/PEncryptionProvider.kt
@@ -0,0 +1,7 @@
+package com.futo.polycentric.core
+
+class PEncryptionProvider {
+    companion object {
+        val instance: PEncryptionProviderV1 = PEncryptionProviderV1.instance;
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/polycentric/core/EncryptionProvider.kt b/app/src/main/java/com/futo/polycentric/core/PEncryptionProviderV0.kt
similarity index 89%
rename from app/src/main/java/com/futo/polycentric/core/EncryptionProvider.kt
rename to app/src/main/java/com/futo/polycentric/core/PEncryptionProviderV0.kt
index 724fa034108694f05bfae31ae06584a3dde9bcd7..41510b5a7b45aa8d1eba405fdfbd13f1c6debe88 100644
--- a/app/src/main/java/com/futo/polycentric/core/EncryptionProvider.kt
+++ b/app/src/main/java/com/futo/polycentric/core/PEncryptionProviderV0.kt
@@ -8,7 +8,7 @@ import javax.crypto.Cipher
 import javax.crypto.KeyGenerator
 import javax.crypto.spec.GCMParameterSpec
 
-class EncryptionProvider {
+class PEncryptionProviderV0 {
     private val _keyStore: KeyStore
     private val secretKey: Key? get() = _keyStore.getKey(KEY_ALIAS, null)
 
@@ -30,7 +30,7 @@ class EncryptionProvider {
 
     fun encrypt(decrypted: ByteArray): ByteArray {
         val c: Cipher = Cipher.getInstance(AES_MODE)
-        c.init(Cipher.ENCRYPT_MODE, secretKey, GCMParameterSpec(128, FIXED_IV))
+        c.init(Cipher.ENCRYPT_MODE, secretKey, GCMParameterSpec(TAG_LENGTH, FIXED_IV))
         return c.doFinal(decrypted)
     }
 
@@ -40,7 +40,7 @@ class EncryptionProvider {
 
     fun decrypt(encrypted: ByteArray): ByteArray {
         val c = Cipher.getInstance(AES_MODE)
-        c.init(Cipher.DECRYPT_MODE, secretKey, GCMParameterSpec(128, FIXED_IV))
+        c.init(Cipher.DECRYPT_MODE, secretKey, GCMParameterSpec(TAG_LENGTH, FIXED_IV))
         return c.doFinal(encrypted)
     }
 
@@ -49,12 +49,13 @@ class EncryptionProvider {
     }
 
     companion object {
-        val instance: EncryptionProvider = EncryptionProvider()
+        val instance: PEncryptionProviderV0 = PEncryptionProviderV0()
 
         private val FIXED_IV = byteArrayOf(12, 43, 127, 2, 99, 22, 6,  78,  24, 53, 8, 101)
         private const val AndroidKeyStore = "AndroidKeyStore"
         private const val KEY_ALIAS = "PolycentricCore_Key"
         private const val AES_MODE = "AES/GCM/NoPadding"
-        private val TAG = "EncryptionProvider"
+        private val TAG = "PEncryptionProviderV0"
+        private const val TAG_LENGTH = 128
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/polycentric/core/PEncryptionProviderV1.kt b/app/src/main/java/com/futo/polycentric/core/PEncryptionProviderV1.kt
new file mode 100644
index 0000000000000000000000000000000000000000..60264455ec2670bc01d26c62ddc6643c3803afd6
--- /dev/null
+++ b/app/src/main/java/com/futo/polycentric/core/PEncryptionProviderV1.kt
@@ -0,0 +1,76 @@
+package com.futo.polycentric.core
+
+import android.security.keystore.KeyGenParameterSpec
+import android.security.keystore.KeyProperties
+import android.util.Base64
+import java.security.Key
+import java.security.KeyStore
+import java.security.SecureRandom
+import javax.crypto.Cipher
+import javax.crypto.KeyGenerator
+import javax.crypto.spec.GCMParameterSpec
+
+class PEncryptionProviderV1 {
+    private val _keyStore: KeyStore
+    private val secretKey: Key? get() = _keyStore.getKey(KEY_ALIAS, null)
+
+    constructor() {
+        _keyStore = KeyStore.getInstance(AndroidKeyStore)
+        _keyStore.load(null)
+
+        if (!_keyStore.containsAlias(KEY_ALIAS)) {
+            val keyGenerator: KeyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, AndroidKeyStore)
+            keyGenerator.init(KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
+                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                .setRandomizedEncryptionRequired(false)
+                .build());
+
+            keyGenerator.generateKey()
+        }
+    }
+
+    fun encrypt(decrypted: String): String {
+        val encrypted = encrypt(decrypted.toByteArray())
+        val encoded = Base64.encodeToString(encrypted, Base64.DEFAULT)
+        return encoded
+    }
+    fun encrypt(decrypted: ByteArray): ByteArray {
+        val ivBytes = generateIv()
+        val c: Cipher = Cipher.getInstance(AES_MODE);
+        c.init(Cipher.ENCRYPT_MODE, secretKey, GCMParameterSpec(TAG_LENGTH, ivBytes))
+        val encodedBytes: ByteArray = c.doFinal(decrypted)
+        return ivBytes + encodedBytes
+    }
+
+    fun decrypt(data: String): String {
+        val bytes = Base64.decode(data, Base64.DEFAULT)
+        return String(decrypt(bytes))
+    }
+    fun decrypt(bytes: ByteArray): ByteArray {
+        val encrypted = bytes.sliceArray(IntRange(IV_SIZE, bytes.size - 1))
+        val ivBytes = bytes.sliceArray(IntRange(0, IV_SIZE - 1))
+
+        val c = Cipher.getInstance(AES_MODE)
+        c.init(Cipher.DECRYPT_MODE, secretKey, GCMParameterSpec(TAG_LENGTH, ivBytes))
+        return c.doFinal(encrypted)
+    }
+
+    private fun generateIv(): ByteArray {
+        val r = SecureRandom()
+        val ivBytes = ByteArray(IV_SIZE)
+        r.nextBytes(ivBytes)
+        return ivBytes
+    }
+
+    companion object {
+        val instance: PEncryptionProviderV1 = PEncryptionProviderV1();
+
+        private const val AndroidKeyStore = "AndroidKeyStore"
+        private const val KEY_ALIAS = "PolycentricCore_Key"
+        private const val AES_MODE = "AES/GCM/NoPadding"
+        private const val IV_SIZE = 12
+        private const val TAG_LENGTH = 128
+        private val TAG = "PEncryptionProviderV1"
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/polycentric/core/SqlLiteDbHelper.kt b/app/src/main/java/com/futo/polycentric/core/SqlLiteDbHelper.kt
index dfe048f19f302bcdd1364d30eff8dfa340330077..e21fbd430f90a05846e49a9ced83d01b9a0ec594 100644
--- a/app/src/main/java/com/futo/polycentric/core/SqlLiteDbHelper.kt
+++ b/app/src/main/java/com/futo/polycentric/core/SqlLiteDbHelper.kt
@@ -4,6 +4,7 @@ import android.content.Context
 import android.database.sqlite.SQLiteDatabase
 import android.database.sqlite.SQLiteOpenHelper
 import android.util.Log
+import userpackage.Protocol
 
 class SqlLiteDbHelper : SQLiteOpenHelper {
     constructor(context: Context, factory: SQLiteDatabase.CursorFactory? = null) : super(context, DATABASE_NAME, factory, DATABASE_VERSION) { }
@@ -17,9 +18,42 @@ class SqlLiteDbHelper : SQLiteOpenHelper {
         Log.w(TAG, "Upgrade from version $oldVersion to $newVersion")
         Log.w(TAG, "This is version 1, no DB to update")
 
+        var currentVersion = oldVersion
         if (oldVersion == 1 && newVersion == 2) {
             deleteTables(db)
             createTables(db)
+            currentVersion = 2
+        }
+
+        if (currentVersion == 2 && newVersion == 3) {
+            val cursor = db.rawQuery("SELECT value FROM process_secrets", arrayOf())
+            val secrets = arrayListOf<ProcessSecret>()
+
+            cursor.use {
+                if (it.moveToFirst()) {
+                    do {
+                        val value = it.getBlob(0)
+                        if (value != null) {
+                            val secret = ProcessSecret.fromProto(Protocol.StorageTypeProcessSecret.parseFrom(PEncryptionProviderV0.instance.decrypt(value)))
+                            secrets.add(secret)
+                        }
+                    } while (cursor.moveToNext())
+                }
+            }
+
+            db.beginTransaction();
+            try {
+                for (secret in secrets) {
+                    db.execSQL("DELETE FROM process_secrets WHERE public_key = ?", arrayOf(secret.system.publicKey.key.toBase64()))
+                    val value = PEncryptionProviderV1.instance.encrypt(secret.toProto().toByteArray())
+                    db.execSQL("INSERT INTO process_secrets VALUES(?, ?)", arrayOf(secret.system.publicKey.key.toBase64(), value))
+                }
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+
+            currentVersion = 3
         }
     }
 
@@ -50,6 +84,6 @@ class SqlLiteDbHelper : SQLiteOpenHelper {
     companion object {
         private const val TAG = "SqlLiteDbHelper"
         private const val DATABASE_NAME = "polycentric_core.db"
-        private const val DATABASE_VERSION = 2
+        private const val DATABASE_VERSION = 3
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/com/futo/polycentric/core/SqlLiteStore.kt b/app/src/main/java/com/futo/polycentric/core/SqlLiteStore.kt
index b559a3a9e1a15b4a4a2a0b1283e973176d814a2a..859284937c2a896d910dc44ecc564daa32782e11 100644
--- a/app/src/main/java/com/futo/polycentric/core/SqlLiteStore.kt
+++ b/app/src/main/java/com/futo/polycentric/core/SqlLiteStore.kt
@@ -130,8 +130,7 @@ class SqlLiteStore(private val _db: SqlLiteDbHelper) : Store() {
         }
 
         if (value != null) {
-            val result = ProcessSecret.fromProto(Protocol.StorageTypeProcessSecret.parseFrom(EncryptionProvider.instance.decrypt(value!!)))
-            return result
+            return ProcessSecret.fromProto(Protocol.StorageTypeProcessSecret.parseFrom(PEncryptionProvider.instance.decrypt(value!!)))
         }
 
         return null
@@ -146,7 +145,7 @@ class SqlLiteStore(private val _db: SqlLiteDbHelper) : Store() {
                 do {
                     val value = it.getBlob(0)
                     if (value != null) {
-                        val secret = ProcessSecret.fromProto(Protocol.StorageTypeProcessSecret.parseFrom(EncryptionProvider.instance.decrypt(value!!)))
+                        val secret = ProcessSecret.fromProto(Protocol.StorageTypeProcessSecret.parseFrom(PEncryptionProvider.instance.decrypt(value)))
                         secrets.add(secret)
                     }
                 } while (cursor.moveToNext())
@@ -161,7 +160,7 @@ class SqlLiteStore(private val _db: SqlLiteDbHelper) : Store() {
     }
 
     override fun addProcessSecret(processSecret: ProcessSecret) {
-        val value = EncryptionProvider.instance.encrypt(processSecret.toProto().toByteArray())
+        val value = PEncryptionProvider.instance.encrypt(processSecret.toProto().toByteArray())
         _db.writableDatabase.execSQL("INSERT INTO process_secrets VALUES(?, ?)",
             arrayOf(processSecret.system.publicKey.key.toBase64(), value))
     }