Rollback readBytes method and default buffer to fix argon2 database

This commit is contained in:
J-Jamet
2021-02-09 14:15:18 +01:00
parent 309380bdd5
commit 3f6a9c3af5
7 changed files with 39 additions and 26 deletions

View File

@@ -281,7 +281,5 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
const val BACKUP_FOLDER_TITLE = "Backup"
private const val BACKUP_FOLDER_UNDEFINED_ID = -1
const val BUFFER_SIZE_BYTES = 3 * 128
}
}

View File

@@ -216,7 +216,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
val cipherKey = loadedCipherKey
?: throw IOException("Unable to retrieve cipher key to compress binaries")
// To compress, create a new binary with file
binary.compress(cipherKey, BUFFER_SIZE_BYTES)
binary.compress(cipherKey)
} catch (e: Exception) {
Log.e(TAG, "Unable to compress $binary", e)
}
@@ -228,7 +228,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
try {
val cipherKey = loadedCipherKey
?: throw IOException("Unable to retrieve cipher key to decompress binaries")
binary.decompress(cipherKey, BUFFER_SIZE_BYTES)
binary.decompress(cipherKey)
} catch (e: Exception) {
Log.e(TAG, "Unable to decompress $binary", e)
}
@@ -713,7 +713,5 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
private const val XML_ATTRIBUTE_DATA_HASH = "Hash"
const val BASE_64_FLAG = Base64.NO_WRAP
const val BUFFER_SIZE_BYTES = 3 * 128
}
}

View File

@@ -332,7 +332,9 @@ class DatabaseInputKDB(cacheDirectory: File)
val cipherKey = mDatabase.loadedCipherKey
?: throw IOException("Unable to retrieve cipher key to load binaries")
BufferedOutputStream(binaryAttachment.getOutputDataStream(cipherKey)).use { outputStream ->
cipherInputStream.copyPartTo(outputStream, fieldSize)
cipherInputStream.readBytes(fieldSize) { buffer ->
outputStream.write(buffer)
}
}
}
}

View File

@@ -33,7 +33,6 @@ import com.kunzisoft.keepass.database.element.database.BinaryAttachment
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX.Companion.BASE_64_FLAG
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX.Companion.BUFFER_SIZE_BYTES
import com.kunzisoft.keepass.database.element.database.DatabaseVersioned
import com.kunzisoft.keepass.database.element.entry.EntryKDBX
import com.kunzisoft.keepass.database.element.group.GroupKDBX
@@ -303,7 +302,9 @@ class DatabaseInputKDBX(cacheDirectory: File)
val cipherKey = mDatabase.loadedCipherKey
?: throw IOException("Unable to retrieve cipher key to load binaries")
protectedBinary.getOutputDataStream(cipherKey).use { outputStream ->
dataInputStream.copyPartTo(outputStream, byteLength)
dataInputStream.readBytes(byteLength) { buffer ->
outputStream.write(buffer)
}
}
}
}

View File

