package de.ruvnox.tactical.security import java.security.MessageDigest import java.util.Base64 import javax.crypto.SecretKeyFactory import javax.crypto.spec.PBEKeySpec object PasswordHash { fun verify(password: String, storedHash: String?): Boolean { if (storedHash.isNullOrBlank()) return false val parts = storedHash.split("$") if (parts.size != 4) return false if (parts[0] != "pbkdf2_sha256") return false val iterations = parts[1].toIntOrNull() ?: return false val salt = runCatching { Base64.getDecoder().decode(parts[2]) }.getOrNull() ?: return false val expected = runCatching { Base64.getDecoder().decode(parts[3]) }.getOrNull() ?: return false val spec = PBEKeySpec(password.toCharArray(), salt, iterations, expected.size * 8) val actual = SecretKeyFactory .getInstance("PBKDF2WithHmacSHA256") .generateSecret(spec) .encoded return MessageDigest.isEqual(expected, actual) } }