mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Merge branch 'feature/RefactorImporter' into develop
This commit is contained in:
@@ -30,9 +30,9 @@ import junit.framework.TestCase
|
||||
import com.kunzisoft.keepass.database.element.PwDate
|
||||
import com.kunzisoft.keepass.stream.LEDataInputStream
|
||||
import com.kunzisoft.keepass.stream.LEDataOutputStream
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
|
||||
class TypesTest : TestCase() {
|
||||
class DatabaseInputOutputUtilsTest : TestCase() {
|
||||
|
||||
fun testReadWriteLongZero() {
|
||||
testReadWriteLong(0.toByte())
|
||||
@@ -155,8 +155,8 @@ class TypesTest : TestCase() {
|
||||
|
||||
setArray(orig, value, 0, 1)
|
||||
|
||||
val one = Types.readUByte(orig, 0)
|
||||
Types.writeUByte(one, dest, 0)
|
||||
val one = DatabaseInputOutputUtils.readUByte(orig, 0)
|
||||
DatabaseInputOutputUtils.writeUByte(one, dest, 0)
|
||||
|
||||
assertArrayEquals(orig, dest)
|
||||
|
||||
@@ -185,8 +185,8 @@ class TypesTest : TestCase() {
|
||||
val bUUID = ByteArray(16)
|
||||
rnd.nextBytes(bUUID)
|
||||
|
||||
val uuid = Types.bytestoUUID(bUUID)
|
||||
val eUUID = Types.UUIDtoBytes(uuid)
|
||||
val uuid = DatabaseInputOutputUtils.bytestoUUID(bUUID)
|
||||
val eUUID = DatabaseInputOutputUtils.UUIDtoBytes(uuid)
|
||||
|
||||
assertArrayEquals("UUID match failed", bUUID, eUUID)
|
||||
}
|
||||
@@ -200,7 +200,7 @@ class TypesTest : TestCase() {
|
||||
|
||||
val bos = ByteArrayOutputStream()
|
||||
val leos = LEDataOutputStream(bos)
|
||||
leos.writeLong(Types.ULONG_MAX_VALUE)
|
||||
leos.writeLong(DatabaseInputOutputUtils.ULONG_MAX_VALUE)
|
||||
leos.close()
|
||||
|
||||
val uLongMax = bos.toByteArray()
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.crypto.engine
|
||||
|
||||
import com.kunzisoft.keepass.crypto.CipherFactory
|
||||
import com.kunzisoft.keepass.database.element.PwEncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import java.security.InvalidAlgorithmParameterException
|
||||
import java.security.InvalidKeyException
|
||||
import java.security.NoSuchAlgorithmException
|
||||
@@ -47,7 +47,7 @@ class AesEngine : CipherEngine() {
|
||||
|
||||
companion object {
|
||||
|
||||
val CIPHER_UUID: UUID = Types.bytestoUUID(
|
||||
val CIPHER_UUID: UUID = DatabaseInputOutputUtils.bytestoUUID(
|
||||
byteArrayOf(0x31.toByte(), 0xC1.toByte(), 0xF2.toByte(), 0xE6.toByte(), 0xBF.toByte(), 0x71.toByte(), 0x43.toByte(), 0x50.toByte(), 0xBE.toByte(), 0x58.toByte(), 0x05.toByte(), 0x21.toByte(), 0x6A.toByte(), 0xFC.toByte(), 0x5A.toByte(), 0xFF.toByte()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
package com.kunzisoft.keepass.crypto.engine
|
||||
|
||||
import com.kunzisoft.keepass.database.element.PwEncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import org.spongycastle.jce.provider.BouncyCastleProvider
|
||||
import java.security.InvalidAlgorithmParameterException
|
||||
import java.security.InvalidKeyException
|
||||
@@ -50,7 +50,7 @@ class ChaCha20Engine : CipherEngine() {
|
||||
|
||||
companion object {
|
||||
|
||||
val CIPHER_UUID: UUID = Types.bytestoUUID(
|
||||
val CIPHER_UUID: UUID = DatabaseInputOutputUtils.bytestoUUID(
|
||||
byteArrayOf(0xD6.toByte(), 0x03.toByte(), 0x8A.toByte(), 0x2B.toByte(), 0x8B.toByte(), 0x6F.toByte(), 0x4C.toByte(), 0xB5.toByte(), 0xA5.toByte(), 0x24.toByte(), 0x33.toByte(), 0x9A.toByte(), 0x31.toByte(), 0xDB.toByte(), 0xB5.toByte(), 0x9A.toByte()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.crypto.engine
|
||||
|
||||
import com.kunzisoft.keepass.crypto.CipherFactory
|
||||
import com.kunzisoft.keepass.database.element.PwEncryptionAlgorithm
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException
|
||||
import java.security.InvalidKeyException
|
||||
@@ -53,7 +53,7 @@ class TwofishEngine : CipherEngine() {
|
||||
|
||||
companion object {
|
||||
|
||||
val CIPHER_UUID: UUID = Types.bytestoUUID(
|
||||
val CIPHER_UUID: UUID = DatabaseInputOutputUtils.bytestoUUID(
|
||||
byteArrayOf(0xAD.toByte(), 0x68.toByte(), 0xF2.toByte(), 0x9F.toByte(), 0x57.toByte(), 0x6F.toByte(), 0x4B.toByte(), 0xB9.toByte(), 0xA3.toByte(), 0x6A.toByte(), 0xD4.toByte(), 0x7A.toByte(), 0xF9.toByte(), 0x65.toByte(), 0x34.toByte(), 0x6C.toByte()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ 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.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import java.io.IOException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
@@ -88,7 +88,7 @@ class AesKdf internal constructor() : KdfEngine() {
|
||||
|
||||
private const val DEFAULT_ROUNDS = 6000
|
||||
|
||||
val CIPHER_UUID: UUID = Types.bytestoUUID(
|
||||
val CIPHER_UUID: UUID = DatabaseInputOutputUtils.bytestoUUID(
|
||||
byteArrayOf(0xC9.toByte(),
|
||||
0xD9.toByte(),
|
||||
0xF3.toByte(),
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.crypto.keyDerivation
|
||||
|
||||
import android.content.res.Resources
|
||||
import com.kunzisoft.keepass.R
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import java.io.IOException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
@@ -126,7 +126,7 @@ class Argon2Kdf internal constructor() : KdfEngine() {
|
||||
|
||||
companion object {
|
||||
|
||||
val CIPHER_UUID: UUID = Types.bytestoUUID(
|
||||
val CIPHER_UUID: UUID = DatabaseInputOutputUtils.bytestoUUID(
|
||||
byteArrayOf(0xEF.toByte(),
|
||||
0x63.toByte(),
|
||||
0x6D.toByte(),
|
||||
|
||||
@@ -22,7 +22,7 @@ package com.kunzisoft.keepass.crypto.keyDerivation;
|
||||
import com.kunzisoft.keepass.utils.VariantDictionary;
|
||||
import com.kunzisoft.keepass.stream.LEDataInputStream;
|
||||
import com.kunzisoft.keepass.stream.LEDataOutputStream;
|
||||
import com.kunzisoft.keepass.utils.Types;
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -44,7 +44,7 @@ public class KdfParameters extends VariantDictionary {
|
||||
}
|
||||
|
||||
protected void setParamUUID() {
|
||||
setByteArray(ParamUUID, Types.UUIDtoBytes(kdfUUID));
|
||||
setByteArray(ParamUUID, DatabaseInputOutputUtils.UUIDtoBytes(kdfUUID));
|
||||
}
|
||||
|
||||
public static KdfParameters deserialize(byte[] data) throws IOException {
|
||||
@@ -56,7 +56,7 @@ public class KdfParameters extends VariantDictionary {
|
||||
return null;
|
||||
}
|
||||
|
||||
UUID uuid = Types.bytestoUUID(d.getByteArray(ParamUUID));
|
||||
UUID uuid = DatabaseInputOutputUtils.bytestoUUID(d.getByteArray(ParamUUID));
|
||||
|
||||
KdfParameters kdfP = new KdfParameters(uuid);
|
||||
kdfP.copyTo(d);
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.content.res.Resources
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@@ -188,11 +188,11 @@ class PwDate : Parcelable {
|
||||
*/
|
||||
fun readTime(buf: ByteArray?, offset: Int, calendar: Calendar?): Date {
|
||||
var time = calendar
|
||||
val dw1 = Types.readUByte(buf!!, offset)
|
||||
val dw2 = Types.readUByte(buf, offset + 1)
|
||||
val dw3 = Types.readUByte(buf, offset + 2)
|
||||
val dw4 = Types.readUByte(buf, offset + 3)
|
||||
val dw5 = Types.readUByte(buf, offset + 4)
|
||||
val dw1 = DatabaseInputOutputUtils.readUByte(buf!!, offset)
|
||||
val dw2 = DatabaseInputOutputUtils.readUByte(buf, offset + 1)
|
||||
val dw3 = DatabaseInputOutputUtils.readUByte(buf, offset + 2)
|
||||
val dw4 = DatabaseInputOutputUtils.readUByte(buf, offset + 3)
|
||||
val dw5 = DatabaseInputOutputUtils.readUByte(buf, offset + 4)
|
||||
|
||||
// Unpack 5 byte structure to date and time
|
||||
val year = dw1 shl 6 or (dw2 shr 2)
|
||||
@@ -236,8 +236,8 @@ class PwDate : Parcelable {
|
||||
val minute = cal.get(Calendar.MINUTE)
|
||||
val second = cal.get(Calendar.SECOND)
|
||||
|
||||
buf[0] = Types.writeUByte(year shr 6 and 0x0000003F)
|
||||
buf[1] = Types.writeUByte(year and 0x0000003F shl 2 or (month shr 2 and 0x00000003))
|
||||
buf[0] = DatabaseInputOutputUtils.writeUByte(year shr 6 and 0x0000003F)
|
||||
buf[1] = DatabaseInputOutputUtils.writeUByte(year and 0x0000003F shl 2 or (month shr 2 and 0x00000003))
|
||||
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()
|
||||
|
||||
@@ -21,11 +21,7 @@ package com.kunzisoft.keepass.database.element
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
import java.io.UnsupportedEncodingException
|
||||
import java.util.Arrays
|
||||
import java.util.UUID
|
||||
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Structure containing information about one entry.
|
||||
@@ -56,12 +52,11 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
|
||||
* @return the actual binaryData byte array.
|
||||
*/
|
||||
var binaryData: ByteArray = ByteArray(0)
|
||||
private set
|
||||
|
||||
// Determine if this is a MetaStream entry
|
||||
val isMetaStream: Boolean
|
||||
get() {
|
||||
if (Arrays.equals(binaryData, ByteArray(0))) return false
|
||||
if (binaryData.contentEquals(ByteArray(0))) return false
|
||||
if (notes.isEmpty()) return false
|
||||
if (binaryDesc != PMS_ID_BINDESC) return false
|
||||
if (title.isEmpty()) return false
|
||||
@@ -85,10 +80,11 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
|
||||
constructor(parcel: Parcel) : super(parcel) {
|
||||
title = parcel.readString() ?: title
|
||||
username = parcel.readString() ?: username
|
||||
parcel.readByteArray(passwordBytes)
|
||||
password = parcel.readString() ?: password
|
||||
url = parcel.readString() ?: url
|
||||
notes = parcel.readString() ?: notes
|
||||
binaryDesc = parcel.readString() ?: binaryDesc
|
||||
binaryData = ByteArray(parcel.readInt())
|
||||
parcel.readByteArray(binaryData)
|
||||
}
|
||||
|
||||
@@ -104,10 +100,11 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
|
||||
super.writeToParcel(dest, flags)
|
||||
dest.writeString(title)
|
||||
dest.writeString(username)
|
||||
dest.writeByteArray(passwordBytes)
|
||||
dest.writeString(password)
|
||||
dest.writeString(url)
|
||||
dest.writeString(notes)
|
||||
dest.writeString(binaryDesc)
|
||||
dest.writeInt(binaryData.size)
|
||||
dest.writeByteArray(binaryData)
|
||||
}
|
||||
|
||||
@@ -115,11 +112,7 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
|
||||
super.updateWith(source)
|
||||
title = source.title
|
||||
username = source.username
|
||||
|
||||
val passLen = source.passwordBytes.size
|
||||
passwordBytes = ByteArray(passLen)
|
||||
System.arraycopy(source.passwordBytes, 0, passwordBytes, 0, passLen)
|
||||
|
||||
password = source.password
|
||||
url = source.url
|
||||
notes = source.notes
|
||||
binaryDesc = source.binaryDesc
|
||||
@@ -131,32 +124,10 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
|
||||
|
||||
override var username = ""
|
||||
|
||||
var passwordBytes: ByteArray = ByteArray(0)
|
||||
private set
|
||||
|
||||
/** Securely erase old password before copying new. */
|
||||
fun setPassword(buf: ByteArray, offset: Int, len: Int) {
|
||||
fill(passwordBytes, 0.toByte())
|
||||
passwordBytes = ByteArray(len)
|
||||
System.arraycopy(buf, offset, passwordBytes, 0, len)
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the actual password byte array.
|
||||
*/
|
||||
override var password: String
|
||||
get() = String(passwordBytes)
|
||||
set(pass) {
|
||||
var password: ByteArray
|
||||
try {
|
||||
password = pass.toByteArray(charset("UTF-8"))
|
||||
setPassword(password, 0, password.size)
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
password = pass.toByteArray()
|
||||
setPassword(password, 0, password.size)
|
||||
}
|
||||
|
||||
}
|
||||
override var password = ""
|
||||
|
||||
override var url = ""
|
||||
|
||||
@@ -167,13 +138,6 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
|
||||
override val type: Type
|
||||
get() = Type.ENTRY
|
||||
|
||||
fun setBinaryData(buf: ByteArray, offset: Int, len: Int) {
|
||||
/** Securely erase old data before copying new. */
|
||||
fill(binaryData, 0.toByte())
|
||||
binaryData = ByteArray(len)
|
||||
System.arraycopy(buf, offset, binaryData, 0, len)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
/** Size of byte buffer needed to hold this struct. */
|
||||
@@ -184,21 +148,13 @@ class PwEntryV3 : PwEntry<Int, UUID, PwGroupV3, PwEntryV3>, PwNodeV3Interface {
|
||||
|
||||
@JvmField
|
||||
val CREATOR: Parcelable.Creator<PwEntryV3> = object : Parcelable.Creator<PwEntryV3> {
|
||||
override fun createFromParcel(`in`: Parcel): PwEntryV3 {
|
||||
return PwEntryV3(`in`)
|
||||
override fun createFromParcel(parcel: Parcel): PwEntryV3 {
|
||||
return PwEntryV3(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<PwEntryV3?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fill byte array
|
||||
*/
|
||||
private fun fill(array: ByteArray, value: Byte) {
|
||||
for (i in array.indices)
|
||||
array[i] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ class ProtectedBinary : Parcelable {
|
||||
|
||||
private constructor(parcel: Parcel) {
|
||||
isProtected = parcel.readByte().toInt() != 0
|
||||
data = ByteArray(parcel.readInt())
|
||||
parcel.readByteArray(data)
|
||||
dataFile = File(parcel.readString())
|
||||
size = parcel.readInt()
|
||||
@@ -130,8 +131,9 @@ class ProtectedBinary : Parcelable {
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
dest.writeByte((if (isProtected) 1 else 0).toByte())
|
||||
dest.writeInt(data?.size ?: 0)
|
||||
dest.writeByteArray(data)
|
||||
dest.writeString(dataFile!!.absolutePath)
|
||||
dest.writeString(dataFile?.absolutePath)
|
||||
dest.writeInt(size)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.kunzisoft.keepass.database.exception.LoadDatabaseVersionException
|
||||
import com.kunzisoft.keepass.stream.CopyInputStream
|
||||
import com.kunzisoft.keepass.stream.HmacBlockStream
|
||||
import com.kunzisoft.keepass.stream.LEDataInputStream
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
@@ -239,7 +239,7 @@ class PwDbHeaderV4(private val databaseV4: PwDatabaseV4) : PwDbHeader() {
|
||||
throw IOException("Invalid cipher ID.")
|
||||
}
|
||||
|
||||
databaseV4.dataCipher = Types.bytestoUUID(pbId)
|
||||
databaseV4.dataCipher = DatabaseInputOutputUtils.bytestoUUID(pbId)
|
||||
}
|
||||
|
||||
private fun setTransformRound(roundsByte: ByteArray?) {
|
||||
@@ -319,7 +319,7 @@ class PwDbHeaderV4(private val databaseV4: PwDatabaseV4) : PwDbHeader() {
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun computeHeaderHmac(header: ByteArray, key: ByteArray): ByteArray {
|
||||
val blockKey = HmacBlockStream.GetHmacKey64(key, Types.ULONG_MAX_VALUE)
|
||||
val blockKey = HmacBlockStream.GetHmacKey64(key, DatabaseInputOutputUtils.ULONG_MAX_VALUE)
|
||||
|
||||
val hmac: Mac
|
||||
try {
|
||||
|
||||
@@ -55,7 +55,7 @@ import com.kunzisoft.keepass.database.file.PwDbHeaderV3
|
||||
import com.kunzisoft.keepass.stream.LEDataInputStream
|
||||
import com.kunzisoft.keepass.stream.NullOutputStream
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
|
||||
import javax.crypto.*
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
@@ -287,7 +287,7 @@ class ImporterV3 : Importer<PwDatabaseV3>() {
|
||||
0x0000 -> {
|
||||
}
|
||||
0x0001 -> grp.setGroupId(LEDataInputStream.readInt(buf, offset))
|
||||
0x0002 -> grp.title = Types.readCString(buf, offset)
|
||||
0x0002 -> grp.title = DatabaseInputOutputUtils.readCString(buf, offset)
|
||||
0x0003 -> grp.creationTime = PwDate(buf, offset)
|
||||
0x0004 -> grp.lastModificationTime = PwDate(buf, offset)
|
||||
0x0005 -> grp.lastAccessTime = PwDate(buf, offset)
|
||||
@@ -309,7 +309,7 @@ class ImporterV3 : Importer<PwDatabaseV3>() {
|
||||
when (fieldType) {
|
||||
0x0000 -> {
|
||||
}
|
||||
0x0001 -> ent.nodeId = PwNodeIdUUID(Types.bytestoUUID(buf, offsetMutable))
|
||||
0x0001 -> ent.nodeId = PwNodeIdUUID(DatabaseInputOutputUtils.bytestoUUID(buf, offsetMutable))
|
||||
0x0002 -> {
|
||||
val pwGroupV3 = mDatabaseToOpen.createGroup()
|
||||
pwGroupV3.nodeId = PwNodeIdInt(LEDataInputStream.readInt(buf, offsetMutable))
|
||||
@@ -325,17 +325,17 @@ class ImporterV3 : Importer<PwDatabaseV3>() {
|
||||
|
||||
ent.icon = db.iconFactory.getIcon(iconId)
|
||||
}
|
||||
0x0004 -> ent.title = Types.readCString(buf, offsetMutable)
|
||||
0x0005 -> ent.url = Types.readCString(buf, offsetMutable)
|
||||
0x0006 -> ent.username = Types.readCString(buf, offsetMutable)
|
||||
0x0007 -> ent.setPassword(buf, offsetMutable, Types.strlen(buf, offsetMutable))
|
||||
0x0008 -> ent.notes = Types.readCString(buf, offsetMutable)
|
||||
0x0004 -> ent.title = DatabaseInputOutputUtils.readCString(buf, offsetMutable)
|
||||
0x0005 -> ent.url = DatabaseInputOutputUtils.readCString(buf, offsetMutable)
|
||||
0x0006 -> ent.username = DatabaseInputOutputUtils.readCString(buf, offsetMutable)
|
||||
0x0007 -> ent.password = DatabaseInputOutputUtils.readPassword(buf, offsetMutable)
|
||||
0x0008 -> ent.notes = DatabaseInputOutputUtils.readCString(buf, offsetMutable)
|
||||
0x0009 -> ent.creationTime = PwDate(buf, offsetMutable)
|
||||
0x000A -> ent.lastModificationTime = PwDate(buf, offsetMutable)
|
||||
0x000B -> ent.lastAccessTime = PwDate(buf, offsetMutable)
|
||||
0x000C -> ent.expiryTime = PwDate(buf, offsetMutable)
|
||||
0x000D -> ent.binaryDesc = Types.readCString(buf, offsetMutable)
|
||||
0x000E -> ent.setBinaryData(buf, offsetMutable, fieldSize)
|
||||
0x000D -> ent.binaryDesc = DatabaseInputOutputUtils.readCString(buf, offsetMutable)
|
||||
0x000E -> ent.binaryData = DatabaseInputOutputUtils.readBytes(buf, offsetMutable, fieldSize)
|
||||
}// Ignore field
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ import com.kunzisoft.keepass.stream.HmacBlockInputStream
|
||||
import com.kunzisoft.keepass.stream.LEDataInputStream
|
||||
import com.kunzisoft.keepass.tasks.ProgressTaskUpdater
|
||||
import com.kunzisoft.keepass.utils.MemoryUtil
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import org.spongycastle.crypto.StreamCipher
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import org.xmlpull.v1.XmlPullParserException
|
||||
@@ -876,7 +876,7 @@ class ImporterV4(private val streamDir: File,
|
||||
// TODO: Switch to framework Base64 once API level 8 is the minimum
|
||||
val buf = Base64Coder.decode(encoded)
|
||||
|
||||
return Types.bytestoUUID(buf)
|
||||
return DatabaseInputOutputUtils.bytestoUUID(buf)
|
||||
}
|
||||
|
||||
@Throws(IOException::class, XmlPullParserException::class)
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.kunzisoft.keepass.database.exception.DatabaseOutputException
|
||||
import com.kunzisoft.keepass.stream.HmacBlockStream
|
||||
import com.kunzisoft.keepass.stream.LEDataOutputStream
|
||||
import com.kunzisoft.keepass.stream.MacOutputStream
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
@@ -66,7 +66,7 @@ constructor(private val db: PwDatabaseV4, private val header: PwDbHeaderV4, os:
|
||||
val hmac: Mac
|
||||
try {
|
||||
hmac = Mac.getInstance("HmacSHA256")
|
||||
val signingKey = SecretKeySpec(HmacBlockStream.GetHmacKey64(db.hmacKey, Types.ULONG_MAX_VALUE), "HmacSHA256")
|
||||
val signingKey = SecretKeySpec(HmacBlockStream.GetHmacKey64(db.hmacKey, DatabaseInputOutputUtils.ULONG_MAX_VALUE), "HmacSHA256")
|
||||
hmac.init(signingKey)
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
throw DatabaseOutputException(e)
|
||||
@@ -86,7 +86,7 @@ constructor(private val db: PwDatabaseV4, private val header: PwDbHeaderV4, os:
|
||||
los.writeUInt(PwDbHeaderV4.DBSIG_2.toLong())
|
||||
los.writeUInt(header.version)
|
||||
|
||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.CipherID, Types.UUIDtoBytes(db.dataCipher))
|
||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.CipherID, DatabaseInputOutputUtils.UUIDtoBytes(db.dataCipher))
|
||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.CompressionFlags, LEDataOutputStream.writeIntBuf(PwDbHeaderV4.getFlagFromCompression(db.compressionAlgorithm)))
|
||||
writeHeaderField(PwDbHeaderV4.PwDbHeaderV4Fields.MasterSeed, header.masterSeed)
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ import com.kunzisoft.keepass.stream.HmacBlockOutputStream
|
||||
import com.kunzisoft.keepass.stream.LEDataOutputStream
|
||||
import com.kunzisoft.keepass.database.file.KDBX4DateUtil
|
||||
import com.kunzisoft.keepass.utils.MemoryUtil
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
import org.joda.time.DateTime
|
||||
import org.spongycastle.crypto.StreamCipher
|
||||
import org.xmlpull.v1.XmlSerializer
|
||||
@@ -505,7 +505,7 @@ class PwDbV4Output(private val mDatabaseV4: PwDatabaseV4, outputStream: OutputSt
|
||||
|
||||
@Throws(IllegalArgumentException::class, IllegalStateException::class, IOException::class)
|
||||
private fun writeObject(name: String, uuid: UUID) {
|
||||
val data = Types.UUIDtoBytes(uuid)
|
||||
val data = DatabaseInputOutputUtils.UUIDtoBytes(uuid)
|
||||
writeObject(name, String(Base64Coder.encode(data)))
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.database.file.save
|
||||
|
||||
import com.kunzisoft.keepass.database.element.PwEntryV3
|
||||
import com.kunzisoft.keepass.stream.LEDataOutputStream
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
@@ -30,7 +30,7 @@ class PwEntryOutputV3
|
||||
/**
|
||||
* Output the PwGroupV3 to the stream
|
||||
*/
|
||||
(private val mPE: PwEntryV3, private val mOS: OutputStream) {
|
||||
(private val mEntry: PwEntryV3, private val mOutputStream: OutputStream) {
|
||||
/**
|
||||
* Returns the number of bytes written by the stream
|
||||
* @return Number of bytes written
|
||||
@@ -45,98 +45,82 @@ class PwEntryOutputV3
|
||||
length += 134 // Length of fixed size fields
|
||||
|
||||
// UUID
|
||||
mOS.write(UUID_FIELD_TYPE)
|
||||
mOS.write(UUID_FIELD_SIZE)
|
||||
mOS.write(Types.UUIDtoBytes(mPE.id))
|
||||
mOutputStream.write(UUID_FIELD_TYPE)
|
||||
mOutputStream.write(UUID_FIELD_SIZE)
|
||||
mOutputStream.write(DatabaseInputOutputUtils.UUIDtoBytes(mEntry.id))
|
||||
|
||||
// Group ID
|
||||
mOS.write(GROUPID_FIELD_TYPE)
|
||||
mOS.write(LONG_FOUR)
|
||||
mOS.write(LEDataOutputStream.writeIntBuf(mPE.parent!!.id))
|
||||
mOutputStream.write(GROUPID_FIELD_TYPE)
|
||||
mOutputStream.write(LONG_FOUR)
|
||||
mOutputStream.write(LEDataOutputStream.writeIntBuf(mEntry.parent!!.id))
|
||||
|
||||
// Image ID
|
||||
mOS.write(IMAGEID_FIELD_TYPE)
|
||||
mOS.write(LONG_FOUR)
|
||||
mOS.write(LEDataOutputStream.writeIntBuf(mPE.icon.iconId))
|
||||
mOutputStream.write(IMAGEID_FIELD_TYPE)
|
||||
mOutputStream.write(LONG_FOUR)
|
||||
mOutputStream.write(LEDataOutputStream.writeIntBuf(mEntry.icon.iconId))
|
||||
|
||||
// Title
|
||||
//byte[] title = mPE.title.getBytes("UTF-8");
|
||||
mOS.write(TITLE_FIELD_TYPE)
|
||||
val titleLen = Types.writeCString(mPE.title, mOS)
|
||||
length += titleLen.toLong()
|
||||
//byte[] title = mEntry.title.getBytes("UTF-8");
|
||||
mOutputStream.write(TITLE_FIELD_TYPE)
|
||||
length += DatabaseInputOutputUtils.writeCString(mEntry.title, mOutputStream).toLong()
|
||||
|
||||
// URL
|
||||
mOS.write(URL_FIELD_TYPE)
|
||||
val urlLen = Types.writeCString(mPE.url, mOS)
|
||||
length += urlLen.toLong()
|
||||
mOutputStream.write(URL_FIELD_TYPE)
|
||||
length += DatabaseInputOutputUtils.writeCString(mEntry.url, mOutputStream).toLong()
|
||||
|
||||
// Username
|
||||
mOS.write(USERNAME_FIELD_TYPE)
|
||||
val userLen = Types.writeCString(mPE.username, mOS)
|
||||
length += userLen.toLong()
|
||||
mOutputStream.write(USERNAME_FIELD_TYPE)
|
||||
length += DatabaseInputOutputUtils.writeCString(mEntry.username, mOutputStream).toLong()
|
||||
|
||||
// Password
|
||||
val password = mPE.passwordBytes
|
||||
mOS.write(PASSWORD_FIELD_TYPE)
|
||||
mOS.write(LEDataOutputStream.writeIntBuf(password.size + 1))
|
||||
mOS.write(password)
|
||||
mOS.write(0)
|
||||
length += (password.size + 1).toLong()
|
||||
mOutputStream.write(PASSWORD_FIELD_TYPE)
|
||||
length += DatabaseInputOutputUtils.writePassword(mEntry.password, mOutputStream).toLong()
|
||||
|
||||
// Additional
|
||||
mOS.write(ADDITIONAL_FIELD_TYPE)
|
||||
val addlLen = Types.writeCString(mPE.notes, mOS)
|
||||
length += addlLen.toLong()
|
||||
mOutputStream.write(ADDITIONAL_FIELD_TYPE)
|
||||
length += DatabaseInputOutputUtils.writeCString(mEntry.notes, mOutputStream).toLong()
|
||||
|
||||
// Create date
|
||||
writeDate(CREATE_FIELD_TYPE, mPE.creationTime.byteArrayDate)
|
||||
writeDate(CREATE_FIELD_TYPE, mEntry.creationTime.byteArrayDate)
|
||||
|
||||
// Modification date
|
||||
writeDate(MOD_FIELD_TYPE, mPE.lastModificationTime.byteArrayDate)
|
||||
writeDate(MOD_FIELD_TYPE, mEntry.lastModificationTime.byteArrayDate)
|
||||
|
||||
// Access date
|
||||
writeDate(ACCESS_FIELD_TYPE, mPE.lastAccessTime.byteArrayDate)
|
||||
writeDate(ACCESS_FIELD_TYPE, mEntry.lastAccessTime.byteArrayDate)
|
||||
|
||||
// Expiration date
|
||||
writeDate(EXPIRE_FIELD_TYPE, mPE.expiryTime.byteArrayDate)
|
||||
writeDate(EXPIRE_FIELD_TYPE, mEntry.expiryTime.byteArrayDate)
|
||||
|
||||
// Binary desc
|
||||
mOS.write(BINARY_DESC_FIELD_TYPE)
|
||||
val descLen = Types.writeCString(mPE.binaryDesc, mOS)
|
||||
length += descLen.toLong()
|
||||
|
||||
// Binary data
|
||||
val dataLen = writeByteArray(mPE.binaryData)
|
||||
length += dataLen.toLong()
|
||||
// Binary
|
||||
writeBinary(mEntry.binaryData)
|
||||
|
||||
// End
|
||||
mOS.write(END_FIELD_TYPE)
|
||||
mOS.write(ZERO_FIELD_SIZE)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun writeByteArray(data: ByteArray?): Int {
|
||||
val dataLen: Int = data?.size ?: 0
|
||||
mOS.write(BINARY_DATA_FIELD_TYPE)
|
||||
mOS.write(LEDataOutputStream.writeIntBuf(dataLen))
|
||||
if (data != null) {
|
||||
mOS.write(data)
|
||||
}
|
||||
|
||||
return dataLen
|
||||
mOutputStream.write(END_FIELD_TYPE)
|
||||
mOutputStream.write(ZERO_FIELD_SIZE)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun writeDate(type: ByteArray, date: ByteArray?) {
|
||||
mOS.write(type)
|
||||
mOS.write(DATE_FIELD_SIZE)
|
||||
mOutputStream.write(type)
|
||||
mOutputStream.write(DATE_FIELD_SIZE)
|
||||
if (date != null) {
|
||||
mOS.write(date)
|
||||
mOutputStream.write(date)
|
||||
} else {
|
||||
mOS.write(ZERO_FIVE)
|
||||
mOutputStream.write(ZERO_FIVE)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun writeBinary(data: ByteArray?) {
|
||||
mOutputStream.write(BINARY_DESC_FIELD_TYPE)
|
||||
length += DatabaseInputOutputUtils.writeCString(mEntry.binaryDesc, mOutputStream).toLong()
|
||||
|
||||
val dataLen: Int = data?.size ?: 0
|
||||
mOutputStream.write(BINARY_DATA_FIELD_TYPE)
|
||||
length += DatabaseInputOutputUtils.writeBytes(data, dataLen, mOutputStream)
|
||||
}
|
||||
|
||||
companion object {
|
||||
// Constants
|
||||
val UUID_FIELD_TYPE:ByteArray = LEDataOutputStream.writeUShortBuf(1)
|
||||
|
||||
@@ -21,7 +21,7 @@ package com.kunzisoft.keepass.database.file.save
|
||||
|
||||
import com.kunzisoft.keepass.database.element.PwGroupV3
|
||||
import com.kunzisoft.keepass.stream.LEDataOutputStream
|
||||
import com.kunzisoft.keepass.utils.Types
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.OutputStream
|
||||
@@ -44,7 +44,7 @@ class PwGroupOutputV3
|
||||
|
||||
// Name
|
||||
mOS.write(NAME_FIELD_TYPE)
|
||||
Types.writeCString(mPG.title, mOS)
|
||||
DatabaseInputOutputUtils.writeCString(mPG.title, mOS)
|
||||
|
||||
// Create date
|
||||
mOS.write(CREATE_FIELD_TYPE)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.database.search;
|
||||
|
||||
import com.kunzisoft.keepass.utils.Types;
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -27,7 +27,7 @@ public class UuidUtil {
|
||||
public static String toHexString(UUID uuid) {
|
||||
if (uuid == null) { return null; }
|
||||
|
||||
byte[] buf = Types.UUIDtoBytes(uuid);
|
||||
byte[] buf = DatabaseInputOutputUtils.UUIDtoBytes(uuid);
|
||||
if (buf == null) { return null; }
|
||||
|
||||
int len = buf.length;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.stream;
|
||||
|
||||
import com.kunzisoft.keepass.utils.Types;
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -151,7 +151,7 @@ public class HashedBlockInputStream extends InputStream {
|
||||
if ( ! ReadHashedBlock() ) return -1;
|
||||
}
|
||||
|
||||
int output = Types.readUByte(buffer, bufferPos);
|
||||
int output = DatabaseInputOutputUtils.readUByte(buffer, bufferPos);
|
||||
bufferPos++;
|
||||
|
||||
return output;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
package com.kunzisoft.keepass.stream;
|
||||
|
||||
import com.kunzisoft.keepass.utils.Types;
|
||||
import com.kunzisoft.keepass.utils.DatabaseInputOutputUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -56,7 +56,7 @@ public class HmacBlockInputStream extends InputStream {
|
||||
if (!readSafeBlock()) return -1;
|
||||
}
|
||||
|
||||
int output = Types.readUByte(buffer, bufferPos);
|
||||
int output = DatabaseInputOutputUtils.readUByte(buffer, bufferPos);
|
||||
bufferPos++;
|
||||
|
||||
return output;
|
||||
|
||||
@@ -46,7 +46,7 @@ import com.kunzisoft.keepass.stream.LEDataOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@@ -55,20 +55,24 @@ import java.util.UUID;
|
||||
*
|
||||
* @author Bill Zwicky <wrzwicky@pobox.com>
|
||||
*/
|
||||
public class Types {
|
||||
public class DatabaseInputOutputUtils {
|
||||
|
||||
public static long ULONG_MAX_VALUE = -1;
|
||||
|
||||
private static Charset defaultCharset = Charset.forName("UTF-8");
|
||||
|
||||
private static final byte[] CRLFbuf = { 0x0D, 0x0A };
|
||||
private static final String CRLF = new String(CRLFbuf);
|
||||
private static final String SEP = System.getProperty("line.separator");
|
||||
private static final boolean REPLACE = !SEP.equals(CRLF);
|
||||
|
||||
/** Read an unsigned byte */
|
||||
public static int readUByte( byte[] buf, int offset ) {
|
||||
return ((int)buf[offset] & 0xFF);
|
||||
}
|
||||
|
||||
/** Write an unsigned byte
|
||||
*
|
||||
* @param val
|
||||
* @param buf
|
||||
* @param offset
|
||||
/**
|
||||
* Write an unsigned byte
|
||||
*/
|
||||
public static void writeUByte(int val, byte[] buf, int offset) {
|
||||
buf[offset] = (byte)(val & 0xFF);
|
||||
@@ -85,42 +89,16 @@ public class Types {
|
||||
/**
|
||||
* Return len of null-terminated string (i.e. distance to null)
|
||||
* within a byte buffer.
|
||||
*
|
||||
* @param buf
|
||||
* @param offset
|
||||
* @return
|
||||
*/
|
||||
public static int strlen( byte[] buf, int offset ) {
|
||||
private static int strlen( byte[] buf, int offset ) {
|
||||
int len = 0;
|
||||
while( buf[offset + len] != 0 )
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Copy a sequence of bytes into a new array.
|
||||
*
|
||||
* @param b - source array
|
||||
* @param offset - first byte
|
||||
* @param len - number of bytes
|
||||
* @return new byte[len]
|
||||
*/
|
||||
public static byte[] extract( byte[] b, int offset, int len ) {
|
||||
byte[] b2 = new byte[len];
|
||||
System.arraycopy( b, offset, b2, 0, len );
|
||||
return b2;
|
||||
}
|
||||
|
||||
|
||||
private static final byte[] CRLFbuf = { 0x0D, 0x0A };
|
||||
private static final String CRLF = new String(CRLFbuf);
|
||||
private static final String SEP = System.getProperty("line.separator");
|
||||
private static final boolean REPLACE = ! SEP.equals(CRLF);
|
||||
|
||||
public static String readCString(byte[] buf, int offset) throws UnsupportedEncodingException {
|
||||
String jstring = new String(buf, offset, strlen(buf, offset), "UTF-8");
|
||||
public static String readCString(byte[] buf, int offset) {
|
||||
String jstring = new String(buf, offset, strlen(buf, offset), defaultCharset);
|
||||
|
||||
if ( REPLACE ) {
|
||||
jstring = jstring.replace(CRLF, SEP);
|
||||
@@ -141,7 +119,7 @@ public class Types {
|
||||
str = str.replace(SEP, CRLF);
|
||||
}
|
||||
|
||||
byte[] initial = str.getBytes("UTF-8");
|
||||
byte[] initial = str.getBytes(defaultCharset);
|
||||
|
||||
int length = initial.length+1;
|
||||
os.write(LEDataOutputStream.writeIntBuf(length));
|
||||
@@ -151,6 +129,33 @@ public class Types {
|
||||
return length;
|
||||
}
|
||||
|
||||
public static String readPassword(byte[] buf, int offset) {
|
||||
return new String(buf, offset, strlen(buf, offset), defaultCharset);
|
||||
}
|
||||
|
||||
public static int writePassword(String str, OutputStream os) throws IOException {
|
||||
byte[] initial = str.getBytes(defaultCharset);
|
||||
int length = initial.length+1;
|
||||
os.write(LEDataOutputStream.writeIntBuf(length));
|
||||
os.write(initial);
|
||||
os.write(0x00);
|
||||
return length;
|
||||
}
|
||||
|
||||
public static byte[] readBytes(byte[] buf, int offset, int len) {
|
||||
byte[] binaryData = new byte[len];
|
||||
System.arraycopy(buf, offset, binaryData, 0, len);
|
||||
return binaryData;
|
||||
}
|
||||
|
||||
public static int writeBytes(byte[] data, int dataLen, OutputStream os ) throws IOException {
|
||||
os.write(LEDataOutputStream.writeIntBuf(dataLen));
|
||||
if (data != null) {
|
||||
os.write(data);
|
||||
}
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
public static UUID bytestoUUID(byte[] buf) {
|
||||
return bytestoUUID(buf, 0);
|
||||
}
|
||||
@@ -167,15 +172,12 @@ public class Types {
|
||||
}
|
||||
|
||||
return new UUID(msb, lsb);
|
||||
|
||||
}
|
||||
|
||||
public static byte[] UUIDtoBytes(UUID uuid) {
|
||||
byte[] buf = new byte[16];
|
||||
|
||||
LEDataOutputStream.writeLong(uuid.getMostSignificantBits(), buf, 0);
|
||||
LEDataOutputStream.writeLong(uuid.getLeastSignificantBits(), buf, 8);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user