@@ -32,7 +32,6 @@ import com.kunzisoft.keepass.database.element.DeletedObject
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX.Companion.BASE_64_FLAG
import com.kunzisoft.keepass.database.element.database.DatabaseKDBX.Companion.BUFFER_SIZE_BYTES
import com.kunzisoft.keepass.database.element.entry.AutoType
import com.kunzisoft.keepass.database.element.entry.EntryKDBX
import com.kunzisoft.keepass.database.element.group.GroupKDBX
@@ -473,7 +472,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
if (binary.isProtected) {
xml.attribute(null, DatabaseKDBXXML.AttrProtected, DatabaseKDBXXML.ValTrue)
binary.getInputDataStream().use { inputStream ->
inputStream.readBytes(BUFFER_SIZE_BYTES) { buffer ->
inputStream.readBytes { buffer ->
val encoded = ByteArray(buffer.size)
randomStream!!.processBytes(buffer, 0, encoded.size, encoded, 0)
xml.text(String(Base64.encode(encoded, BASE_64_FLAG)))
@@ -482,7 +481,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
} else {
// Write the XML
binary.getInputDataStream().use { inputStream ->
inputStream.readBytes(BUFFER_SIZE_BYTES) { buffer ->
inputStream.readBytes { buffer ->
xml.text(String(Base64.encode(buffer, BASE_64_FLAG)))
}
}
@@ -510,7 +509,7 @@ class DatabaseOutputKDBX(private val mDatabaseKDBX: DatabaseKDBX,
val binaryCipherKey = mDatabaseKDBX.loadedCipherKey
?: throw IOException("Unable to retrieve cipher key to write binaries")
binary.getInputDataStream(binaryCipherKey).use { inputStream ->
inputStream.readAllBytes(BUFFER_SIZE_BYTES) { buffer ->
inputStream.readAllBytes { buffer ->
xml.text(String(Base64.encode(buffer, BASE_64_FLAG)))
}
}

View File

@@ -20,7 +20,6 @@
package com.kunzisoft.keepass.database.file.output
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.database.DatabaseKDB
import com.kunzisoft.keepass.database.element.entry.EntryKDB
import com.kunzisoft.keepass.database.exception.DatabaseOutputException
import com.kunzisoft.keepass.stream.*
@@ -103,7 +102,7 @@ class EntryOutputKDB {
// Write data
if (binaryDataLength > 0) {
binaryData?.getInputDataStream(binaryCipherKey).use { inputStream ->
inputStream?.readAllBytes(DatabaseKDB.BUFFER_SIZE_BYTES) { buffer ->
inputStream?.readAllBytes { buffer ->
mOutputStream.write(buffer)
}
inputStream?.close()

View File

@@ -24,14 +24,14 @@ import com.kunzisoft.keepass.utils.StringDatabaseKDBUtils.bytesToString
import com.kunzisoft.keepass.utils.UnsignedInt
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.*
/**
* Read all data of stream and invoke [readBytes] each time the buffer is full or no more data to read.
*/
@Throws(IOException::class)
fun InputStream.readAllBytes(bufferSize: Int, readBytes: (bytesRead: ByteArray) -> Unit) {
fun InputStream.readAllBytes(bufferSize: Int = DEFAULT_BUFFER_SIZE,
readBytes: (bytesRead: ByteArray) -> Unit) {
val buffer = ByteArray(bufferSize)
var read = 0
while (read != -1) {
@@ -48,17 +48,33 @@ fun InputStream.readAllBytes(bufferSize: Int, readBytes: (bytesRead: ByteArray)
}
/**
* Read number of bytes defined by [length] and copy the content in [outputStream]
* Read number of bytes defined by [length] and invoke [readBytes] each time the buffer is full or no more data to read.
*/
@Throws(IOException::class)
fun InputStream.copyPartTo(outputStream: OutputStream, length: Int, bufferSize: Int = DEFAULT_BUFFER_SIZE) {
var bytesCopied: Long = 0
val buffer = ByteArray(bufferSize)
var bytesRead = read(buffer)
while (bytesRead >= 0 && bytesCopied <= length) {
outputStream.write(buffer, 0, bytesRead)
bytesCopied += bytesRead
bytesRead = read(buffer)
fun InputStream.readBytes(length: Int, bufferSize: Int = DEFAULT_BUFFER_SIZE,
readBytes: (bytesRead: ByteArray) -> Unit) {
var bufferLength = bufferSize
var buffer = ByteArray(bufferLength)
var offset = 0
var read = 0
while (offset < length && read != -1) {
// To reduce the buffer for the last bytes reads
if (length - offset < bufferLength) {
bufferLength = length - offset
buffer = ByteArray(bufferLength)
}
read = this.read(buffer, 0, bufferLength)
// To get only the bytes read
val optimizedBuffer: ByteArray = if (read >= 0 && buffer.size > read) {
buffer.copyOf(read)
} else {
buffer
}
readBytes.invoke(optimizedBuffer)
offset += read
}
}