Better KDBX version implementation (new code)

This commit is contained in:
J-Jamet
2021-03-25 11:07:51 +01:00
parent 3ffa89bfaf
commit f5073238d8
7 changed files with 39 additions and 30 deletions

View File

@@ -43,6 +43,7 @@ import com.kunzisoft.keepass.database.element.node.NodeIdUUID
import com.kunzisoft.keepass.database.exception.*
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDB
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX.Companion.FILE_VERSION_32_4
import com.kunzisoft.keepass.database.file.input.DatabaseInputKDB
import com.kunzisoft.keepass.database.file.input.DatabaseInputKDBX
import com.kunzisoft.keepass.database.file.output.DatabaseOutputKDB
@@ -225,7 +226,7 @@ class Database {
// Default compression not necessary if stored in header
mDatabaseKDBX?.let {
return it.compressionAlgorithm == CompressionAlgorithm.GZip
&& it.kdbxVersion.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()
&& it.kdbxVersion.isBefore(FILE_VERSION_32_4)
}
return false
}

View File

@@ -187,7 +187,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
}
CompressionAlgorithm.GZip -> {
// Only in databaseV3.1, in databaseV4 the header is zipped during the save
if (kdbxVersion.toKotlinLong() < FILE_VERSION_32_4.toKotlinLong()) {
if (kdbxVersion.isBefore(FILE_VERSION_32_4)) {
compressAllBinaries()
}
}
@@ -195,9 +195,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
}
CompressionAlgorithm.GZip -> {
// In databaseV4 the header is zipped during the save, so not necessary here
if (kdbxVersion.toKotlinLong() >= FILE_VERSION_32_4.toKotlinLong()) {
decompressAllBinaries()
} else {
if (kdbxVersion.isBefore(FILE_VERSION_32_4)) {
when (newCompression) {
CompressionAlgorithm.None -> {
decompressAllBinaries()
@@ -205,6 +203,8 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
CompressionAlgorithm.GZip -> {
}
}
} else {
decompressAllBinaries()
}
}
}

View File

@@ -167,7 +167,7 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
private fun readHeaderField(dis: InputStream): Boolean {
val fieldID = dis.read().toByte()
val fieldSize: Int = if (version.toKotlinLong() < FILE_VERSION_32_4.toKotlinLong()) {
val fieldSize: Int = if (version.isBefore(FILE_VERSION_32_4)) {
dis.readBytes2ToUShort()
} else {
dis.readBytes4ToUInt().toKotlinInt()
@@ -194,20 +194,20 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
PwDbHeaderV4Fields.MasterSeed -> masterSeed = fieldData
PwDbHeaderV4Fields.TransformSeed -> if (version.toKotlinLong() < FILE_VERSION_32_4.toKotlinLong())
PwDbHeaderV4Fields.TransformSeed -> if (version.isBefore(FILE_VERSION_32_4))
transformSeed = fieldData
PwDbHeaderV4Fields.TransformRounds -> if (version.toKotlinLong() < FILE_VERSION_32_4.toKotlinLong())
PwDbHeaderV4Fields.TransformRounds -> if (version.isBefore(FILE_VERSION_32_4))
setTransformRound(fieldData)
PwDbHeaderV4Fields.EncryptionIV -> encryptionIV = fieldData
PwDbHeaderV4Fields.InnerRandomstreamKey -> if (version.toKotlinLong() < FILE_VERSION_32_4.toKotlinLong())
PwDbHeaderV4Fields.InnerRandomstreamKey -> if (version.isBefore(FILE_VERSION_32_4))
innerRandomStreamKey = fieldData
PwDbHeaderV4Fields.StreamStartBytes -> streamStartBytes = fieldData
PwDbHeaderV4Fields.InnerRandomStreamID -> if (version.toKotlinLong() < FILE_VERSION_32_4.toKotlinLong())
PwDbHeaderV4Fields.InnerRandomStreamID -> if (version.isBefore(FILE_VERSION_32_4))
setRandomStreamID(fieldData)
PwDbHeaderV4Fields.KdfParameters -> databaseV4.kdfParameters = KdfParameters.deserialize(fieldData)

View File

@@ -42,6 +42,7 @@ import com.kunzisoft.keepass.database.element.node.NodeKDBXInterface
import com.kunzisoft.keepass.database.element.security.ProtectedString
import com.kunzisoft.keepass.database.exception.*
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX.Companion.FILE_VERSION_32_4
import com.kunzisoft.keepass.database.file.DatabaseKDBXXML
import com.kunzisoft.keepass.database.file.DateKDBXUtil
import com.kunzisoft.keepass.stream.HashedBlockInputStream
@@ -158,7 +159,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
}
val plainInputStream: InputStream
if (mDatabase.kdbxVersion.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (mDatabase.kdbxVersion.isBefore(FILE_VERSION_32_4)) {
val dataDecrypted = CipherInputStream(databaseInputStream, cipher)
val storedStartBytes: ByteArray?
@@ -207,7 +208,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
else -> plainInputStream
}
if (mDatabase.kdbxVersion.toKotlinLong() >= DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (!mDatabase.kdbxVersion.isBefore(FILE_VERSION_32_4)) {
readInnerHeader(inputStreamXml, header)
}
@@ -842,7 +843,13 @@ class DatabaseInputKDBX(cacheDirectory: File,
val sDate = readString(xpp)
var utcDate: Date? = null
if (mDatabase.kdbxVersion.toKotlinLong() >= DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (mDatabase.kdbxVersion.isBefore(FILE_VERSION_32_4)) {
try {
utcDate = DatabaseKDBXXML.DateFormatter.parse(sDate)
} catch (e: ParseException) {
// Catch with null test below
}
} else {
var buf = Base64.decode(sDate, BASE_64_FLAG)
if (buf.size != 8) {
val buf8 = ByteArray(8)
@@ -852,14 +859,6 @@ class DatabaseInputKDBX(cacheDirectory: File,
val seconds = bytes64ToLong(buf)
utcDate = DateKDBXUtil.convertKDBX4Time(seconds)
} else {
try {
utcDate = DatabaseKDBXXML.DateFormatter.parse(sDate)
} catch (e: ParseException) {
// Catch with null test below
}
}
return utcDate ?: Date(0L)

View File

@@ -27,6 +27,7 @@ import com.kunzisoft.keepass.database.element.database.DatabaseKDBX
import com.kunzisoft.keepass.database.exception.DatabaseOutputException
import com.kunzisoft.keepass.database.file.DatabaseHeader
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX.Companion.FILE_VERSION_32_4
import com.kunzisoft.keepass.stream.MacOutputStream
import com.kunzisoft.keepass.utils.*
import java.io.ByteArrayOutputStream
@@ -75,7 +76,7 @@ constructor(private val databaseKDBX: DatabaseKDBX,
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.CompressionFlags, uIntTo4Bytes(DatabaseHeaderKDBX.getFlagFromCompression(databaseKDBX.compressionAlgorithm)))
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.MasterSeed, header.masterSeed)
if (header.version.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (header.version.isBefore(FILE_VERSION_32_4)) {
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.TransformSeed, header.transformSeed)
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.TransformRounds, longTo8Bytes(databaseKDBX.numberKeyEncryptionRounds))
} else {
@@ -86,7 +87,7 @@ constructor(private val databaseKDBX: DatabaseKDBX,
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.EncryptionIV, header.encryptionIV)
}
if (header.version.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (header.version.isBefore(FILE_VERSION_32_4)) {
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.InnerRandomstreamKey, header.innerRandomStreamKey)
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.StreamStartBytes, header.streamStartBytes)
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.InnerRandomStreamID, uIntTo4Bytes(header.innerRandomStream!!.id))
@@ -120,7 +121,7 @@ constructor(private val databaseKDBX: DatabaseKDBX,
@Throws(IOException::class)
private fun writeHeaderFieldSize(size: Int) {
if (header.version.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (header.version.isBefore(FILE_VERSION_32_4)) {
mos.write2BytesUShort(size)
} else {
mos.write4BytesUInt(UnsignedInt(size))

View File

@@ -41,6 +41,7 @@ import com.kunzisoft.keepass.database.element.security.ProtectedString
import com.kunzisoft.keepass.database.exception.DatabaseOutputException
import com.kunzisoft.keepass.database.exception.UnknownKDF
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX.Companion.FILE_VERSION_32_4
import com.kunzisoft.keepass.database.file.DatabaseKDBXXML
import com.kunzisoft.keepass.database.file.DateKDBXUtil
import com.kunzisoft.keepass.stream.HashedBlockOutputStream
@@ -82,7 +83,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
header = outputHeader(mOutputStream)
val osPlain: OutputStream = if (header!!.version.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
val osPlain: OutputStream = if (header!!.version.isBefore(FILE_VERSION_32_4)) {
val cos = attachStreamEncryptor(header!!, mOutputStream)
cos.write(header!!.streamStartBytes)
@@ -101,7 +102,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
else -> osPlain
}
if (header!!.version.toKotlinLong() >= DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (!header!!.version.isBefore(FILE_VERSION_32_4)) {
outputInnerHeader(mDatabaseKDBX, header!!, xmlOutputStream)
}
@@ -266,7 +267,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
writeUuid(DatabaseKDBXXML.ElemLastTopVisibleGroup, mDatabaseKDBX.lastTopVisibleGroupUUID)
// Seem to work properly if always in meta
if (header!!.version.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong())
if (header!!.version.isBefore(FILE_VERSION_32_4))
writeMetaBinaries()
writeCustomData(mDatabaseKDBX.customData)
@@ -308,7 +309,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
Log.e(TAG, "Unable to retrieve header", unknownKDF)
}
if (header.version.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (header.version.isBefore(FILE_VERSION_32_4)) {
header.innerRandomStream = CrsAlgorithm.Salsa20
header.innerRandomStreamKey = ByteArray(32)
} else {
@@ -323,7 +324,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
throw DatabaseOutputException(e)
}
if (header.version.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (header.version.isBefore(FILE_VERSION_32_4)) {
random.nextBytes(header.streamStartBytes)
}
@@ -422,7 +423,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
private fun writeObject(name: String, value: Date) {
if (header!!.version.toKotlinLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toKotlinLong()) {
if (header!!.version.isBefore(FILE_VERSION_32_4)) {
writeObject(name, DatabaseKDBXXML.DateFormatter.format(value))
} else {
val dt = DateTime(value)

View File

@@ -19,6 +19,8 @@
*/
package com.kunzisoft.keepass.utils
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX
class UnsignedInt(private var unsignedValue: Int) {
constructor(unsignedValue: UnsignedInt) : this(unsignedValue.toKotlinInt())
@@ -44,6 +46,11 @@ class UnsignedInt(private var unsignedValue: Int) {
return (unsignedValue and 0xFF).toByte()
}
fun isBefore(value: UnsignedInt): Boolean {
return toKotlinLong() < value.toKotlinLong()
}
override fun toString():String {
return toKotlinLong().toString()
}