Checksum Verifier — Kotlin source
Drag and drop a file to compute its MD5, SHA-1, SHA-256, and SHA-512 checksums. Paste an expected hash to verify integrity - detect tampered or corrupted downloads instantly. Runs entirely in your browser.
This is the Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.
// Checksum Verifier - MD5 / SHA-1 / SHA-256 / SHA-512 digests + verification.
//
// Language: Kotlin 1.9+ (JVM), standard library only.
// Ported from src/lib/checksum-verifier.ts — display source, part of
// CosmoDev's polyglot tool pages. Functionally equivalent to the TS
// reference: same inputs -> same digests, detections and verdicts.
//
// The TS reference implements MD5 from scratch (RFC 1321) because the Web
// Crypto API dropped MD5; the JVM's java.security.MessageDigest still ships
// it — and is itself an incremental update/finalize hasher — so all four
// algorithms use the platform digest here. The verification helpers
// (length-based algorithm detection, normalization, comparison) are ported
// as-is.
import java.security.MessageDigest
/** The four digests the tool computes, as lowercase hex. */
data class ChecksumResult(
val md5: String,
val sha1: String,
val sha256: String,
val sha512: String,
)
/** Supported hash algorithms, keyed by their hex-digest length. */
enum class HashAlgorithm(val digestName: String, val hexLength: Int) {
MD5("MD5", 32),
SHA1("SHA-1", 40),
SHA256("SHA-256", 64),
SHA512("SHA-512", 128);
companion object {
private val BY_LENGTH = entries.associateBy { it.hexLength }
/** Detect the algorithm from a hex string length: 32/40/64/128. */
fun fromHexLength(length: Int): HashAlgorithm? = BY_LENGTH[length]
}
}
/** An incremental hasher: absorb bytes, then emit the lowercase hex digest. */
interface MD5Hasher {
/** Absorb bytes. Call repeatedly for chunked input (no length limit). */
fun update(data: ByteArray)
/** Pad, append the 64-bit length, and return the lowercase hex digest. */
fun digestHex(): String
}
/**
* Create an incremental MD5 hasher (RFC 1321). MessageDigest already keeps
* the update/finalize split the TS reference hand-rolled; MD5 is only for
* integrity checks - not security.
*/
fun createMD5(): MD5Hasher {
val digest = MessageDigest.getInstance("MD5")
return object : MD5Hasher {
override fun update(data: ByteArray) = digest.update(data)
override fun digestHex(): String = digest.digest().toHex()
}
}
/** Synchronous one-shot MD5 of a byte array, as lowercase hex. */
fun md5(data: ByteArray): String = createMD5().let { hasher ->
hasher.update(data)
hasher.digestHex()
}
/** Lowercase hex of a byte array. */
private fun ByteArray.toHex(): String = joinToString("") { "%02x".format(it) }
/** Digest a buffer with the platform hasher and return lowercase hex. */
fun shaHex(algorithm: HashAlgorithm, data: ByteArray): String =
MessageDigest.getInstance(algorithm.digestName).digest(data).toHex()
/** Compute all four checksums of a buffer (MD5 + 3 platform digests). */
fun computeChecksums(data: ByteArray): ChecksumResult = ChecksumResult(
md5 = md5(data),
sha1 = shaHex(HashAlgorithm.SHA1, data),
sha256 = shaHex(HashAlgorithm.SHA256, data),
sha512 = shaHex(HashAlgorithm.SHA512, data),
)
/** The verdict of verifyChecksum: which algorithm matched (or did not). */
data class Verification(val algorithm: HashAlgorithm, val match: Boolean)
/** Normalize a pasted hash: drop whitespace and `:` grouping, lowercase. */
private fun normalizeHash(hash: String): String =
hash.trim().replace(Regex("[\\s:]"), "").lowercase()
/** Detect the algorithm from the hex length: 32=MD5, 40=SHA-1, 64=SHA-256, 128=SHA-512. */
fun detectHashAlgorithm(hash: String): HashAlgorithm? {
val h = normalizeHash(hash)
if (!Regex("^[0-9a-f]+$").matches(h)) return null
return HashAlgorithm.fromHexLength(h.length)
}
/**
* Compare an expected hash against a computed result. Returns null when the
* expected string is not a recognizable hex hash of a supported length.
*/
fun verifyChecksum(expected: String, result: ChecksumResult): Verification? {
val algorithm = detectHashAlgorithm(expected) ?: return null
val match = normalizeHash(expected) == when (algorithm) {
HashAlgorithm.MD5 -> result.md5
HashAlgorithm.SHA1 -> result.sha1
HashAlgorithm.SHA256 -> result.sha256
HashAlgorithm.SHA512 -> result.sha512
}
return Verification(algorithm, match)
}
Also available in 8 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →