mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Better hash implementation
This commit is contained in:
@@ -33,7 +33,6 @@ import com.kunzisoft.keepass.database.element.node.NodeIdUUID
|
||||
import com.kunzisoft.keepass.database.element.node.NodeVersioned
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.security.MessageDigest
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@@ -141,16 +140,11 @@ class DatabaseKDB : DatabaseVersioned<Int, UUID, GroupKDB, EntryKDB>() {
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun makeFinalKey(masterSeed: ByteArray, masterSeed2: ByteArray, numRounds: Long) {
|
||||
|
||||
// Write checksum Checksum
|
||||
val messageDigest: MessageDigest = HashManager.getHash256()
|
||||
messageDigest.update(masterSeed)
|
||||
fun makeFinalKey(masterSeed: ByteArray, transformSeed: ByteArray, numRounds: Long) {
|
||||
// Encrypt the master key a few times to make brute-force key-search harder
|
||||
val transformedKey = AESKeyTransformerFactory.transformMasterKey(masterSeed2, masterKey, numRounds) ?: ByteArray(0)
|
||||
messageDigest.update(transformedKey)
|
||||
|
||||
finalKey = messageDigest.digest()
|
||||
val transformedKey = AESKeyTransformerFactory.transformMasterKey(transformSeed, masterKey, numRounds) ?: ByteArray(0)
|
||||
// Write checksum Checksum
|
||||
finalKey = HashManager.hashSha256(masterSeed, transformedKey)
|
||||
}
|
||||
|
||||
override fun createGroup(): GroupKDB {
|
||||
|
||||
@@ -347,8 +347,7 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
masterKey = getFileKey(keyInputStream)
|
||||
}
|
||||
|
||||
val messageDigest: MessageDigest = HashManager.getHash256()
|
||||
return messageDigest.digest(masterKey)
|
||||
return HashManager.hashSha256(masterKey)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -383,11 +382,9 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
private fun resizeKey(inBytes: ByteArray, cbOut: Int): ByteArray {
|
||||
if (cbOut == 0) return ByteArray(0)
|
||||
|
||||
val hash: ByteArray = if (cbOut <= 32) {
|
||||
HashManager.hashSha256(inBytes, 0, 64)
|
||||
} else {
|
||||
HashManager.hashSha512(inBytes, 0, 64)
|
||||
}
|
||||
val messageDigest = if (cbOut <= 32) HashManager.getHash256() else HashManager.getHash512()
|
||||
messageDigest.update(inBytes, 0, 64)
|
||||
val hash: ByteArray = messageDigest.digest()
|
||||
|
||||
if (cbOut == hash.size) {
|
||||
return hash
|
||||
@@ -522,12 +519,9 @@ class DatabaseKDBX : DatabaseVersioned<UUID, UUID, GroupKDBX, EntryKDBX> {
|
||||
private fun checkKeyFileHash(data: String, hash: String): Boolean {
|
||||
var success = false
|
||||
try {
|
||||
val digest: MessageDigest = HashManager.getHash256()
|
||||
digest.reset()
|
||||
// hexadecimal encoding of the first 4 bytes of the SHA-256 hash of the key.
|
||||
val dataDigest = digest.digest(Hex.decodeHex(data.toCharArray()))
|
||||
.copyOfRange(0, 4)
|
||||
.toHexString()
|
||||
val dataDigest = HashManager.hashSha256(Hex.decodeHex(data.toCharArray()))
|
||||
.copyOfRange(0, 4).toHexString()
|
||||
success = dataDigest == hash
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
||||
@@ -100,10 +100,7 @@ abstract class DatabaseVersioned<
|
||||
protected fun getCompositeKey(key: String, keyfileInputStream: InputStream): ByteArray {
|
||||
val fileKey = getFileKey(keyfileInputStream)
|
||||
val passwordKey = getPasswordKey(key)
|
||||
|
||||
val messageDigest: MessageDigest = HashManager.getHash256()
|
||||
messageDigest.update(passwordKey)
|
||||
return messageDigest.digest(fileKey)
|
||||
return HashManager.hashSha256(passwordKey, fileKey)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -113,10 +110,7 @@ abstract class DatabaseVersioned<
|
||||
} catch (e: UnsupportedEncodingException) {
|
||||
key.toByteArray()
|
||||
}
|
||||
|
||||
val messageDigest: MessageDigest = HashManager.getHash256()
|
||||
messageDigest.update(bKey)
|
||||
return messageDigest.digest()
|
||||
return HashManager.hashSha256(bKey)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
@@ -138,10 +132,8 @@ abstract class DatabaseVersioned<
|
||||
// Key is not base 64, treat it as binary data
|
||||
}
|
||||
}
|
||||
|
||||
// Hash file as binary data
|
||||
val messageDigest = HashManager.getHash256()
|
||||
return messageDigest.digest(keyData)
|
||||
return HashManager.hashSha256(keyData)
|
||||
}
|
||||
|
||||
protected open fun loadXmlKeyFile(keyInputStream: InputStream): ByteArray? {
|
||||
|
||||
@@ -53,7 +53,6 @@ class HashedBlockInputStream(private val baseStream: InputStream) : InputStream(
|
||||
if (!readHashedBlock()) {
|
||||
return length - remaining
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Copy from buffer out
|
||||
@@ -109,13 +108,12 @@ class HashedBlockInputStream(private val baseStream: InputStream) : InputStream(
|
||||
throw IOException("Invalid data format")
|
||||
}
|
||||
|
||||
val messageDigest: MessageDigest = HashManager.getHash256()
|
||||
val computedHash = messageDigest.digest(buffer)
|
||||
val computedHash = HashManager.hashSha256(buffer)
|
||||
if (computedHash.size != HASH_SIZE) {
|
||||
throw IOException("Hash wrong size")
|
||||
}
|
||||
|
||||
if (!Arrays.equals(storedHash, computedHash)) {
|
||||
if (!storedHash.contentEquals(computedHash)) {
|
||||
throw IOException("Hashes didn't match.")
|
||||
}
|
||||
|
||||
|
||||
@@ -39,22 +39,29 @@ object HashManager {
|
||||
return messageDigest
|
||||
}
|
||||
|
||||
fun hashSha256(data: ByteArray, offset: Int = 0, count: Int = data.size): ByteArray {
|
||||
return hashGen("SHA-256", data, offset, count)
|
||||
}
|
||||
|
||||
fun hashSha512(data: ByteArray, offset: Int = 0, count: Int = data.size): ByteArray {
|
||||
return hashGen("SHA-512", data, offset, count)
|
||||
}
|
||||
|
||||
private fun hashGen(transform: String, data: ByteArray, offset: Int, count: Int): ByteArray {
|
||||
val hash: MessageDigest
|
||||
try {
|
||||
hash = MessageDigest.getInstance(transform)
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
throw RuntimeException(e)
|
||||
fun hashSha256(vararg data: ByteArray): ByteArray {
|
||||
val hash: MessageDigest = getHash256()
|
||||
for (byteArray in data) {
|
||||
hash.update(byteArray)
|
||||
}
|
||||
return hash.digest()
|
||||
}
|
||||
|
||||
fun getHash512(): MessageDigest {
|
||||
val messageDigest: MessageDigest
|
||||
try {
|
||||
messageDigest = MessageDigest.getInstance("SHA-256")
|
||||
} catch (e: NoSuchAlgorithmException) {
|
||||
throw IOException("SHA-256 not implemented here.", e)
|
||||
}
|
||||
return messageDigest
|
||||
}
|
||||
|
||||
private fun hashSha512(vararg data: ByteArray): ByteArray {
|
||||
val hash: MessageDigest = getHash512()
|
||||
for (byteArray in data) {
|
||||
hash.update(byteArray)
|
||||
}
|
||||
hash.update(data, offset, count)
|
||||
return hash.digest()
|
||||
}
|
||||
|
||||
|
||||
@@ -62,8 +62,6 @@ class AndroidAESKeyTransformer : KeyTransformer() {
|
||||
}
|
||||
|
||||
// Hash the key
|
||||
val messageDigest: MessageDigest = HashManager.getHash256()
|
||||
messageDigest.update(newKey)
|
||||
return messageDigest.digest()
|
||||
return HashManager.hashSha256(newKey)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user