Skip to content
Snippets Groups Projects
Commit c5f1474d authored by Koen's avatar Koen
Browse files

Encryption changes.

parent 3fe81ffb
No related branches found
No related tags found
1 merge request!6Encryption changes.
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
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
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
package com.futo.polycentric.core
class PEncryptionProvider {
companion object {
val instance: PEncryptionProviderV1 = PEncryptionProviderV1.instance;
}
}
\ No newline at end of file
......@@ -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
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
......@@ -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
......@@ -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))
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment