mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Add UnsignedInt and UnsignedLong
This commit is contained in:
@@ -118,4 +118,7 @@ dependencies {
|
||||
// Icon pack
|
||||
implementation project(path: ':icon-pack-classic')
|
||||
implementation project(path: ':icon-pack-material')
|
||||
|
||||
// Tests
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
package com.kunzisoft.keepass.tests
|
||||
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX.Companion.ULONG_MAX_VALUE
|
||||
import com.kunzisoft.keepass.stream.*
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import com.kunzisoft.keepass.utils.UnsignedLong
|
||||
import junit.framework.TestCase
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
import java.io.ByteArrayOutputStream
|
||||
@@ -77,8 +78,8 @@ class StringDatabaseKDBUtilsTest : TestCase() {
|
||||
|
||||
setArray(orig, value, 4)
|
||||
|
||||
val one = bytes4ToInt(orig)
|
||||
val dest = intTo4Bytes(one)
|
||||
val one = bytes4ToUInt(orig)
|
||||
val dest = uIntTo4Bytes(one)
|
||||
|
||||
assertArrayEquals(orig, dest)
|
||||
|
||||
@@ -133,7 +134,7 @@ class StringDatabaseKDBUtilsTest : TestCase() {
|
||||
}
|
||||
|
||||
private fun testReadWriteByte(value: Byte) {
|
||||
val dest: Byte = uIntToByte(byteToUInt(value))
|
||||
val dest: Byte = UnsignedInt(UnsignedInt.fromByte(value)).toByte()
|
||||
assert(value == dest)
|
||||
}
|
||||
|
||||
@@ -185,7 +186,7 @@ class StringDatabaseKDBUtilsTest : TestCase() {
|
||||
|
||||
val bos = ByteArrayOutputStream()
|
||||
val leos = LittleEndianDataOutputStream(bos)
|
||||
leos.writeLong(ULONG_MAX_VALUE)
|
||||
leos.writeLong(UnsignedLong.ULONG_MAX_VALUE)
|
||||
leos.close()
|
||||
|
||||
val uLongMax = bos.toByteArray()
|
||||
|
||||
@@ -26,8 +26,8 @@ import java.util.Random
|
||||
|
||||
import junit.framework.TestCase
|
||||
|
||||
import com.kunzisoft.keepass.crypto.finalkey.AndroidFinalKey
|
||||
import com.kunzisoft.keepass.crypto.finalkey.NativeFinalKey
|
||||
import com.kunzisoft.keepass.crypto.finalkey.AndroidAESKeyTransformer
|
||||
import com.kunzisoft.keepass.crypto.finalkey.NativeAESKeyTransformer
|
||||
|
||||
class FinalKeyTest : TestCase() {
|
||||
private var mRand: Random? = null
|
||||
@@ -56,10 +56,10 @@ class FinalKeyTest : TestCase() {
|
||||
mRand!!.nextBytes(seed)
|
||||
mRand!!.nextBytes(key)
|
||||
|
||||
val aKey = AndroidFinalKey()
|
||||
val aKey = AndroidAESKeyTransformer()
|
||||
androidKey = aKey.transformMasterKey(seed, key, rounds.toLong())
|
||||
|
||||
val nKey = NativeFinalKey()
|
||||
val nKey = NativeAESKeyTransformer()
|
||||
nativeKey = nKey.transformMasterKey(seed, key, rounds.toLong())
|
||||
|
||||
assertArrayEquals("Does not match", androidKey, nativeKey)
|
||||
|
||||
@@ -19,16 +19,18 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.crypto
|
||||
|
||||
enum class CrsAlgorithm constructor(val id: Int) {
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
|
||||
Null(0),
|
||||
ArcFourVariant(1),
|
||||
Salsa20(2),
|
||||
ChaCha20(3);
|
||||
enum class CrsAlgorithm constructor(val id: UnsignedInt) {
|
||||
|
||||
Null(UnsignedInt(0)),
|
||||
ArcFourVariant(UnsignedInt(1)),
|
||||
Salsa20(UnsignedInt(2)),
|
||||
ChaCha20(UnsignedInt(3));
|
||||
|
||||
companion object {
|
||||
|
||||
fun fromId(num: Int): CrsAlgorithm? {
|
||||
fun fromId(num: UnsignedInt): CrsAlgorithm? {
|
||||
for (e in values()) {
|
||||
if (e.id == num) {
|
||||
return e
|
||||
|
||||
@@ -30,7 +30,7 @@ object NativeLib {
|
||||
fun init(): Boolean {
|
||||
if (!isLoaded) {
|
||||
try {
|
||||
System.loadLibrary("final-key")
|
||||
System.loadLibrary("final-key") // TODO Rename
|
||||
System.loadLibrary("argon2")
|
||||
} catch (e: UnsatisfiedLinkError) {
|
||||
return false
|
||||
|
||||
@@ -21,14 +21,17 @@ package com.kunzisoft.keepass.crypto.finalkey;
|
||||
|
||||
import com.kunzisoft.keepass.crypto.CipherFactory;
|
||||
|
||||
public class FinalKeyFactory {
|
||||
public static FinalKey createFinalKey() {
|
||||
public class AESFactory {
|
||||
|
||||
// TODO Encaspulate
|
||||
public static KeyTransformer createFinalKey() {
|
||||
// Prefer the native final key implementation
|
||||
if ( !CipherFactory.INSTANCE.deviceBlacklisted() && NativeFinalKey.available() ) {
|
||||
return new NativeFinalKey();
|
||||
if ( !CipherFactory.INSTANCE.deviceBlacklisted()
|
||||
&& NativeAESKeyTransformer.available() ) {
|
||||
return new NativeAESKeyTransformer();
|
||||
} else {
|
||||
// Fall back on the android crypto implementation
|
||||
return new AndroidFinalKey();
|
||||
return new AndroidAESKeyTransformer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class AndroidFinalKey extends FinalKey {
|
||||
public class AndroidAESKeyTransformer extends KeyTransformer {
|
||||
|
||||
@Override
|
||||
public byte[] transformMasterKey(byte[] pKeySeed, byte[] pKey, long rounds) throws IOException {
|
||||
@@ -21,6 +21,6 @@ package com.kunzisoft.keepass.crypto.finalkey;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class FinalKey {
|
||||
public abstract class KeyTransformer {
|
||||
public abstract byte[] transformMasterKey(byte[] seed, byte[] key, long rounds) throws IOException;
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import com.kunzisoft.keepass.crypto.NativeLib;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
public class NativeFinalKey extends FinalKey {
|
||||
public class NativeAESKeyTransformer extends KeyTransformer {
|
||||
|
||||
public static boolean available() {
|
||||
return NativeLib.INSTANCE.init();
|
||||
@@ -22,8 +22,9 @@ package com.kunzisoft.keepass.crypto.keyDerivation
|
||||
import android.content.res.Resources
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.crypto.CryptoUtil
|
||||
import com.kunzisoft.keepass.crypto.finalkey.FinalKeyFactory
|
||||
import com.kunzisoft.keepass.crypto.finalkey.AESFactory
|
||||
import com.kunzisoft.keepass.stream.bytes16ToUuid
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
@@ -34,12 +35,11 @@ class AesKdf internal constructor() : KdfEngine() {
|
||||
get() {
|
||||
return KdfParameters(uuid!!).apply {
|
||||
setParamUUID()
|
||||
setUInt32(PARAM_ROUNDS, DEFAULT_ROUNDS.toLong())
|
||||
setUInt32(PARAM_ROUNDS, UnsignedInt.fromLong(defaultKeyRounds))
|
||||
}
|
||||
}
|
||||
|
||||
override val defaultKeyRounds: Long
|
||||
get() = DEFAULT_ROUNDS.toLong()
|
||||
override val defaultKeyRounds: Long = 6000L
|
||||
|
||||
init {
|
||||
uuid = CIPHER_UUID
|
||||
@@ -63,8 +63,7 @@ class AesKdf internal constructor() : KdfEngine() {
|
||||
seed = CryptoUtil.hashSha256(seed)
|
||||
}
|
||||
|
||||
val key = FinalKeyFactory.createFinalKey()
|
||||
return key.transformMasterKey(seed, currentMasterKey, rounds)
|
||||
return AESFactory.createFinalKey().transformMasterKey(seed, currentMasterKey, rounds)
|
||||
}
|
||||
|
||||
override fun randomize(p: KdfParameters) {
|
||||
@@ -86,8 +85,6 @@ class AesKdf internal constructor() : KdfEngine() {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val DEFAULT_ROUNDS = 6000
|
||||
|
||||
val CIPHER_UUID: UUID = bytes16ToUuid(
|
||||
byteArrayOf(0xC9.toByte(),
|
||||
0xD9.toByte(),
|
||||
|
||||
@@ -22,6 +22,7 @@ package com.kunzisoft.keepass.crypto.keyDerivation
|
||||
import android.content.res.Resources
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.stream.bytes16ToUuid
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
@@ -56,15 +57,21 @@ class Argon2Kdf internal constructor() : KdfEngine() {
|
||||
override fun transform(masterKey: ByteArray, p: KdfParameters): ByteArray {
|
||||
|
||||
val salt = p.getByteArray(PARAM_SALT)
|
||||
val parallelism = p.getUInt32(PARAM_PARALLELISM).toInt()
|
||||
val memory = p.getUInt64(PARAM_MEMORY)
|
||||
val iterations = p.getUInt64(PARAM_ITERATIONS)
|
||||
val version = p.getUInt32(PARAM_VERSION)
|
||||
val parallelism = UnsignedInt(p.getUInt32(PARAM_PARALLELISM))
|
||||
val memory = UnsignedInt.fromLong(p.getUInt64(PARAM_MEMORY) / MEMORY_BLOCK_SIZE)
|
||||
val iterations = UnsignedInt.fromLong(p.getUInt64(PARAM_ITERATIONS))
|
||||
val version = UnsignedInt(p.getUInt32(PARAM_VERSION))
|
||||
val secretKey = p.getByteArray(PARAM_SECRET_KEY)
|
||||
val assocData = p.getByteArray(PARAM_ASSOC_DATA)
|
||||
|
||||
return Argon2Native.transformKey(masterKey, salt, parallelism, memory, iterations,
|
||||
secretKey, assocData, version)
|
||||
return Argon2Native.transformKey(masterKey,
|
||||
salt,
|
||||
parallelism,
|
||||
memory,
|
||||
iterations,
|
||||
secretKey,
|
||||
assocData,
|
||||
version)
|
||||
}
|
||||
|
||||
override fun randomize(p: KdfParameters) {
|
||||
@@ -107,21 +114,21 @@ class Argon2Kdf internal constructor() : KdfEngine() {
|
||||
override val maxMemoryUsage: Long
|
||||
get() = MAX_MEMORY
|
||||
|
||||
override fun getParallelism(p: KdfParameters): Int {
|
||||
return p.getUInt32(PARAM_PARALLELISM).toInt() // TODO Verify #443
|
||||
override fun getParallelism(p: KdfParameters): Long {
|
||||
return UnsignedInt(p.getUInt32(PARAM_PARALLELISM)).toLong()
|
||||
}
|
||||
|
||||
override fun setParallelism(p: KdfParameters, parallelism: Int) {
|
||||
p.setUInt32(PARAM_PARALLELISM, parallelism.toLong())
|
||||
override fun setParallelism(p: KdfParameters, parallelism: Long) {
|
||||
p.setUInt32(PARAM_PARALLELISM, UnsignedInt.fromLong(parallelism))
|
||||
}
|
||||
|
||||
override val defaultParallelism: Int
|
||||
get() = DEFAULT_PARALLELISM.toInt()
|
||||
override val defaultParallelism: Long
|
||||
get() = DEFAULT_PARALLELISM.toLong()
|
||||
|
||||
override val minParallelism: Int
|
||||
override val minParallelism: Long
|
||||
get() = MIN_PARALLELISM
|
||||
|
||||
override val maxParallelism: Int
|
||||
override val maxParallelism: Long
|
||||
get() = MAX_PARALLELISM
|
||||
|
||||
companion object {
|
||||
@@ -152,23 +159,24 @@ class Argon2Kdf internal constructor() : KdfEngine() {
|
||||
private const val PARAM_SECRET_KEY = "K" // byte[]
|
||||
private const val PARAM_ASSOC_DATA = "A" // byte[]
|
||||
|
||||
private const val MIN_VERSION: Long = 0x10
|
||||
private const val MAX_VERSION: Long = 0x13
|
||||
private val MIN_VERSION = UnsignedInt(0x10)
|
||||
private val MAX_VERSION = UnsignedInt(0x13)
|
||||
|
||||
private const val MIN_SALT = 8
|
||||
private const val MAX_SALT = Integer.MAX_VALUE
|
||||
private val MAX_SALT = UnsignedInt.MAX_VALUE.toLong()
|
||||
|
||||
private const val MIN_ITERATIONS: Long = 1
|
||||
private const val MIN_ITERATIONS: Long = 1L
|
||||
private const val MAX_ITERATIONS = 4294967295L
|
||||
|
||||
private const val MIN_MEMORY = (1024 * 8).toLong()
|
||||
private const val MAX_MEMORY = Integer.MAX_VALUE.toLong()
|
||||
private val MAX_MEMORY = UnsignedInt.MAX_VALUE.toLong()
|
||||
private const val MEMORY_BLOCK_SIZE: Long = 1024L
|
||||
|
||||
private const val MIN_PARALLELISM = 1
|
||||
private const val MAX_PARALLELISM = (1 shl 24) - 1
|
||||
private const val MIN_PARALLELISM: Long = 1L
|
||||
private const val MAX_PARALLELISM: Long = ((1 shl 24) - 1).toLong()
|
||||
|
||||
private const val DEFAULT_ITERATIONS: Long = 2
|
||||
private const val DEFAULT_ITERATIONS: Long = 2L
|
||||
private const val DEFAULT_MEMORY = (1024 * 1024).toLong()
|
||||
private const val DEFAULT_PARALLELISM: Long = 2
|
||||
private val DEFAULT_PARALLELISM = UnsignedInt(2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,20 +20,29 @@
|
||||
package com.kunzisoft.keepass.crypto.keyDerivation;
|
||||
|
||||
import com.kunzisoft.keepass.crypto.NativeLib;
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Argon2Native {
|
||||
|
||||
public static byte[] transformKey(byte[] password, byte[] salt, int parallelism,
|
||||
long memory, long iterations, byte[] secretKey,
|
||||
byte[] associatedData, long version) throws IOException {
|
||||
public static byte[] transformKey(byte[] password, byte[] salt, UnsignedInt parallelism,
|
||||
UnsignedInt memory, UnsignedInt iterations, byte[] secretKey,
|
||||
byte[] associatedData, UnsignedInt version) throws IOException {
|
||||
NativeLib.INSTANCE.init();
|
||||
|
||||
return nTransformMasterKey(password, salt, parallelism, memory, iterations, secretKey, associatedData, version);
|
||||
return nTransformMasterKey(
|
||||
password,
|
||||
salt,
|
||||
parallelism.toInt(),
|
||||
memory.toInt(),
|
||||
iterations.toInt(),
|
||||
secretKey,
|
||||
associatedData,
|
||||
version.toInt());
|
||||
}
|
||||
|
||||
private static native byte[] nTransformMasterKey(byte[] password, byte[] salt, int parallelism,
|
||||
long memory, long iterations, byte[] secretKey,
|
||||
byte[] associatedData, long version) throws IOException;
|
||||
int memory, int iterations, byte[] secretKey,
|
||||
byte[] associatedData, int version) throws IOException;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package com.kunzisoft.keepass.crypto.keyDerivation
|
||||
|
||||
import com.kunzisoft.keepass.utils.ObjectNameResource
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.Serializable
|
||||
@@ -51,14 +52,14 @@ abstract class KdfEngine : ObjectNameResource, Serializable {
|
||||
get() = 1
|
||||
|
||||
open val maxKeyRounds: Long
|
||||
get() = Int.MAX_VALUE.toLong()
|
||||
get() = UnsignedInt.MAX_VALUE.toLong()
|
||||
|
||||
/*
|
||||
* MEMORY
|
||||
*/
|
||||
|
||||
open fun getMemoryUsage(p: KdfParameters): Long {
|
||||
return UNKNOWN_VALUE.toLong()
|
||||
return UNKNOWN_VALUE
|
||||
}
|
||||
|
||||
open fun setMemoryUsage(p: KdfParameters, memory: Long) {
|
||||
@@ -66,36 +67,36 @@ abstract class KdfEngine : ObjectNameResource, Serializable {
|
||||
}
|
||||
|
||||
open val defaultMemoryUsage: Long
|
||||
get() = UNKNOWN_VALUE.toLong()
|
||||
get() = UNKNOWN_VALUE
|
||||
|
||||
open val minMemoryUsage: Long
|
||||
get() = 1
|
||||
|
||||
open val maxMemoryUsage: Long
|
||||
get() = Int.MAX_VALUE.toLong()
|
||||
get() = UnsignedInt.MAX_VALUE.toLong()
|
||||
|
||||
/*
|
||||
* PARALLELISM
|
||||
*/
|
||||
|
||||
open fun getParallelism(p: KdfParameters): Int {
|
||||
open fun getParallelism(p: KdfParameters): Long {
|
||||
return UNKNOWN_VALUE
|
||||
}
|
||||
|
||||
open fun setParallelism(p: KdfParameters, parallelism: Int) {
|
||||
open fun setParallelism(p: KdfParameters, parallelism: Long) {
|
||||
// Do nothing by default
|
||||
}
|
||||
|
||||
open val defaultParallelism: Int
|
||||
open val defaultParallelism: Long
|
||||
get() = UNKNOWN_VALUE
|
||||
|
||||
open val minParallelism: Int
|
||||
get() = 1
|
||||
open val minParallelism: Long
|
||||
get() = 1L
|
||||
|
||||
open val maxParallelism: Int
|
||||
get() = Int.MAX_VALUE
|
||||
open val maxParallelism: Long
|
||||
get() = UnsignedInt.MAX_VALUE.toLong()
|
||||
|
||||
companion object {
|
||||
const val UNKNOWN_VALUE = -1
|
||||
const val UNKNOWN_VALUE: Long = -1L
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,12 +552,12 @@ class ProgressDialogThread(private val activity: FragmentActivity) {
|
||||
, ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK)
|
||||
}
|
||||
|
||||
fun startDatabaseSaveParallelism(oldParallelism: Int,
|
||||
newParallelism: Int,
|
||||
fun startDatabaseSaveParallelism(oldParallelism: Long,
|
||||
newParallelism: Long,
|
||||
save: Boolean) {
|
||||
start(Bundle().apply {
|
||||
putInt(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldParallelism)
|
||||
putInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newParallelism)
|
||||
putLong(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldParallelism)
|
||||
putLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newParallelism)
|
||||
putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save)
|
||||
}
|
||||
, ACTION_DATABASE_UPDATE_PARALLELISM_TASK)
|
||||
|
||||
@@ -47,7 +47,7 @@ import com.kunzisoft.keepass.database.search.SearchHelper
|
||||
import com.kunzisoft.keepass.database.search.SearchParameters
|
||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||
import com.kunzisoft.keepass.model.SearchInfo
|
||||
import com.kunzisoft.keepass.stream.readBytes4ToInt
|
||||
import com.kunzisoft.keepass.stream.readBytes4ToUInt
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.SingletonHolder
|
||||
import com.kunzisoft.keepass.utils.UriUtil
|
||||
@@ -206,7 +206,6 @@ class Database {
|
||||
|
||||
var numberKeyEncryptionRounds: Long
|
||||
get() = mDatabaseKDB?.numberKeyEncryptionRounds ?: mDatabaseKDBX?.numberKeyEncryptionRounds ?: 0
|
||||
@Throws(NumberFormatException::class)
|
||||
set(numberRounds) {
|
||||
mDatabaseKDB?.numberKeyEncryptionRounds = numberRounds
|
||||
mDatabaseKDBX?.numberKeyEncryptionRounds = numberRounds
|
||||
@@ -214,13 +213,13 @@ class Database {
|
||||
|
||||
var memoryUsage: Long
|
||||
get() {
|
||||
return mDatabaseKDBX?.memoryUsage ?: return KdfEngine.UNKNOWN_VALUE.toLong()
|
||||
return mDatabaseKDBX?.memoryUsage ?: return KdfEngine.UNKNOWN_VALUE
|
||||
}
|
||||
set(memory) {
|
||||
mDatabaseKDBX?.memoryUsage = memory
|
||||
}
|
||||
|
||||
var parallelism: Int
|
||||
var parallelism: Long
|
||||
get() = mDatabaseKDBX?.parallelism ?: KdfEngine.UNKNOWN_VALUE
|
||||
set(parallelism) {
|
||||
mDatabaseKDBX?.parallelism = parallelism
|
||||
@@ -348,8 +347,8 @@ class Database {
|
||||
databaseInputStream.mark(10)
|
||||
|
||||
// Get the file directory to save the attachments
|
||||
val sig1 = databaseInputStream.readBytes4ToInt()
|
||||
val sig2 = databaseInputStream.readBytes4ToInt()
|
||||
val sig1 = databaseInputStream.readBytes4ToUInt()
|
||||
val sig2 = databaseInputStream.readBytes4ToUInt()
|
||||
|
||||
// Return to the start
|
||||
databaseInputStream.reset()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
package com.kunzisoft.keepass.database.element.database
|
||||
|
||||
import com.kunzisoft.keepass.crypto.finalkey.FinalKeyFactory
|
||||
import com.kunzisoft.keepass.crypto.finalkey.AESFactory
|
||||
import com.kunzisoft.keepass.crypto.keyDerivation.KdfEngine
|
||||
import com.kunzisoft.keepass.crypto.keyDerivation.KdfFactory
|
||||
import com.kunzisoft.keepass.database.element.entry.EntryKDB
|
||||
@@ -38,8 +38,6 @@ import kotlin.collections.ArrayList
|
||||
|
||||
class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
|
||||
|
||||
private var numKeyEncRounds: Int = 0
|
||||
|
||||
var backupGroupId: Int = BACKUP_FOLDER_UNDEFINED_ID
|
||||
|
||||
private var kdfListV3: MutableList<KdfEngine> = ArrayList()
|
||||
@@ -87,19 +85,10 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
|
||||
override val passwordEncoding: String
|
||||
get() = "ISO-8859-1"
|
||||
|
||||
override var numberKeyEncryptionRounds: Long
|
||||
get() = numKeyEncRounds.toLong()
|
||||
@Throws(NumberFormatException::class)
|
||||
set(rounds) {
|
||||
if (rounds > Integer.MAX_VALUE || rounds < Integer.MIN_VALUE) {
|
||||
throw NumberFormatException()
|
||||
}
|
||||
numKeyEncRounds = rounds.toInt()
|
||||
}
|
||||
override var numberKeyEncryptionRounds = 300L
|
||||
|
||||
init {
|
||||
algorithm = EncryptionAlgorithm.AESRijndael
|
||||
numKeyEncRounds = DEFAULT_ENCRYPTION_ROUNDS
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,9 +147,9 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
|
||||
val nos = NullOutputStream()
|
||||
val dos = DigestOutputStream(nos, messageDigest)
|
||||
|
||||
val transformedMasterKey = transformMasterKey(masterSeed2, masterKey, numRounds)
|
||||
// Encrypt the master key a few times to make brute-force key-search harder
|
||||
dos.write(masterSeed)
|
||||
dos.write(transformedMasterKey)
|
||||
dos.write(AESFactory.createFinalKey().transformMasterKey(masterSeed2, masterKey, numRounds))
|
||||
|
||||
finalKey = messageDigest.digest()
|
||||
}
|
||||
@@ -266,19 +255,6 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
|
||||
const val BACKUP_FOLDER_TITLE = "Backup"
|
||||
private const val BACKUP_FOLDER_UNDEFINED_ID = -1
|
||||
|
||||
private const val DEFAULT_ENCRYPTION_ROUNDS = 300
|
||||
|
||||
const val BUFFER_SIZE_BYTES = 3 * 128
|
||||
|
||||
/**
|
||||
* Encrypt the master key a few times to make brute-force key-search harder
|
||||
* @throws IOException
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
private fun transformMasterKey(pKeySeed: ByteArray, pKey: ByteArray, rounds: Long): ByteArray {
|
||||
val key = FinalKeyFactory.createFinalKey()
|
||||
|
||||
return key.transformMasterKey(pKeySeed, pKey, rounds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import com.kunzisoft.keepass.database.element.security.MemoryProtectionConfig
|
||||
import com.kunzisoft.keepass.database.exception.UnknownKDF
|
||||
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX.Companion.FILE_VERSION_32_3
|
||||
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDBX.Companion.FILE_VERSION_32_4
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import com.kunzisoft.keepass.utils.VariantDictionary
|
||||
import org.w3c.dom.Node
|
||||
import org.w3c.dom.Text
|
||||
@@ -67,7 +68,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
private var numKeyEncRounds: Long = 0
|
||||
var publicCustomData = VariantDictionary()
|
||||
|
||||
var kdbxVersion: Long = 0
|
||||
var kdbxVersion = UnsignedInt(0)
|
||||
var name = ""
|
||||
var nameChanged = DateInstant()
|
||||
// TODO change setting date
|
||||
@@ -83,7 +84,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
var keyChangeForceDays: Long = 1
|
||||
var isKeyChangeForceOnce = false
|
||||
|
||||
var maintenanceHistoryDays: Long = 365
|
||||
var maintenanceHistoryDays = UnsignedInt(365)
|
||||
var color = ""
|
||||
/**
|
||||
* Determine if RecycleBin is enable or not
|
||||
@@ -219,7 +220,6 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
numKeyEncRounds = kdfEngine.getKeyRounds(kdfParameters!!)
|
||||
return numKeyEncRounds
|
||||
}
|
||||
@Throws(NumberFormatException::class)
|
||||
set(rounds) {
|
||||
val kdfEngine = kdfEngine
|
||||
if (kdfEngine != null && kdfParameters != null)
|
||||
@@ -232,7 +232,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
val kdfEngine = kdfEngine
|
||||
return if (kdfEngine != null && kdfParameters != null) {
|
||||
kdfEngine.getMemoryUsage(kdfParameters!!)
|
||||
} else KdfEngine.UNKNOWN_VALUE.toLong()
|
||||
} else KdfEngine.UNKNOWN_VALUE
|
||||
}
|
||||
set(memory) {
|
||||
val kdfEngine = kdfEngine
|
||||
@@ -240,7 +240,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
kdfEngine.setMemoryUsage(kdfParameters!!, memory)
|
||||
}
|
||||
|
||||
var parallelism: Int
|
||||
var parallelism: Long
|
||||
get() {
|
||||
val kdfEngine = kdfEngine
|
||||
return if (kdfEngine != null && kdfParameters != null) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
import com.kunzisoft.keepass.utils.ParcelableUtil
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
|
||||
import java.util.HashMap
|
||||
|
||||
@@ -46,7 +47,7 @@ class AutoType : Parcelable {
|
||||
|
||||
constructor(parcel: Parcel) {
|
||||
this.enabled = parcel.readByte().toInt() != 0
|
||||
this.obfuscationOptions = parcel.readLong()
|
||||
this.obfuscationOptions = UnsignedInt(parcel.readInt())
|
||||
this.defaultSequence = parcel.readString() ?: defaultSequence
|
||||
this.windowSeqPairs = ParcelableUtil.readStringParcelableMap(parcel)
|
||||
}
|
||||
@@ -57,7 +58,7 @@ class AutoType : Parcelable {
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
dest.writeByte((if (enabled) 1 else 0).toByte())
|
||||
dest.writeLong(obfuscationOptions)
|
||||
dest.writeInt(obfuscationOptions.toInt())
|
||||
dest.writeString(defaultSequence)
|
||||
ParcelableUtil.writeStringParcelableMap(dest, windowSeqPairs)
|
||||
}
|
||||
@@ -71,7 +72,7 @@ class AutoType : Parcelable {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val OBF_OPT_NONE: Long = 0
|
||||
private val OBF_OPT_NONE = UnsignedInt(0)
|
||||
|
||||
@JvmField
|
||||
val CREATOR: Parcelable.Creator<AutoType> = object : Parcelable.Creator<AutoType> {
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.database.element.security.BinaryAttachment
|
||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
||||
import com.kunzisoft.keepass.utils.ParcelableUtil
|
||||
import com.kunzisoft.keepass.utils.UnsignedLong
|
||||
import java.util.*
|
||||
|
||||
class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInterface {
|
||||
@@ -104,7 +105,7 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
||||
|
||||
constructor(parcel: Parcel) : super(parcel) {
|
||||
iconCustom = parcel.readParcelable(IconImageCustom::class.java.classLoader) ?: iconCustom
|
||||
usageCount = parcel.readLong()
|
||||
usageCount = UnsignedLong(parcel.readLong())
|
||||
locationChanged = parcel.readParcelable(DateInstant::class.java.classLoader) ?: locationChanged
|
||||
customData = ParcelableUtil.readStringParcelableMap(parcel)
|
||||
fields = ParcelableUtil.readStringParcelableMap(parcel, ProtectedString::class.java)
|
||||
@@ -122,7 +123,7 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
super.writeToParcel(dest, flags)
|
||||
dest.writeParcelable(iconCustom, flags)
|
||||
dest.writeLong(usageCount)
|
||||
dest.writeLong(usageCount.toLong())
|
||||
dest.writeParcelable(locationChanged, flags)
|
||||
ParcelableUtil.writeStringParcelableMap(dest, customData)
|
||||
ParcelableUtil.writeStringParcelableMap(dest, flags, fields)
|
||||
@@ -243,7 +244,7 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
||||
fields[STR_NOTES] = ProtectedString(protect, value)
|
||||
}
|
||||
|
||||
override var usageCount: Long = 0
|
||||
override var usageCount = UnsignedLong(0)
|
||||
|
||||
override var locationChanged = DateInstant()
|
||||
|
||||
@@ -332,7 +333,8 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
||||
|
||||
override fun touch(modified: Boolean, touchParents: Boolean) {
|
||||
super.touch(modified, touchParents)
|
||||
++usageCount
|
||||
// TODO unsigned long
|
||||
usageCount = UnsignedLong(usageCount.toLong() + 1)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -32,14 +32,14 @@ import java.util.*
|
||||
class GroupKDB : GroupVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface {
|
||||
|
||||
var level = 0 // short
|
||||
/** Used by KeePass internally, don't use */
|
||||
var flags: Int = 0
|
||||
// Used by KeePass internally, don't use
|
||||
var groupFlags = 0
|
||||
|
||||
constructor() : super()
|
||||
|
||||
constructor(parcel: Parcel) : super(parcel) {
|
||||
level = parcel.readInt()
|
||||
flags = parcel.readInt()
|
||||
groupFlags = parcel.readInt()
|
||||
}
|
||||
|
||||
override fun readParentParcelable(parcel: Parcel): GroupKDB? {
|
||||
@@ -53,13 +53,13 @@ class GroupKDB : GroupVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
super.writeToParcel(dest, flags)
|
||||
dest.writeInt(level)
|
||||
dest.writeInt(flags)
|
||||
dest.writeInt(groupFlags)
|
||||
}
|
||||
|
||||
fun updateWith(source: GroupKDB) {
|
||||
super.updateWith(source)
|
||||
level = source.level
|
||||
flags = source.flags
|
||||
groupFlags = source.groupFlags
|
||||
}
|
||||
|
||||
override val type: Type
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.kunzisoft.keepass.database.element.node.NodeId
|
||||
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
|
||||
import com.kunzisoft.keepass.database.element.node.NodeKDBXInterface
|
||||
import com.kunzisoft.keepass.database.element.node.Type
|
||||
import com.kunzisoft.keepass.utils.UnsignedLong
|
||||
|
||||
import java.util.HashMap
|
||||
import java.util.UUID
|
||||
@@ -77,7 +78,7 @@ class GroupKDBX : GroupVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
||||
|
||||
constructor(parcel: Parcel) : super(parcel) {
|
||||
iconCustom = parcel.readParcelable(IconImageCustom::class.java.classLoader) ?: iconCustom
|
||||
usageCount = parcel.readLong()
|
||||
usageCount = UnsignedLong(parcel.readLong())
|
||||
locationChanged = parcel.readParcelable(DateInstant::class.java.classLoader) ?: locationChanged
|
||||
// TODO customData = ParcelableUtil.readStringParcelableMap(parcel);
|
||||
notes = parcel.readString() ?: notes
|
||||
@@ -101,7 +102,7 @@ class GroupKDBX : GroupVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
super.writeToParcel(dest, flags)
|
||||
dest.writeParcelable(iconCustom, flags)
|
||||
dest.writeLong(usageCount)
|
||||
dest.writeLong(usageCount.toLong())
|
||||
dest.writeParcelable(locationChanged, flags)
|
||||
// TODO ParcelableUtil.writeStringParcelableMap(dest, customData);
|
||||
dest.writeString(notes)
|
||||
@@ -130,7 +131,7 @@ class GroupKDBX : GroupVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
||||
lastTopVisibleEntry = source.lastTopVisibleEntry
|
||||
}
|
||||
|
||||
override var usageCount: Long = 0
|
||||
override var usageCount = UnsignedLong(0)
|
||||
|
||||
override var locationChanged = DateInstant()
|
||||
|
||||
|
||||
@@ -20,10 +20,11 @@
|
||||
package com.kunzisoft.keepass.database.element.node
|
||||
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.utils.UnsignedLong
|
||||
|
||||
interface NodeKDBXInterface : NodeTimeInterface {
|
||||
|
||||
var usageCount: Long
|
||||
var usageCount: UnsignedLong
|
||||
|
||||
var locationChanged: DateInstant
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.file
|
||||
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
|
||||
abstract class DatabaseHeader {
|
||||
|
||||
/**
|
||||
@@ -32,7 +34,7 @@ abstract class DatabaseHeader {
|
||||
var encryptionIV = ByteArray(16)
|
||||
|
||||
companion object {
|
||||
const val PWM_DBSIG_1 = -0x655d26fd
|
||||
val PWM_DBSIG_1 = UnsignedInt(-0x655d26fd)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
|
||||
package com.kunzisoft.keepass.database.file
|
||||
|
||||
import com.kunzisoft.keepass.stream.bytes4ToInt
|
||||
import com.kunzisoft.keepass.stream.readBytesLength
|
||||
import com.kunzisoft.keepass.stream.readBytes4ToInt
|
||||
import com.kunzisoft.keepass.stream.readBytes4ToUInt
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
@@ -34,15 +34,15 @@ class DatabaseHeaderKDB : DatabaseHeader() {
|
||||
*/
|
||||
var transformSeed = ByteArray(32)
|
||||
|
||||
var signature1: Int = 0 // = PWM_DBSIG_1
|
||||
var signature2: Int = 0 // = DBSIG_2
|
||||
var flags: Int = 0
|
||||
var version: Int = 0
|
||||
var signature1 = UnsignedInt(0) // = PWM_DBSIG_1
|
||||
var signature2 = UnsignedInt(0) // = DBSIG_2
|
||||
var flags= UnsignedInt(0)
|
||||
var version= UnsignedInt(0)
|
||||
|
||||
/** Number of groups in the database */
|
||||
var numGroups: Int = 0
|
||||
var numGroups = UnsignedInt(0)
|
||||
/** Number of entries in the database */
|
||||
var numEntries: Int = 0
|
||||
var numEntries = UnsignedInt(0)
|
||||
|
||||
/**
|
||||
* SHA-256 hash of the database, used for integrity check
|
||||
@@ -50,28 +50,24 @@ class DatabaseHeaderKDB : DatabaseHeader() {
|
||||
var contentsHash = ByteArray(32)
|
||||
|
||||
// As UInt
|
||||
var numKeyEncRounds: Int = 0
|
||||
var numKeyEncRounds = UnsignedInt(0)
|
||||
|
||||
/**
|
||||
* Parse given buf, as read from file.
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
fun loadFromFile(inputStream: InputStream) {
|
||||
signature1 = inputStream.readBytes4ToInt() // 4 bytes
|
||||
signature2 = inputStream.readBytes4ToInt() // 4 bytes
|
||||
flags = inputStream.readBytes4ToInt() // 4 bytes
|
||||
version = inputStream.readBytes4ToInt() // 4 bytes
|
||||
signature1 = inputStream.readBytes4ToUInt() // 4 bytes
|
||||
signature2 = inputStream.readBytes4ToUInt() // 4 bytes
|
||||
flags = inputStream.readBytes4ToUInt() // 4 bytes
|
||||
version = inputStream.readBytes4ToUInt() // 4 bytes
|
||||
masterSeed = inputStream.readBytesLength(16) // 16 bytes
|
||||
encryptionIV = inputStream.readBytesLength(16) // 16 bytes
|
||||
numGroups = inputStream.readBytes4ToInt() // 4 bytes
|
||||
numEntries = inputStream.readBytes4ToInt() // 4 bytes
|
||||
numGroups = inputStream.readBytes4ToUInt() // 4 bytes
|
||||
numEntries = inputStream.readBytes4ToUInt() // 4 bytes
|
||||
contentsHash = inputStream.readBytesLength(32) // 32 bytes
|
||||
transformSeed = inputStream.readBytesLength(32) // 32 bytes
|
||||
numKeyEncRounds = inputStream.readBytes4ToInt()
|
||||
if (numKeyEncRounds < 0) {
|
||||
// TODO: Really treat this like an unsigned integer #443
|
||||
throw IOException("Does not support more than " + Integer.MAX_VALUE + " rounds.")
|
||||
}
|
||||
numKeyEncRounds = inputStream.readBytes4ToUInt()
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -88,24 +84,24 @@ class DatabaseHeaderKDB : DatabaseHeader() {
|
||||
companion object {
|
||||
|
||||
// DB sig from KeePass 1.03
|
||||
const val DBSIG_2 = -0x4ab4049b
|
||||
val DBSIG_2 = UnsignedInt(-0x4ab4049b)
|
||||
// DB sig from KeePass 1.03
|
||||
const val DBVER_DW = 0x00030003
|
||||
val DBVER_DW = UnsignedInt(0x00030003)
|
||||
|
||||
const val FLAG_SHA2 = 1
|
||||
const val FLAG_RIJNDAEL = 2
|
||||
const val FLAG_ARCFOUR = 4
|
||||
const val FLAG_TWOFISH = 8
|
||||
val FLAG_SHA2 = UnsignedInt(1)
|
||||
val FLAG_RIJNDAEL = UnsignedInt(2)
|
||||
val FLAG_ARCFOUR = UnsignedInt(4)
|
||||
val FLAG_TWOFISH = UnsignedInt(8)
|
||||
|
||||
/** Size of byte buffer needed to hold this struct. */
|
||||
const val BUF_SIZE = 124
|
||||
|
||||
fun matchesHeader(sig1: Int, sig2: Int): Boolean {
|
||||
return sig1 == PWM_DBSIG_1 && sig2 == DBSIG_2
|
||||
fun matchesHeader(sig1: UnsignedInt, sig2: UnsignedInt): Boolean {
|
||||
return sig1.toInt() == PWM_DBSIG_1.toInt() && sig2.toInt() == DBSIG_2.toInt()
|
||||
}
|
||||
|
||||
fun compatibleHeaders(one: Int, two: Int): Boolean {
|
||||
return one and -0x100 == two and -0x100
|
||||
fun compatibleHeaders(one: UnsignedInt, two: UnsignedInt): Boolean {
|
||||
return one.toInt() and -0x100 == two.toInt() and -0x100
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019 Jeremy Jamet / Kunzisoft.
|
||||
* Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
@@ -31,6 +31,8 @@ import com.kunzisoft.keepass.database.element.group.GroupKDBX
|
||||
import com.kunzisoft.keepass.database.element.node.NodeKDBXInterface
|
||||
import com.kunzisoft.keepass.database.exception.VersionDatabaseException
|
||||
import com.kunzisoft.keepass.stream.*
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import com.kunzisoft.keepass.utils.UnsignedLong
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
@@ -45,7 +47,7 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
|
||||
var innerRandomStreamKey: ByteArray = ByteArray(32)
|
||||
var streamStartBytes: ByteArray = ByteArray(32)
|
||||
var innerRandomStream: CrsAlgorithm? = null
|
||||
var version: Long = 0
|
||||
var version: UnsignedInt = UnsignedInt(0)
|
||||
|
||||
// version < FILE_VERSION_32_4)
|
||||
var transformSeed: ByteArray?
|
||||
@@ -103,7 +105,7 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMinKdbxVersion(databaseV4: DatabaseKDBX): Long {
|
||||
private fun getMinKdbxVersion(databaseV4: DatabaseKDBX): UnsignedInt {
|
||||
// https://keepass.info/help/kb/kdbx_4.html
|
||||
|
||||
// Return v4 if AES is not use
|
||||
@@ -147,8 +149,8 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
|
||||
val digestInputStream = DigestInputStream(copyInputStream, messageDigest)
|
||||
val littleEndianDataInputStream = LittleEndianDataInputStream(digestInputStream)
|
||||
|
||||
val sig1 = littleEndianDataInputStream.readInt()
|
||||
val sig2 = littleEndianDataInputStream.readInt()
|
||||
val sig1 = littleEndianDataInputStream.readUInt()
|
||||
val sig2 = littleEndianDataInputStream.readUInt()
|
||||
|
||||
if (!matchesHeader(sig1, sig2)) {
|
||||
throw VersionDatabaseException()
|
||||
@@ -172,10 +174,10 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
|
||||
private fun readHeaderField(dis: LittleEndianDataInputStream): Boolean {
|
||||
val fieldID = dis.read().toByte()
|
||||
|
||||
val fieldSize: Int = if (version < FILE_VERSION_32_4) {
|
||||
val fieldSize: Int = if (version.toLong() < FILE_VERSION_32_4.toLong()) {
|
||||
dis.readUShort()
|
||||
} else {
|
||||
dis.readInt()
|
||||
dis.readUInt().toInt()
|
||||
}
|
||||
|
||||
var fieldData: ByteArray? = null
|
||||
@@ -198,20 +200,20 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
|
||||
|
||||
PwDbHeaderV4Fields.MasterSeed -> masterSeed = fieldData
|
||||
|
||||
PwDbHeaderV4Fields.TransformSeed -> if (version < FILE_VERSION_32_4)
|
||||
PwDbHeaderV4Fields.TransformSeed -> if (version.toLong() < FILE_VERSION_32_4.toLong())
|
||||
transformSeed = fieldData
|
||||
|
||||
PwDbHeaderV4Fields.TransformRounds -> if (version < FILE_VERSION_32_4)
|
||||
PwDbHeaderV4Fields.TransformRounds -> if (version.toLong() < FILE_VERSION_32_4.toLong())
|
||||
setTransformRound(fieldData)
|
||||
|
||||
PwDbHeaderV4Fields.EncryptionIV -> encryptionIV = fieldData
|
||||
|
||||
PwDbHeaderV4Fields.InnerRandomstreamKey -> if (version < FILE_VERSION_32_4)
|
||||
PwDbHeaderV4Fields.InnerRandomstreamKey -> if (version.toLong() < FILE_VERSION_32_4.toLong())
|
||||
innerRandomStreamKey = fieldData
|
||||
|
||||
PwDbHeaderV4Fields.StreamStartBytes -> streamStartBytes = fieldData
|
||||
|
||||
PwDbHeaderV4Fields.InnerRandomStreamID -> if (version < FILE_VERSION_32_4)
|
||||
PwDbHeaderV4Fields.InnerRandomStreamID -> if (version.toLong() < FILE_VERSION_32_4.toLong())
|
||||
setRandomStreamID(fieldData)
|
||||
|
||||
PwDbHeaderV4Fields.KdfParameters -> databaseV4.kdfParameters = KdfParameters.deserialize(fieldData)
|
||||
@@ -256,8 +258,8 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
|
||||
throw IOException("Invalid compression flags.")
|
||||
}
|
||||
|
||||
val flag = bytes4ToInt(pbFlags)
|
||||
if (flag < 0 || flag >= CompressionAlgorithm.values().size) {
|
||||
val flag = bytes4ToUInt(pbFlags)
|
||||
if (flag.toLong() < 0 || flag.toLong() >= CompressionAlgorithm.values().size) {
|
||||
throw IOException("Unrecognized compression flag.")
|
||||
}
|
||||
|
||||
@@ -272,8 +274,8 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
|
||||
throw IOException("Invalid stream id.")
|
||||
}
|
||||
|
||||
val id = bytes4ToInt(streamID)
|
||||
if (id < 0 || id >= CrsAlgorithm.values().size) {
|
||||
val id = bytes4ToUInt(streamID)
|
||||
if (id.toInt() < 0 || id.toInt() >= CrsAlgorithm.values().size) {
|
||||
throw IOException("Invalid stream id.")
|
||||
}
|
||||
|
||||
@@ -287,43 +289,42 @@ class DatabaseHeaderKDBX(private val databaseV4: DatabaseKDBX) : DatabaseHeader(
|
||||
* @param version Database version
|
||||
* @return true if it's a supported version
|
||||
*/
|
||||
private fun validVersion(version: Long): Boolean {
|
||||
return version and FILE_VERSION_CRITICAL_MASK <= FILE_VERSION_32_4 and FILE_VERSION_CRITICAL_MASK
|
||||
private fun validVersion(version: UnsignedInt): Boolean {
|
||||
return version.toInt() and FILE_VERSION_CRITICAL_MASK.toInt() <=
|
||||
FILE_VERSION_32_4.toInt() and FILE_VERSION_CRITICAL_MASK.toInt()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
var ULONG_MAX_VALUE: Long = -1
|
||||
val DBSIG_PRE2 = UnsignedInt(-0x4ab4049a)
|
||||
val DBSIG_2 = UnsignedInt(-0x4ab40499)
|
||||
|
||||
const val DBSIG_PRE2 = -0x4ab4049a
|
||||
const val DBSIG_2 = -0x4ab40499
|
||||
private val FILE_VERSION_CRITICAL_MASK = UnsignedInt(-0x10000)
|
||||
val FILE_VERSION_32_3 = UnsignedInt(0x00030001)
|
||||
val FILE_VERSION_32_4 = UnsignedInt(0x00040000)
|
||||
|
||||
private const val FILE_VERSION_CRITICAL_MASK: Long = -0x10000
|
||||
const val FILE_VERSION_32_3: Long = 0x00030001
|
||||
const val FILE_VERSION_32_4: Long = 0x00040000
|
||||
|
||||
fun getCompressionFromFlag(flag: Int): CompressionAlgorithm? {
|
||||
return when (flag) {
|
||||
fun getCompressionFromFlag(flag: UnsignedInt): CompressionAlgorithm? {
|
||||
return when (flag.toInt()) {
|
||||
0 -> CompressionAlgorithm.None
|
||||
1 -> CompressionAlgorithm.GZip
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun getFlagFromCompression(compression: CompressionAlgorithm): Int {
|
||||
fun getFlagFromCompression(compression: CompressionAlgorithm): UnsignedInt {
|
||||
return when (compression) {
|
||||
CompressionAlgorithm.GZip -> 1
|
||||
else -> 0
|
||||
CompressionAlgorithm.GZip -> UnsignedInt(1)
|
||||
else -> UnsignedInt(0)
|
||||
}
|
||||
}
|
||||
|
||||
fun matchesHeader(sig1: Int, sig2: Int): Boolean {
|
||||
fun matchesHeader(sig1: UnsignedInt, sig2: UnsignedInt): Boolean {
|
||||
return sig1 == PWM_DBSIG_1 && (sig2 == DBSIG_PRE2 || sig2 == DBSIG_2)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun computeHeaderHmac(header: ByteArray, key: ByteArray): ByteArray {
|
||||
val blockKey = HmacBlockStream.getHmacKey64(key, ULONG_MAX_VALUE)
|
||||
val blockKey = HmacBlockStream.getHmacKey64(key, UnsignedLong.ULONG_MAX_VALUE)
|
||||
|
||||
val hmac: Mac
|
||||
try {
|
||||
|
||||
@@ -90,10 +90,10 @@ class DatabaseInputKDB(cacheDirectory: File,
|
||||
|
||||
// Select algorithm
|
||||
when {
|
||||
header.flags and DatabaseHeaderKDB.FLAG_RIJNDAEL != 0 -> {
|
||||
header.flags.toInt() and DatabaseHeaderKDB.FLAG_RIJNDAEL.toInt() != 0 -> {
|
||||
mDatabaseToOpen.encryptionAlgorithm = EncryptionAlgorithm.AESRijndael
|
||||
}
|
||||
header.flags and DatabaseHeaderKDB.FLAG_TWOFISH != 0 -> {
|
||||
header.flags.toInt() and DatabaseHeaderKDB.FLAG_TWOFISH.toInt() != 0 -> {
|
||||
mDatabaseToOpen.encryptionAlgorithm = EncryptionAlgorithm.Twofish
|
||||
}
|
||||
else -> throw InvalidAlgorithmDatabaseException()
|
||||
@@ -160,8 +160,8 @@ class DatabaseInputKDB(cacheDirectory: File,
|
||||
var newEntry: EntryKDB? = null
|
||||
var currentGroupNumber = 0
|
||||
var currentEntryNumber = 0
|
||||
while (currentGroupNumber < header.numGroups
|
||||
|| currentEntryNumber < header.numEntries) {
|
||||
while (currentGroupNumber < header.numGroups.toLong()
|
||||
|| currentEntryNumber < header.numEntries.toLong()) {
|
||||
|
||||
val fieldType = cipherInputStream.readBytes2ToUShort()
|
||||
val fieldSize = cipherInputStream.readBytes4ToUInt().toInt()
|
||||
@@ -175,7 +175,7 @@ class DatabaseInputKDB(cacheDirectory: File,
|
||||
when (fieldSize) {
|
||||
4 -> {
|
||||
newGroup = mDatabaseToOpen.createGroup().apply {
|
||||
setGroupId(cipherInputStream.readBytes4ToInt())
|
||||
setGroupId(cipherInputStream.readBytes4ToUInt().toInt())
|
||||
}
|
||||
}
|
||||
16 -> {
|
||||
@@ -194,7 +194,7 @@ class DatabaseInputKDB(cacheDirectory: File,
|
||||
} ?:
|
||||
newEntry?.let { entry ->
|
||||
val groupKDB = mDatabaseToOpen.createGroup()
|
||||
groupKDB.nodeId = NodeIdInt(cipherInputStream.readBytes4ToInt())
|
||||
groupKDB.nodeId = NodeIdInt(cipherInputStream.readBytes4ToUInt().toInt())
|
||||
entry.parent = groupKDB
|
||||
}
|
||||
}
|
||||
@@ -203,7 +203,7 @@ class DatabaseInputKDB(cacheDirectory: File,
|
||||
group.creationTime = cipherInputStream.readBytes5ToDate()
|
||||
} ?:
|
||||
newEntry?.let { entry ->
|
||||
var iconId = cipherInputStream.readBytes4ToInt()
|
||||
var iconId = cipherInputStream.readBytes4ToUInt().toInt()
|
||||
// Clean up after bug that set icon ids to -1
|
||||
if (iconId == -1) {
|
||||
iconId = 0
|
||||
@@ -237,7 +237,7 @@ class DatabaseInputKDB(cacheDirectory: File,
|
||||
}
|
||||
0x0007 -> {
|
||||
newGroup?.let { group ->
|
||||
group.icon = mDatabaseToOpen.iconFactory.getIcon(cipherInputStream.readBytes4ToInt())
|
||||
group.icon = mDatabaseToOpen.iconFactory.getIcon(cipherInputStream.readBytes4ToUInt().toInt())
|
||||
} ?:
|
||||
newEntry?.let { entry ->
|
||||
entry.password = cipherInputStream.readBytesToString(fieldSize,false)
|
||||
@@ -253,7 +253,7 @@ class DatabaseInputKDB(cacheDirectory: File,
|
||||
}
|
||||
0x0009 -> {
|
||||
newGroup?.let { group ->
|
||||
group.flags = cipherInputStream.readBytes4ToInt()
|
||||
group.groupFlags = cipherInputStream.readBytes4ToUInt().toInt()
|
||||
} ?:
|
||||
newEntry?.let { entry ->
|
||||
entry.creationTime = cipherInputStream.readBytes5ToDate()
|
||||
|
||||
@@ -43,6 +43,8 @@ import com.kunzisoft.keepass.database.file.DatabaseKDBXXML
|
||||
import com.kunzisoft.keepass.database.file.DateKDBXUtil
|
||||
import com.kunzisoft.keepass.stream.*
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import com.kunzisoft.keepass.utils.UnsignedLong
|
||||
import org.bouncycastle.crypto.StreamCipher
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import org.xmlpull.v1.XmlPullParserException
|
||||
@@ -130,7 +132,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
}
|
||||
|
||||
val isPlain: InputStream
|
||||
if (mDatabase.kdbxVersion < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (mDatabase.kdbxVersion.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
|
||||
val decrypted = attachCipherStream(databaseInputStream, cipher)
|
||||
val dataDecrypted = LittleEndianDataInputStream(decrypted)
|
||||
@@ -178,7 +180,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
else -> isPlain
|
||||
}
|
||||
|
||||
if (mDatabase.kdbxVersion >= DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (mDatabase.kdbxVersion.toLong() >= DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
loadInnerHeader(inputStreamXml, header)
|
||||
}
|
||||
|
||||
@@ -226,7 +228,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
header: DatabaseHeaderKDBX): Boolean {
|
||||
val fieldId = dataInputStream.read().toByte()
|
||||
|
||||
val size = dataInputStream.readInt()
|
||||
val size = dataInputStream.readUInt().toInt()
|
||||
if (size < 0) throw IOException("Corrupted file")
|
||||
|
||||
when (fieldId) {
|
||||
@@ -488,7 +490,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemNotes, ignoreCase = true)) {
|
||||
ctxGroup?.notes = readString(xpp)
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemIcon, ignoreCase = true)) {
|
||||
ctxGroup?.icon = mDatabase.iconFactory.getIcon(readUInt(xpp, 0).toInt())
|
||||
ctxGroup?.icon = mDatabase.iconFactory.getIcon(readUInt(xpp, UnsignedInt(0)).toInt())
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemCustomIconID, ignoreCase = true)) {
|
||||
ctxGroup?.iconCustom = mDatabase.iconFactory.getIcon(readUuid(xpp))
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemTimes, ignoreCase = true)) {
|
||||
@@ -542,7 +544,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
KdbContext.Entry -> if (name.equals(DatabaseKDBXXML.ElemUuid, ignoreCase = true)) {
|
||||
ctxEntry?.nodeId = NodeIdUUID(readUuid(xpp))
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemIcon, ignoreCase = true)) {
|
||||
ctxEntry?.icon = mDatabase.iconFactory.getIcon(readUInt(xpp, 0).toInt())
|
||||
ctxEntry?.icon = mDatabase.iconFactory.getIcon(readUInt(xpp, UnsignedInt(0)).toInt())
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemCustomIconID, ignoreCase = true)) {
|
||||
ctxEntry?.iconCustom = mDatabase.iconFactory.getIcon(readUuid(xpp))
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemFgColor, ignoreCase = true)) {
|
||||
@@ -598,7 +600,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
name.equals(DatabaseKDBXXML.ElemLastAccessTime, ignoreCase = true) -> tl?.lastAccessTime = readPwTime(xpp)
|
||||
name.equals(DatabaseKDBXXML.ElemExpiryTime, ignoreCase = true) -> tl?.expiryTime = readPwTime(xpp)
|
||||
name.equals(DatabaseKDBXXML.ElemExpires, ignoreCase = true) -> tl?.expires = readBool(xpp, false)
|
||||
name.equals(DatabaseKDBXXML.ElemUsageCount, ignoreCase = true) -> tl?.usageCount = readULong(xpp, 0)
|
||||
name.equals(DatabaseKDBXXML.ElemUsageCount, ignoreCase = true) -> tl?.usageCount = readULong(xpp, UnsignedLong(0))
|
||||
name.equals(DatabaseKDBXXML.ElemLocationChanged, ignoreCase = true) -> tl?.locationChanged = readPwTime(xpp)
|
||||
else -> readUnknown(xpp)
|
||||
}
|
||||
@@ -621,7 +623,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
KdbContext.EntryAutoType -> if (name.equals(DatabaseKDBXXML.ElemAutoTypeEnabled, ignoreCase = true)) {
|
||||
ctxEntry?.autoType?.enabled = readBool(xpp, true)
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemAutoTypeObfuscation, ignoreCase = true)) {
|
||||
ctxEntry?.autoType?.obfuscationOptions = readUInt(xpp, 0)
|
||||
ctxEntry?.autoType?.obfuscationOptions = readUInt(xpp, UnsignedInt(0))
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemAutoTypeDefaultSeq, ignoreCase = true)) {
|
||||
ctxEntry?.autoType?.defaultSequence = readString(xpp)
|
||||
} else if (name.equals(DatabaseKDBXXML.ElemAutoTypeItem, ignoreCase = true)) {
|
||||
@@ -815,7 +817,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
val sDate = readString(xpp)
|
||||
var utcDate: Date? = null
|
||||
|
||||
if (mDatabase.kdbxVersion >= DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (mDatabase.kdbxVersion.toLong() >= DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
var buf = Base64.decode(sDate, BASE_64_FLAG)
|
||||
if (buf.size != 8) {
|
||||
val buf8 = ByteArray(8)
|
||||
@@ -887,48 +889,39 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
}
|
||||
|
||||
@Throws(IOException::class, XmlPullParserException::class)
|
||||
private fun readInt(xpp: XmlPullParser, def: Int): Int {
|
||||
val str = readString(xpp)
|
||||
|
||||
private fun readInt(xpp: XmlPullParser, default: Int): Int {
|
||||
return try {
|
||||
Integer.parseInt(str)
|
||||
} catch (e: NumberFormatException) {
|
||||
def
|
||||
readString(xpp).toInt()
|
||||
} catch (e: Exception) {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class, XmlPullParserException::class)
|
||||
private fun readUInt(xpp: XmlPullParser, uDefault: Long): Long {
|
||||
val u: Long = readULong(xpp, uDefault)
|
||||
|
||||
if (u < 0 || u > MAX_UINT) {
|
||||
throw NumberFormatException("Outside of the uint size")
|
||||
}
|
||||
|
||||
return u
|
||||
|
||||
}
|
||||
|
||||
@Throws(IOException::class, XmlPullParserException::class)
|
||||
private fun readLong(xpp: XmlPullParser, def: Long): Long {
|
||||
val str = readString(xpp)
|
||||
|
||||
private fun readUInt(xpp: XmlPullParser, default: UnsignedInt): UnsignedInt {
|
||||
return try {
|
||||
java.lang.Long.parseLong(str)
|
||||
} catch (e: NumberFormatException) {
|
||||
def
|
||||
UnsignedInt(readString(xpp).toInt())
|
||||
} catch (e: Exception) {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class, XmlPullParserException::class)
|
||||
private fun readULong(xpp: XmlPullParser, uDefault: Long): Long {
|
||||
var u = readLong(xpp, uDefault)
|
||||
|
||||
if (u < 0) {
|
||||
u = uDefault
|
||||
private fun readLong(xpp: XmlPullParser, default: Long): Long {
|
||||
return try {
|
||||
readString(xpp).toLong()
|
||||
} catch (e: Exception) {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
return u
|
||||
@Throws(IOException::class, XmlPullParserException::class)
|
||||
private fun readULong(xpp: XmlPullParser, default: UnsignedLong): UnsignedLong {
|
||||
return try {
|
||||
UnsignedLong(readString(xpp).toLong())
|
||||
} catch (e: Exception) {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(XmlPullParserException::class, IOException::class)
|
||||
@@ -1050,7 +1043,7 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
|
||||
companion object {
|
||||
|
||||
private const val DEFAULT_HISTORY_DAYS: Long = 365
|
||||
private val DEFAULT_HISTORY_DAYS = UnsignedInt(365)
|
||||
|
||||
@Throws(XmlPullParserException::class)
|
||||
private fun createPullParser(readerStream: InputStream): XmlPullParser {
|
||||
@@ -1062,8 +1055,6 @@ class DatabaseInputKDBX(cacheDirectory: File,
|
||||
|
||||
return xpp
|
||||
}
|
||||
|
||||
private const val MAX_UINT = 4294967296L // 2^32
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
package com.kunzisoft.keepass.database.file.output
|
||||
|
||||
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDB
|
||||
import com.kunzisoft.keepass.stream.intTo4Bytes
|
||||
import com.kunzisoft.keepass.stream.uIntTo4Bytes
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
||||
@@ -29,14 +29,14 @@ class DatabaseHeaderOutputKDB(private val mHeader: DatabaseHeaderKDB,
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun outputStart() {
|
||||
mOutputStream.write(intTo4Bytes(mHeader.signature1))
|
||||
mOutputStream.write(intTo4Bytes(mHeader.signature2))
|
||||
mOutputStream.write(intTo4Bytes(mHeader.flags))
|
||||
mOutputStream.write(intTo4Bytes(mHeader.version))
|
||||
mOutputStream.write(uIntTo4Bytes(mHeader.signature1))
|
||||
mOutputStream.write(uIntTo4Bytes(mHeader.signature2))
|
||||
mOutputStream.write(uIntTo4Bytes(mHeader.flags))
|
||||
mOutputStream.write(uIntTo4Bytes(mHeader.version))
|
||||
mOutputStream.write(mHeader.masterSeed)
|
||||
mOutputStream.write(mHeader.encryptionIV)
|
||||
mOutputStream.write(intTo4Bytes(mHeader.numGroups))
|
||||
mOutputStream.write(intTo4Bytes(mHeader.numEntries))
|
||||
mOutputStream.write(uIntTo4Bytes(mHeader.numGroups))
|
||||
mOutputStream.write(uIntTo4Bytes(mHeader.numEntries))
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -47,7 +47,7 @@ class DatabaseHeaderOutputKDB(private val mHeader: DatabaseHeaderKDB,
|
||||
@Throws(IOException::class)
|
||||
fun outputEnd() {
|
||||
mOutputStream.write(mHeader.transformSeed)
|
||||
mOutputStream.write(intTo4Bytes(mHeader.numKeyEncRounds))
|
||||
mOutputStream.write(uIntTo4Bytes(mHeader.numKeyEncRounds))
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
|
||||
@@ -24,8 +24,8 @@ 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.ULONG_MAX_VALUE
|
||||
import com.kunzisoft.keepass.stream.*
|
||||
import com.kunzisoft.keepass.utils.UnsignedLong
|
||||
import com.kunzisoft.keepass.utils.VariantDictionary
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
@@ -66,7 +66,7 @@ constructor(private val databaseKDBX: DatabaseKDBX,
|
||||
val hmac: Mac
|
||||
try {
|
||||
hmac = Mac.getInstance("HmacSHA256")
|
||||
val signingKey = SecretKeySpec(HmacBlockStream.getHmacKey64(hmacKey, ULONG_MAX_VALUE), "HmacSHA256")
|
||||
val signingKey = SecretKeySpec(HmacBlockStream.getHmacKey64(hmacKey, UnsignedLong.ULONG_MAX_VALUE), "HmacSHA256")
|
||||
hmac.init(signingKey)
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
throw DatabaseOutputException(e)
|
||||
@@ -82,15 +82,15 @@ constructor(private val databaseKDBX: DatabaseKDBX,
|
||||
@Throws(IOException::class)
|
||||
fun output() {
|
||||
|
||||
los.writeUInt(DatabaseHeader.PWM_DBSIG_1.toLong())
|
||||
los.writeUInt(DatabaseHeaderKDBX.DBSIG_2.toLong())
|
||||
los.writeUInt(DatabaseHeader.PWM_DBSIG_1)
|
||||
los.writeUInt(DatabaseHeaderKDBX.DBSIG_2)
|
||||
los.writeUInt(header.version)
|
||||
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.CipherID, uuidTo16Bytes(databaseKDBX.dataCipher))
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.CompressionFlags, intTo4Bytes(DatabaseHeaderKDBX.getFlagFromCompression(databaseKDBX.compressionAlgorithm)))
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.CompressionFlags, uIntTo4Bytes(DatabaseHeaderKDBX.getFlagFromCompression(databaseKDBX.compressionAlgorithm)))
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.MasterSeed, header.masterSeed)
|
||||
|
||||
if (header.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (header.version.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.TransformSeed, header.transformSeed)
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.TransformRounds, longTo8Bytes(databaseKDBX.numberKeyEncryptionRounds))
|
||||
} else {
|
||||
@@ -101,10 +101,10 @@ constructor(private val databaseKDBX: DatabaseKDBX,
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.EncryptionIV, header.encryptionIV)
|
||||
}
|
||||
|
||||
if (header.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (header.version.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.InnerRandomstreamKey, header.innerRandomStreamKey)
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.StreamStartBytes, header.streamStartBytes)
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.InnerRandomStreamID, intTo4Bytes(header.innerRandomStream!!.id))
|
||||
writeHeaderField(DatabaseHeaderKDBX.PwDbHeaderV4Fields.InnerRandomStreamID, uIntTo4Bytes(header.innerRandomStream!!.id))
|
||||
}
|
||||
|
||||
if (databaseKDBX.containsPublicCustomData()) {
|
||||
@@ -136,7 +136,7 @@ constructor(private val databaseKDBX: DatabaseKDBX,
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun writeHeaderFieldSize(size: Int) {
|
||||
if (header.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (header.version.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
los.writeUShort(size)
|
||||
} else {
|
||||
los.writeInt(size)
|
||||
|
||||
@@ -40,7 +40,7 @@ class DatabaseInnerHeaderOutputKDBX(private val database: DatabaseKDBX,
|
||||
dataOutputStream.writeInt(4)
|
||||
if (header.innerRandomStream == null)
|
||||
throw IOException("Can't write innerRandomStream")
|
||||
dataOutputStream.writeInt(header.innerRandomStream!!.id)
|
||||
dataOutputStream.writeInt(header.innerRandomStream!!.id.toInt())
|
||||
|
||||
val streamKeySize = header.innerRandomStreamKey.size
|
||||
dataOutputStream.write(DatabaseHeaderKDBX.PwDbInnerHeaderV4Fields.InnerRandomstreamKey.toInt())
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.kunzisoft.keepass.database.file.DatabaseHeader
|
||||
import com.kunzisoft.keepass.database.file.DatabaseHeaderKDB
|
||||
import com.kunzisoft.keepass.stream.LittleEndianDataOutputStream
|
||||
import com.kunzisoft.keepass.stream.NullOutputStream
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
@@ -117,18 +118,18 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
|
||||
|
||||
when {
|
||||
mDatabaseKDB.encryptionAlgorithm === EncryptionAlgorithm.AESRijndael -> {
|
||||
header.flags = header.flags or DatabaseHeaderKDB.FLAG_RIJNDAEL
|
||||
header.flags = UnsignedInt(header.flags.toInt() or DatabaseHeaderKDB.FLAG_RIJNDAEL.toInt())
|
||||
}
|
||||
mDatabaseKDB.encryptionAlgorithm === EncryptionAlgorithm.Twofish -> {
|
||||
header.flags = header.flags or DatabaseHeaderKDB.FLAG_TWOFISH
|
||||
header.flags = UnsignedInt(header.flags.toInt() or DatabaseHeaderKDB.FLAG_TWOFISH.toInt())
|
||||
}
|
||||
else -> throw DatabaseOutputException("Unsupported algorithm.")
|
||||
}
|
||||
|
||||
header.version = DatabaseHeaderKDB.DBVER_DW
|
||||
header.numGroups = mDatabaseKDB.numberOfGroups()
|
||||
header.numEntries = mDatabaseKDB.numberOfEntries()
|
||||
header.numKeyEncRounds = mDatabaseKDB.numberKeyEncryptionRounds.toInt() // TODO Signed Long - Unsigned Int #443
|
||||
header.numGroups = UnsignedInt(mDatabaseKDB.numberOfGroups())
|
||||
header.numEntries = UnsignedInt(mDatabaseKDB.numberOfEntries())
|
||||
header.numKeyEncRounds = UnsignedInt.fromLong(mDatabaseKDB.numberKeyEncryptionRounds)
|
||||
|
||||
setIVs(header)
|
||||
|
||||
@@ -279,6 +280,5 @@ class DatabaseOutputKDB(private val mDatabaseKDB: DatabaseKDB,
|
||||
if (data != null) {
|
||||
los.write(data)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
header = outputHeader(mOS)
|
||||
|
||||
val osPlain: OutputStream
|
||||
osPlain = if (header!!.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
osPlain = if (header!!.version.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
val cos = attachStreamEncryptor(header!!, mOS)
|
||||
cos.write(header!!.streamStartBytes)
|
||||
|
||||
@@ -105,7 +105,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
else -> osPlain
|
||||
}
|
||||
|
||||
if (header!!.version >= DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (header!!.version.toLong() >= DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
val ihOut = DatabaseInnerHeaderOutputKDBX(mDatabaseKDBX, header!!, osXml)
|
||||
ihOut.output()
|
||||
}
|
||||
@@ -209,7 +209,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
writeObject(DatabaseKDBXXML.ElemDbDescChanged, mDatabaseKDBX.descriptionChanged.date)
|
||||
writeObject(DatabaseKDBXXML.ElemDbDefaultUser, mDatabaseKDBX.defaultUserName, true)
|
||||
writeObject(DatabaseKDBXXML.ElemDbDefaultUserChanged, mDatabaseKDBX.defaultUserNameChanged.date)
|
||||
writeObject(DatabaseKDBXXML.ElemDbMntncHistoryDays, mDatabaseKDBX.maintenanceHistoryDays)
|
||||
writeObject(DatabaseKDBXXML.ElemDbMntncHistoryDays, mDatabaseKDBX.maintenanceHistoryDays.toLong())
|
||||
writeObject(DatabaseKDBXXML.ElemDbColor, mDatabaseKDBX.color)
|
||||
writeObject(DatabaseKDBXXML.ElemDbKeyChanged, mDatabaseKDBX.keyLastChanged.date)
|
||||
writeObject(DatabaseKDBXXML.ElemDbKeyChangeRec, mDatabaseKDBX.keyChangeRecDays)
|
||||
@@ -230,7 +230,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
writeUuid(DatabaseKDBXXML.ElemLastTopVisibleGroup, mDatabaseKDBX.lastTopVisibleGroupUUID)
|
||||
|
||||
// Seem to work properly if always in meta
|
||||
if (header!!.version < DatabaseHeaderKDBX.FILE_VERSION_32_4)
|
||||
if (header!!.version.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong())
|
||||
writeMetaBinaries()
|
||||
|
||||
writeCustomData(mDatabaseKDBX.customData)
|
||||
@@ -274,7 +274,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
Log.e(TAG, "Unable to retrieve header", unknownKDF)
|
||||
}
|
||||
|
||||
if (header.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (header.version.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
header.innerRandomStream = CrsAlgorithm.Salsa20
|
||||
header.innerRandomStreamKey = ByteArray(32)
|
||||
} else {
|
||||
@@ -288,7 +288,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
throw DatabaseOutputException("Invalid random cipher")
|
||||
}
|
||||
|
||||
if (header.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (header.version.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
random.nextBytes(header.streamStartBytes)
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
|
||||
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
|
||||
private fun writeObject(name: String, value: Date) {
|
||||
if (header!!.version < DatabaseHeaderKDBX.FILE_VERSION_32_4) {
|
||||
if (header!!.version.toLong() < DatabaseHeaderKDBX.FILE_VERSION_32_4.toLong()) {
|
||||
writeObject(name, DatabaseKDBXXML.DateFormatter.format(value))
|
||||
} else {
|
||||
val dt = DateTime(value)
|
||||
@@ -489,7 +489,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
xml.startTag(null, DatabaseKDBXXML.ElemAutoType)
|
||||
|
||||
writeObject(DatabaseKDBXXML.ElemAutoTypeEnabled, autoType.enabled)
|
||||
writeObject(DatabaseKDBXXML.ElemAutoTypeObfuscation, autoType.obfuscationOptions)
|
||||
writeObject(DatabaseKDBXXML.ElemAutoTypeObfuscation, autoType.obfuscationOptions.toLong())
|
||||
|
||||
if (autoType.defaultSequence.isNotEmpty()) {
|
||||
writeObject(DatabaseKDBXXML.ElemAutoTypeDefaultSeq, autoType.defaultSequence, true)
|
||||
@@ -629,7 +629,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
|
||||
writeObject(DatabaseKDBXXML.ElemLastAccessTime, node.lastAccessTime.date)
|
||||
writeObject(DatabaseKDBXXML.ElemExpiryTime, node.expiryTime.date)
|
||||
writeObject(DatabaseKDBXXML.ElemExpires, node.expires)
|
||||
writeObject(DatabaseKDBXXML.ElemUsageCount, node.usageCount)
|
||||
writeObject(DatabaseKDBXXML.ElemUsageCount, node.usageCount.toLong())
|
||||
writeObject(DatabaseKDBXXML.ElemLocationChanged, node.locationChanged.date)
|
||||
|
||||
xml.endTag(null, DatabaseKDBXXML.ElemTimes)
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.kunzisoft.keepass.database.element.entry.EntryKDB
|
||||
import com.kunzisoft.keepass.database.file.output.GroupOutputKDB.Companion.GROUPID_FIELD_SIZE
|
||||
import com.kunzisoft.keepass.stream.*
|
||||
import com.kunzisoft.keepass.utils.StringDatabaseKDBUtils
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import java.nio.charset.Charset
|
||||
@@ -54,12 +55,12 @@ class EntryOutputKDB
|
||||
// Group ID
|
||||
mOutputStream.write(GROUPID_FIELD_TYPE)
|
||||
mOutputStream.write(GROUPID_FIELD_SIZE)
|
||||
mOutputStream.write(intTo4Bytes(mEntry.parent!!.id))
|
||||
mOutputStream.write(uIntTo4Bytes(UnsignedInt(mEntry.parent!!.id)))
|
||||
|
||||
// Image ID
|
||||
mOutputStream.write(IMAGEID_FIELD_TYPE)
|
||||
mOutputStream.write(IMAGEID_FIELD_SIZE)
|
||||
mOutputStream.write(intTo4Bytes(mEntry.icon.iconId))
|
||||
mOutputStream.write(uIntTo4Bytes(UnsignedInt(mEntry.icon.iconId)))
|
||||
|
||||
// Title
|
||||
//byte[] title = mEntry.title.getBytes("UTF-8");
|
||||
@@ -101,14 +102,9 @@ class EntryOutputKDB
|
||||
// Binary
|
||||
mOutputStream.write(BINARY_DATA_FIELD_TYPE)
|
||||
val binaryData = mEntry.binaryData
|
||||
val binaryDataLength = binaryData?.length() ?: 0
|
||||
val binaryDataLengthRightSize = if (binaryDataLength <= Int.MAX_VALUE) {
|
||||
binaryDataLength.toInt()
|
||||
} else {
|
||||
0 // TODO if length > UInt.maxvalue show exception #443
|
||||
}
|
||||
val binaryDataLength = binaryData?.length() ?: 0L
|
||||
// Write data length
|
||||
mOutputStream.write(intTo4Bytes(binaryDataLengthRightSize))
|
||||
mOutputStream.write(uIntTo4Bytes(UnsignedInt.fromLong(binaryDataLength)))
|
||||
// Write data
|
||||
if (binaryDataLength > 0) {
|
||||
binaryData?.getInputDataStream().use { inputStream ->
|
||||
@@ -140,7 +136,7 @@ class EntryOutputKDB
|
||||
private fun writePassword(str: String, os: OutputStream): Int {
|
||||
val initial = str.toByteArray(Charset.forName("UTF-8"))
|
||||
val length = initial.size + 1
|
||||
os.write(intTo4Bytes(length))
|
||||
os.write(uIntTo4Bytes(UnsignedInt(length)))
|
||||
os.write(initial)
|
||||
os.write(0x00)
|
||||
return length
|
||||
@@ -164,13 +160,13 @@ class EntryOutputKDB
|
||||
val BINARY_DATA_FIELD_TYPE:ByteArray = uShortTo2Bytes(14)
|
||||
val END_FIELD_TYPE:ByteArray = uShortTo2Bytes(0xFFFF)
|
||||
|
||||
val LONG_FOUR:ByteArray = intTo4Bytes(4)
|
||||
val UUID_FIELD_SIZE:ByteArray = intTo4Bytes(16)
|
||||
val DATE_FIELD_SIZE:ByteArray = intTo4Bytes(5)
|
||||
val IMAGEID_FIELD_SIZE:ByteArray = intTo4Bytes(4)
|
||||
val LEVEL_FIELD_SIZE:ByteArray = intTo4Bytes(4)
|
||||
val FLAGS_FIELD_SIZE:ByteArray = intTo4Bytes(4)
|
||||
val ZERO_FIELD_SIZE:ByteArray = intTo4Bytes(0)
|
||||
val LONG_FOUR:ByteArray = uIntTo4Bytes(UnsignedInt(4))
|
||||
val UUID_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(16))
|
||||
val DATE_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(5))
|
||||
val IMAGEID_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(4))
|
||||
val LEVEL_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(4))
|
||||
val FLAGS_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(4))
|
||||
val ZERO_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(0))
|
||||
val ZERO_FIVE:ByteArray = byteArrayOf(0x00, 0x00, 0x00, 0x00, 0x00)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,10 @@ package com.kunzisoft.keepass.database.file.output
|
||||
|
||||
import com.kunzisoft.keepass.database.element.group.GroupKDB
|
||||
import com.kunzisoft.keepass.stream.dateTo5Bytes
|
||||
import com.kunzisoft.keepass.stream.intTo4Bytes
|
||||
import com.kunzisoft.keepass.stream.uIntTo4Bytes
|
||||
import com.kunzisoft.keepass.stream.uShortTo2Bytes
|
||||
import com.kunzisoft.keepass.utils.StringDatabaseKDBUtils
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
||||
@@ -39,7 +40,7 @@ class GroupOutputKDB (private val mGroup: GroupKDB, private val mOutputStream: O
|
||||
// Group ID
|
||||
mOutputStream.write(GROUPID_FIELD_TYPE)
|
||||
mOutputStream.write(GROUPID_FIELD_SIZE)
|
||||
mOutputStream.write(intTo4Bytes(mGroup.id))
|
||||
mOutputStream.write(uIntTo4Bytes(UnsignedInt(mGroup.id)))
|
||||
|
||||
// Name
|
||||
mOutputStream.write(NAME_FIELD_TYPE)
|
||||
@@ -68,7 +69,7 @@ class GroupOutputKDB (private val mGroup: GroupKDB, private val mOutputStream: O
|
||||
// Image ID
|
||||
mOutputStream.write(IMAGEID_FIELD_TYPE)
|
||||
mOutputStream.write(IMAGEID_FIELD_SIZE)
|
||||
mOutputStream.write(intTo4Bytes(mGroup.icon.iconId))
|
||||
mOutputStream.write(uIntTo4Bytes(UnsignedInt(mGroup.icon.iconId)))
|
||||
|
||||
// Level
|
||||
mOutputStream.write(LEVEL_FIELD_TYPE)
|
||||
@@ -78,7 +79,7 @@ class GroupOutputKDB (private val mGroup: GroupKDB, private val mOutputStream: O
|
||||
// Flags
|
||||
mOutputStream.write(FLAGS_FIELD_TYPE)
|
||||
mOutputStream.write(FLAGS_FIELD_SIZE)
|
||||
mOutputStream.write(intTo4Bytes(mGroup.flags))
|
||||
mOutputStream.write(uIntTo4Bytes(UnsignedInt(mGroup.groupFlags)))
|
||||
|
||||
// End
|
||||
mOutputStream.write(END_FIELD_TYPE)
|
||||
@@ -98,11 +99,11 @@ class GroupOutputKDB (private val mGroup: GroupKDB, private val mOutputStream: O
|
||||
val FLAGS_FIELD_TYPE:ByteArray = uShortTo2Bytes(9)
|
||||
val END_FIELD_TYPE:ByteArray = uShortTo2Bytes(0xFFFF)
|
||||
|
||||
val GROUPID_FIELD_SIZE:ByteArray = intTo4Bytes(4)
|
||||
val DATE_FIELD_SIZE:ByteArray = intTo4Bytes(5)
|
||||
val IMAGEID_FIELD_SIZE:ByteArray = intTo4Bytes(4)
|
||||
val LEVEL_FIELD_SIZE:ByteArray = intTo4Bytes(2)
|
||||
val FLAGS_FIELD_SIZE:ByteArray = intTo4Bytes(4)
|
||||
val ZERO_FIELD_SIZE:ByteArray = intTo4Bytes(0)
|
||||
val GROUPID_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(4))
|
||||
val DATE_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(5))
|
||||
val IMAGEID_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(4))
|
||||
val LEVEL_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(2))
|
||||
val FLAGS_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(4))
|
||||
val ZERO_FIELD_SIZE:ByteArray = uIntTo4Bytes(UnsignedInt(0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,8 +444,8 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() {
|
||||
mMemoryPref?.summary = memoryToShow.toString()
|
||||
}
|
||||
DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_PARALLELISM_TASK -> {
|
||||
val oldParallelism = data.getInt(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||
val newParallelism = data.getInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)
|
||||
val oldParallelism = data.getLong(DatabaseTaskNotificationService.OLD_ELEMENT_KEY)
|
||||
val newParallelism = data.getLong(DatabaseTaskNotificationService.NEW_ELEMENT_KEY)
|
||||
val parallelismToShow =
|
||||
if (result.isSuccess) {
|
||||
newParallelism
|
||||
|
||||
@@ -35,27 +35,26 @@ class ParallelismPreferenceDialogFragmentCompat : DatabaseSavePreferenceDialogFr
|
||||
override fun onDialogClosed(positiveResult: Boolean) {
|
||||
if (positiveResult) {
|
||||
database?.let { database ->
|
||||
var parallelism: Int = try {
|
||||
inputText.toInt()
|
||||
val parallelism: Long = try {
|
||||
inputText.toLong()
|
||||
} catch (e: NumberFormatException) {
|
||||
MIN_PARALLELISM
|
||||
}
|
||||
if (parallelism < MIN_PARALLELISM) {
|
||||
parallelism = MIN_PARALLELISM
|
||||
}
|
||||
// TODO Max Parallelism
|
||||
|
||||
val oldParallelism = database.parallelism
|
||||
database.parallelism = parallelism
|
||||
|
||||
mProgressDialogThread?.startDatabaseSaveParallelism(oldParallelism, parallelism, mDatabaseAutoSaveEnable)
|
||||
mProgressDialogThread?.startDatabaseSaveParallelism(
|
||||
oldParallelism,
|
||||
parallelism,
|
||||
mDatabaseAutoSaveEnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val MIN_PARALLELISM = 1
|
||||
const val MIN_PARALLELISM = 1L
|
||||
|
||||
fun newInstance(key: String): ParallelismPreferenceDialogFragmentCompat {
|
||||
val fragment = ParallelismPreferenceDialogFragmentCompat()
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.stream
|
||||
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.security.MessageDigest
|
||||
@@ -80,7 +81,7 @@ class HashedBlockInputStream(inputStream: InputStream) : InputStream() {
|
||||
bufferPos = 0
|
||||
|
||||
val index = baseStream.readUInt()
|
||||
if (index != bufferIndex) {
|
||||
if (index.toLong() != bufferIndex) {
|
||||
throw IOException("Invalid data format")
|
||||
}
|
||||
bufferIndex++
|
||||
@@ -90,11 +91,7 @@ class HashedBlockInputStream(inputStream: InputStream) : InputStream() {
|
||||
throw IOException("Invalid data format")
|
||||
}
|
||||
|
||||
val bufferSize = baseStream.readBytes4ToInt()
|
||||
if (bufferSize < 0) {
|
||||
throw IOException("Invalid data format")
|
||||
}
|
||||
|
||||
val bufferSize = baseStream.readBytes4ToUInt().toInt()
|
||||
if (bufferSize == 0) {
|
||||
for (hash in 0 until HASH_SIZE) {
|
||||
if (storedHash[hash].toInt() != 0) {
|
||||
@@ -144,7 +141,7 @@ class HashedBlockInputStream(inputStream: InputStream) : InputStream() {
|
||||
if (!readHashedBlock()) return -1
|
||||
}
|
||||
|
||||
val output = byteToUInt(buffer[bufferPos])
|
||||
val output = UnsignedInt.fromByte(buffer[bufferPos]).toInt()
|
||||
bufferPos++
|
||||
|
||||
return output
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.stream
|
||||
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import java.security.MessageDigest
|
||||
@@ -98,7 +99,7 @@ class HashedBlockOutputStream : OutputStream {
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun writeHashedBlock() {
|
||||
baseStream.writeUInt(bufferIndex)
|
||||
baseStream.writeUInt(UnsignedInt.fromLong(bufferIndex))
|
||||
bufferIndex++
|
||||
|
||||
if (bufferPos > 0) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.stream
|
||||
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.security.InvalidKeyException
|
||||
@@ -43,7 +44,7 @@ class HmacBlockInputStream(baseStream: InputStream, private val verify: Boolean,
|
||||
if (!readSafeBlock()) return -1
|
||||
}
|
||||
|
||||
val output = byteToUInt(buffer[bufferPos])
|
||||
val output = UnsignedInt.fromByte(buffer[bufferPos]).toInt()
|
||||
bufferPos++
|
||||
|
||||
return output
|
||||
@@ -97,10 +98,10 @@ class HmacBlockInputStream(baseStream: InputStream, private val verify: Boolean,
|
||||
if (pbBlockSize.size != 4) {
|
||||
throw IOException("File corrupted")
|
||||
}
|
||||
val blockSize = bytes4ToInt(pbBlockSize)
|
||||
val blockSize = bytes4ToUInt(pbBlockSize)
|
||||
bufferPos = 0
|
||||
|
||||
buffer = baseStream.readBytes(blockSize)
|
||||
buffer = baseStream.readBytes(blockSize.toInt())
|
||||
|
||||
if (verify) {
|
||||
val cmpHmac: ByteArray
|
||||
@@ -134,7 +135,7 @@ class HmacBlockInputStream(baseStream: InputStream, private val verify: Boolean,
|
||||
|
||||
blockIndex++
|
||||
|
||||
if (blockSize == 0) {
|
||||
if (blockSize.toLong() == 0L) {
|
||||
endOfStream = true
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.stream
|
||||
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import java.security.InvalidKeyException
|
||||
@@ -87,7 +88,7 @@ class HmacBlockOutputStream(outputStream: OutputStream,
|
||||
@Throws(IOException::class)
|
||||
private fun writeSafeBlock() {
|
||||
val bufBlockIndex = longTo8Bytes(blockIndex)
|
||||
val blockSizeBuf = intTo4Bytes(bufferPos)
|
||||
val blockSizeBuf = uIntTo4Bytes(UnsignedInt(bufferPos))
|
||||
|
||||
val blockHmac: ByteArray
|
||||
val blockKey = HmacBlockStream.getHmacKey64(key, blockIndex)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.stream
|
||||
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
@@ -32,15 +33,10 @@ class LittleEndianDataInputStream(private val baseStream: InputStream) : InputSt
|
||||
* be interpreted as an unsigned integer.
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
fun readUInt(): Long {
|
||||
fun readUInt(): UnsignedInt {
|
||||
return baseStream.readBytes4ToUInt()
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun readInt(): Int {
|
||||
return baseStream.readBytes4ToInt()
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun readUShort(): Int {
|
||||
val buf = ByteArray(2)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.stream
|
||||
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
|
||||
@@ -30,8 +31,8 @@ import java.io.OutputStream
|
||||
class LittleEndianDataOutputStream(private val baseStream: OutputStream) : OutputStream() {
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun writeUInt(uint: Long) { // TODO UInt #443
|
||||
baseStream.write(intTo4Bytes(uint.toInt()))
|
||||
fun writeUInt(uInt: UnsignedInt) {
|
||||
baseStream.write(uIntTo4Bytes(uInt))
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -66,7 +67,7 @@ class LittleEndianDataOutputStream(private val baseStream: OutputStream) : Outpu
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun writeInt(value: Int) {
|
||||
baseStream.write(intTo4Bytes(value))
|
||||
baseStream.write(uIntTo4Bytes(UnsignedInt(value)))
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.kunzisoft.keepass.stream
|
||||
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.utils.StringDatabaseKDBUtils.bytesToString
|
||||
import com.kunzisoft.keepass.utils.UnsignedInt
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.util.*
|
||||
@@ -80,13 +81,8 @@ fun InputStream.readBytes(length: Int, bufferSize: Int, readBytes: (bytesRead: B
|
||||
* be interpreted as an unsigned integer.
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
fun InputStream.readBytes4ToUInt(): Long {
|
||||
return readBytes4ToInt().toLong() and INT_TO_LONG_MASK
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun InputStream.readBytes4ToInt(): Int {
|
||||
return bytes4ToInt(readBytesLength(4))
|
||||
fun InputStream.readBytes4ToUInt(): UnsignedInt {
|
||||
return bytes4ToUInt(readBytesLength(4))
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -141,18 +137,11 @@ fun bytes64ToLong(buf: ByteArray): Long {
|
||||
+ (buf[7].toLong() and 0xFF shl 56))
|
||||
}
|
||||
|
||||
|
||||
private const val INT_TO_LONG_MASK: Long = 0xffffffffL
|
||||
|
||||
fun bytes4ToUInt(buf: ByteArray): Long {
|
||||
return bytes4ToInt(buf).toLong() and INT_TO_LONG_MASK
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a 32-bit value.
|
||||
*/
|
||||
fun bytes4ToInt(buf: ByteArray): Int {
|
||||
return ((buf[0].toInt() and 0xFF)
|
||||
fun bytes4ToUInt(buf: ByteArray): UnsignedInt {
|
||||
return UnsignedInt((buf[0].toInt() and 0xFF)
|
||||
+ (buf[1].toInt() and 0xFF shl 8)
|
||||
+ (buf[2].toInt() and 0xFF shl 16)
|
||||
+ (buf[3].toInt() and 0xFF shl 24))
|
||||
@@ -182,11 +171,11 @@ fun bytes5ToDate(buf: ByteArray, calendar: Calendar = Calendar.getInstance()): D
|
||||
System.arraycopy(buf, 0, cDate, 0, dateSize)
|
||||
|
||||
val readOffset = 0
|
||||
val dw1 = byteToUInt(cDate[readOffset])
|
||||
val dw2 = byteToUInt(cDate[readOffset + 1])
|
||||
val dw3 = byteToUInt(cDate[readOffset + 2])
|
||||
val dw4 = byteToUInt(cDate[readOffset + 3])
|
||||
val dw5 = byteToUInt(cDate[readOffset + 4])
|
||||
val dw1 = UnsignedInt.fromByte(cDate[readOffset]).toInt()
|
||||
val dw2 = UnsignedInt.fromByte(cDate[readOffset + 1]).toInt()
|
||||
val dw3 = UnsignedInt.fromByte(cDate[readOffset + 2]).toInt()
|
||||
val dw4 = UnsignedInt.fromByte(cDate[readOffset + 3]).toInt()
|
||||
val dw5 = UnsignedInt.fromByte(cDate[readOffset + 4]).toInt()
|
||||
|
||||
// Unpack 5 byte structure to date and time
|
||||
val year = dw1 shl 6 or (dw2 shr 2)
|
||||
@@ -205,19 +194,12 @@ fun bytes5ToDate(buf: ByteArray, calendar: Calendar = Calendar.getInstance()): D
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an unsigned Integer to byte
|
||||
* Write a 32-bit Int value.
|
||||
*/
|
||||
fun uIntToByte(value: Int): Byte {
|
||||
return (value and 0xFF).toByte()
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a 32-bit value.
|
||||
*/
|
||||
fun intTo4Bytes(value: Int): ByteArray {
|
||||
fun uIntTo4Bytes(value: UnsignedInt): ByteArray {
|
||||
val buf = ByteArray(4)
|
||||
for (i in 0 until 4) {
|
||||
buf[i] = (value.ushr(8 * i) and 0xFF).toByte()
|
||||
buf[i] = (value.toInt().ushr(8 * i) and 0xFF).toByte()
|
||||
}
|
||||
return buf
|
||||
}
|
||||
@@ -264,8 +246,8 @@ fun dateTo5Bytes(date: Date, calendar: Calendar = Calendar.getInstance()): ByteA
|
||||
val minute = calendar.get(Calendar.MINUTE)
|
||||
val second = calendar.get(Calendar.SECOND)
|
||||
|
||||
buf[0] = uIntToByte(year shr 6 and 0x0000003F)
|
||||
buf[1] = uIntToByte(year and 0x0000003F shl 2 or (month shr 2 and 0x00000003))
|
||||
buf[0] = UnsignedInt(year shr 6 and 0x0000003F).toByte()
|
||||
buf[1] = UnsignedInt(year and 0x0000003F shl 2 or (month shr 2 and 0x00000003)).toByte()
|
||||
buf[2] = (month and 0x00000003 shl 6
|
||||
or (day and 0x0000001F shl 1) or (hour shr 4 and 0x00000001)).toByte()
|
||||
buf[3] = (hour and 0x0000000F shl 4 or (minute shr 2 and 0x0000000F)).toByte()
|
||||
@@ -273,9 +255,3 @@ fun dateTo5Bytes(date: Date, calendar: Calendar = Calendar.getInstance()): ByteA
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
|
||||
/** Convert a byte to an unsigned byte */
|
||||
fun byteToUInt(byte: Byte): Int {
|
||||
return byte.toInt() and 0xFF
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
package com.kunzisoft.keepass.utils
|
||||
|
||||
import com.kunzisoft.keepass.stream.intTo4Bytes
|
||||
import com.kunzisoft.keepass.stream.uIntTo4Bytes
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
import java.nio.charset.Charset
|
||||
@@ -57,7 +57,7 @@ object StringDatabaseKDBUtils {
|
||||
var str = string
|
||||
if (str == null) {
|
||||
// Write out a null character
|
||||
os.write(intTo4Bytes(1))
|
||||
os.write(uIntTo4Bytes(UnsignedInt(1)))
|
||||
os.write(0x00)
|
||||
return 0
|
||||
}
|
||||
@@ -69,7 +69,7 @@ object StringDatabaseKDBUtils {
|
||||
val initial = str.toByteArray(defaultCharset)
|
||||
|
||||
val length = initial.size + 1
|
||||
os.write(intTo4Bytes(length))
|
||||
os.write(uIntTo4Bytes(UnsignedInt(length)))
|
||||
os.write(initial)
|
||||
os.write(0x00)
|
||||
|
||||
|
||||
86
app/src/main/java/com/kunzisoft/keepass/utils/UnsignedInt.kt
Normal file
86
app/src/main/java/com/kunzisoft/keepass/utils/UnsignedInt.kt
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.utils
|
||||
|
||||
class UnsignedInt(private var unsignedValue: Int) {
|
||||
|
||||
constructor(unsignedValue: UnsignedInt) : this(unsignedValue.toInt())
|
||||
|
||||
/**
|
||||
* Get the int value
|
||||
*/
|
||||
fun toInt(): Int {
|
||||
return unsignedValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an unsigned Integer to Long
|
||||
*/
|
||||
fun toLong(): Long {
|
||||
return unsignedValue.toLong() and INT_TO_LONG_MASK
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an unsigned Integer to Byte
|
||||
*/
|
||||
fun toByte(): Byte {
|
||||
return (unsignedValue and 0xFF).toByte()
|
||||
}
|
||||
|
||||
override fun toString():String {
|
||||
return toLong().toString()
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as UnsignedInt
|
||||
|
||||
if (unsignedValue != other.unsignedValue) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return unsignedValue
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val INT_TO_LONG_MASK: Long = 0xffffffffL
|
||||
private const val UINT_MAX_VALUE: Long = 4294967296L // 2^32
|
||||
|
||||
val MAX_VALUE = UnsignedInt(UINT_MAX_VALUE.toInt())
|
||||
|
||||
/**
|
||||
* Convert a byte to an unsigned byte
|
||||
*/
|
||||
fun fromByte(value: Byte): UnsignedInt {
|
||||
return UnsignedInt(value.toInt() and 0xFF)
|
||||
}
|
||||
|
||||
@Throws(NumberFormatException::class)
|
||||
fun fromLong(value: Long): UnsignedInt {
|
||||
if (value > UINT_MAX_VALUE)
|
||||
throw NumberFormatException("UInt value > $UINT_MAX_VALUE")
|
||||
return UnsignedInt(value.toInt())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2020 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePassDX.
|
||||
*
|
||||
* KeePassDX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePassDX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package com.kunzisoft.keepass.utils
|
||||
|
||||
class UnsignedLong(private var unsignedValue: Long) {
|
||||
|
||||
/**
|
||||
* Convert an unsigned Integer to Long
|
||||
*/
|
||||
fun toLong(): Long {
|
||||
return unsignedValue
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as UnsignedLong
|
||||
|
||||
if (unsignedValue != other.unsignedValue) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return unsignedValue.hashCode()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ULONG_MAX_VALUE: Long = -1
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,10 @@ import com.kunzisoft.keepass.stream.LittleEndianDataOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.kunzisoft.keepass.stream.StreamBytesUtilsKt.bytes4ToInt;
|
||||
import static com.kunzisoft.keepass.stream.StreamBytesUtilsKt.bytes4ToUInt;
|
||||
import static com.kunzisoft.keepass.stream.StreamBytesUtilsKt.bytes64ToLong;
|
||||
|
||||
@@ -35,6 +35,7 @@ public class VariantDictionary {
|
||||
private static final int VdVersion = 0x0100;
|
||||
private static final int VdmCritical = 0xFF00;
|
||||
private static final int VdmInfo = 0x00FF;
|
||||
private static Charset UTF8Charset = Charset.forName("UTF-8");
|
||||
|
||||
private Map<String, VdType> dict = new HashMap<>();
|
||||
|
||||
@@ -69,8 +70,8 @@ public class VariantDictionary {
|
||||
dict.put(name, new VdType(type, value));
|
||||
}
|
||||
|
||||
public void setUInt32(String name, long value) { putType(VdType.UInt32, name, value); }
|
||||
public long getUInt32(String name) { return (long)dict.get(name).value; }
|
||||
public void setUInt32(String name, UnsignedInt value) { putType(VdType.UInt32, name, value); }
|
||||
public UnsignedInt getUInt32(String name) { return (UnsignedInt)dict.get(name).value; }
|
||||
|
||||
public void setUInt64(String name, long value) { putType(VdType.UInt64, name, value); }
|
||||
public long getUInt64(String name) { return (long)dict.get(name).value; }
|
||||
@@ -109,14 +110,14 @@ public class VariantDictionary {
|
||||
break;
|
||||
}
|
||||
|
||||
int nameLen = lis.readInt();
|
||||
int nameLen = lis.readUInt().toInt();
|
||||
byte[] nameBuf = lis.readBytes(nameLen);
|
||||
if (nameLen != nameBuf.length) {
|
||||
throw new IOException("Invalid format");
|
||||
}
|
||||
String name = new String(nameBuf, "UTF-8");
|
||||
String name = new String(nameBuf, UTF8Charset);
|
||||
|
||||
int valueLen = lis.readInt();
|
||||
int valueLen = lis.readUInt().toInt();
|
||||
byte[] valueBuf = lis.readBytes(valueLen);
|
||||
if (valueLen != valueBuf.length) {
|
||||
throw new IOException("Invalid format");
|
||||
@@ -140,7 +141,7 @@ public class VariantDictionary {
|
||||
break;
|
||||
case VdType.Int32:
|
||||
if (valueLen == 4) {
|
||||
d.setInt32(name, bytes4ToInt(valueBuf));
|
||||
d.setInt32(name, bytes4ToUInt(valueBuf).toInt());
|
||||
}
|
||||
break;
|
||||
case VdType.Int64:
|
||||
@@ -149,7 +150,7 @@ public class VariantDictionary {
|
||||
}
|
||||
break;
|
||||
case VdType.String:
|
||||
d.setString(name, new String(valueBuf, "UTF-8"));
|
||||
d.setString(name, new String(valueBuf, UTF8Charset));
|
||||
break;
|
||||
case VdType.ByteArray:
|
||||
d.setByteArray(name, valueBuf);
|
||||
@@ -172,12 +173,7 @@ public class VariantDictionary {
|
||||
|
||||
for (Map.Entry<String, VdType> entry: d.dict.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
byte[] nameBuf = null;
|
||||
try {
|
||||
nameBuf = name.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new IOException("Couldn't encode parameter name.");
|
||||
}
|
||||
byte[] nameBuf = nameBuf = name.getBytes(UTF8Charset);
|
||||
|
||||
VdType vd = entry.getValue();
|
||||
|
||||
@@ -189,7 +185,7 @@ public class VariantDictionary {
|
||||
switch (vd.type) {
|
||||
case VdType.UInt32:
|
||||
los.writeInt(4);
|
||||
los.writeUInt((long)vd.value);
|
||||
los.writeUInt((UnsignedInt) vd.value);
|
||||
break;
|
||||
case VdType.UInt64:
|
||||
los.writeInt(8);
|
||||
@@ -210,7 +206,7 @@ public class VariantDictionary {
|
||||
break;
|
||||
case VdType.String:
|
||||
String value = (String)vd.value;
|
||||
buf = value.getBytes("UTF-8");
|
||||
buf = value.getBytes(UTF8Charset);
|
||||
los.writeInt(buf.length);
|
||||
los.write(buf);
|
||||
break;
|
||||
@@ -231,7 +227,6 @@ public class VariantDictionary {
|
||||
for (Map.Entry<String, VdType> entry : d.dict.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
VdType value = entry.getValue();
|
||||
|
||||
dict.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,12 +126,11 @@ void throwExceptionF(JNIEnv *env, jclass exception, const char *format, ...) {
|
||||
}
|
||||
|
||||
#define ARGON2_HASHLEN 32
|
||||
#define NB_BLOCKSIZE 1024
|
||||
|
||||
JNIEXPORT jbyteArray
|
||||
JNICALL Java_com_kunzisoft_keepass_crypto_keyDerivation_Argon2Native_nTransformMasterKey(JNIEnv *env,
|
||||
jobject this, jbyteArray password, jbyteArray salt, jint parallelism, jlong memory,
|
||||
jlong iterations, jbyteArray secretKey, jbyteArray associatedData, jlong version) {
|
||||
jobject this, jbyteArray password, jbyteArray salt, jint parallelism, jint memory,
|
||||
jint iterations, jbyteArray secretKey, jbyteArray associatedData, jint version) {
|
||||
|
||||
argon2_context context;
|
||||
uint8_t *out;
|
||||
@@ -151,7 +150,7 @@ JNICALL Java_com_kunzisoft_keepass_crypto_keyDerivation_Argon2Native_nTransformM
|
||||
uint8_t *adBuf;
|
||||
uint32_t adLen = getJNIArray(env, associatedData, &adBuf);
|
||||
|
||||
context.out = (uint8_t *) out;
|
||||
context.out = out;
|
||||
context.outlen = ARGON2_HASHLEN;
|
||||
context.pwd = passwordBuf;
|
||||
context.pwdlen = passwordLen;
|
||||
@@ -162,7 +161,7 @@ JNICALL Java_com_kunzisoft_keepass_crypto_keyDerivation_Argon2Native_nTransformM
|
||||
context.ad = adBuf;
|
||||
context.adlen = adLen;
|
||||
context.t_cost = (uint32_t) iterations;
|
||||
context.m_cost = ((uint32_t) memory) / NB_BLOCKSIZE;
|
||||
context.m_cost = (uint32_t) memory;
|
||||
context.lanes = (uint32_t) parallelism;
|
||||
context.threads = (uint32_t) parallelism;
|
||||
context.allocate_cbk = NULL;
|
||||
|
||||
@@ -438,7 +438,7 @@ uint32_t generate_key_material(void *arg) {
|
||||
return flip;
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL Java_com_kunzisoft_keepass_crypto_finalkey_NativeFinalKey_nTransformMasterKey(JNIEnv *env, jobject this, jbyteArray seed, jbyteArray key, jlong rounds) {
|
||||
JNIEXPORT jbyteArray JNICALL Java_com_kunzisoft_keepass_crypto_finalkey_NativeAESKeyTransformer_nTransformMasterKey(JNIEnv *env, jobject this, jbyteArray seed, jbyteArray key, jlong rounds) {
|
||||
master_key mk;
|
||||
uint32_t flip;
|
||||
pthread_t t1, t2;
|
||||
|
||||
Reference in New Issue
Block a user