Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,044 changes: 1,044 additions & 0 deletions FlowCrypt/schemas/com.flowcrypt.email.database.FlowCryptRoomDatabase/37.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class MigrationTest {
FlowCryptRoomDatabase.MIGRATION_33_34,
FlowCryptRoomDatabase.MIGRATION_34_35,
FlowCryptRoomDatabase.MIGRATION_35_36,
FlowCryptRoomDatabase.MIGRATION_36_37,
)

@get:Rule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ abstract class FlowCryptRoomDatabase : RoomDatabase() {

companion object {
const val DB_NAME = "flowcrypt.db"
const val DB_VERSION = 36
const val DB_VERSION = 37

private val MIGRATION_1_3 = object : FlowCryptMigration(1, 3) {
override fun doMigration(database: SupportSQLiteDatabase) {
Expand Down Expand Up @@ -1262,6 +1262,58 @@ abstract class FlowCryptRoomDatabase : RoomDatabase() {
}
}

@VisibleForTesting
val MIGRATION_36_37 = object : FlowCryptMigration(36, 37) {
override fun doMigration(database: SupportSQLiteDatabase) {
//ref https://github.com/FlowCrypt/flowcrypt-android/issues/1766

//create temp table with existing content
database.execSQL("CREATE TEMP TABLE IF NOT EXISTS keys_temp AS SELECT * FROM keys;")
//drop old table
database.execSQL("DROP TABLE IF EXISTS keys;")
//create a new table 'keys' with dropped field 'public_key'
database.execSQL(
"CREATE TABLE IF NOT EXISTS `keys` (" +
"`_id` INTEGER PRIMARY KEY AUTOINCREMENT, " +
"`fingerprint` TEXT NOT NULL, " +
"`account` TEXT NOT NULL, " +
"`account_type` TEXT DEFAULT NULL, " +
"`source` TEXT NOT NULL, " +
"`private_key` BLOB NOT NULL, " +
"`passphrase` TEXT DEFAULT NULL, " +
"`passphrase_type` INTEGER NOT NULL DEFAULT 0, " +
"FOREIGN KEY(`account`, `account_type`) " +
"REFERENCES `accounts`(`email`, `account_type`) " +
"ON UPDATE NO ACTION ON DELETE CASCADE )"

)
//create indices for new table
database.execSQL(
"CREATE INDEX IF NOT EXISTS `account_account_type_in_keys` " +
"ON `keys` (`account`, `account_type`)"
)
database.execSQL(
"CREATE UNIQUE INDEX IF NOT EXISTS `fingerprint_account_account_type_in_keys` " +
"ON `keys` (`fingerprint`, `account`, `account_type`)"
)
//fill new table with existing data.
database.execSQL(
"INSERT INTO `keys` SELECT " +
"_id, " +
"fingerprint, " +
"account, " +
"account_type, " +
"source, " +
"private_key, " +
"passphrase, " +
"passphrase_type " +
"FROM keys_temp;"
)
//drop temp table
database.execSQL("DROP TABLE IF EXISTS keys_temp;")
}
}

// Singleton prevents multiple instances of database opening at the same time.
@Volatile
private var INSTANCE: FlowCryptRoomDatabase? = null
Expand Down Expand Up @@ -1312,6 +1364,7 @@ abstract class FlowCryptRoomDatabase : RoomDatabase() {
MIGRATION_33_34,
MIGRATION_34_35,
MIGRATION_35_36,
MIGRATION_36_37,
).build()
INSTANCE = instance
return instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ data class KeyEntity(
val account: String,
@ColumnInfo(name = "account_type", defaultValue = "NULL") val accountType: String? = null,
val source: String,
@ColumnInfo(name = "public_key") val publicKey: ByteArray,
@ColumnInfo(name = "private_key") val privateKey: ByteArray,
@ColumnInfo(name = "passphrase", defaultValue = "NULL") val storedPassphrase: String?,
@ColumnInfo(name = "passphrase_type", defaultValue = "0") val passphraseType: PassphraseType
Expand All @@ -56,9 +55,6 @@ data class KeyEntity(
@Ignore
val privateKeyAsString = String(privateKey)

@Ignore
val publicKeyAsString = String(publicKey)

@Ignore
val passphrase: Passphrase = if (storedPassphrase == null) {
Passphrase.emptyPassphrase()
Expand All @@ -72,7 +68,6 @@ data class KeyEntity(
" account='$account'," +
" account_type='$accountType'," +
" source='$source'," +
" publicKey=${publicKey.contentToString()}," +
" privateKey=${privateKey.contentToString()}," +
" storedPassphrase=(hidden))" +
" passphraseType='$passphraseType',"
Expand All @@ -89,7 +84,6 @@ data class KeyEntity(
if (account != other.account) return false
if (accountType != other.accountType) return false
if (source != other.source) return false
if (!publicKey.contentEquals(other.publicKey)) return false
if (!privateKey.contentEquals(other.privateKey)) return false
if (storedPassphrase != other.storedPassphrase) return false
if (passphraseType != other.passphraseType) return false
Expand All @@ -104,7 +98,6 @@ data class KeyEntity(
result = 31 * result + account.hashCode()
result = 31 * result + (accountType?.hashCode() ?: 0)
result = 31 * result + source.hashCode()
result = 31 * result + publicKey.contentHashCode()
result = 31 * result + privateKey.contentHashCode()
result = 31 * result + (storedPassphrase?.hashCode() ?: 0)
result = 31 * result + passphraseType.hashCode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat
keyEntity.copy(
privateKey = KeyStoreCryptoManager.encryptSuspend(modifiedPgpKeyDetails.privateKey)
.toByteArray(),
publicKey = modifiedPgpKeyDetails.publicKey.toByteArray(),
storedPassphrase = KeyStoreCryptoManager.encryptSuspend(newPassphrase.asString)
)
}
Expand Down Expand Up @@ -309,6 +308,7 @@ class PrivateKeysViewModel(application: Application) : AccountViewModel(applicat
?: throw IllegalStateException(sourceNotAvailableMsg)
parseKeyResult = PgpKey.parseKeys(source, false)
}

else -> throw IllegalStateException("Unsupported : ${keyImportModel.sourceType}")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,7 @@ class RefreshPrivateKeysFromEkmViewModel(application: Application) : AccountView

val safeVersionOfPrvKey = protectAndEncryptInternally(passphrase, pgpKeyDetails)
roomDatabase.keysDao().updateSuspend(
existingKeyEntity.copy(
privateKey = safeVersionOfPrvKey,
publicKey = pgpKeyDetails.publicKey.toByteArray()
)
existingKeyEntity.copy(privateKey = safeVersionOfPrvKey)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ data class PgpKeyDetails constructor(
account = accountEntity.email.lowercase(),
accountType = accountEntity.accountType,
source = PrivateKeySourceType.BACKUP.toString(),
publicKey = publicKey.toByteArray(),
privateKey = privateKey?.toByteArray()
?: throw NullPointerException("pgpKeyDetails.privateKey == null"),
storedPassphrase = tempPassphrase?.let { String(it) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ data class EncryptPrivateKeysIfNeededAction @JvmOverloads constructor(
val keyDetailsWithPgpEncryptedInfo = encryptedKeyDetailsList.first()
val modifiedKeyEntity = keyEntity.copy(
privateKey = KeyStoreCryptoManager.encrypt(keyDetailsWithPgpEncryptedInfo.privateKey)
.toByteArray(),
publicKey = keyDetailsWithPgpEncryptedInfo.publicKey.toByteArray()
.toByteArray()
)
modifiedKeyEntities.add(modifiedKeyEntity)
} catch (e: PrivateKeyStrengthException) {
Expand Down