Skip to content

Hash Generator — Kotlin source

Compute SHA-1, SHA-256, SHA-384 and SHA-512 hashes of any text at once, using the browser's native SubtleCrypto. Copy each digest. 100% client-side.

This is the Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.

// hash — SHA-1 / SHA-256 / SHA-384 / SHA-512 digest of a UTF-8 string.
//
// Language: Kotlin 1.9 (JVM, standard library + java.security)
// Source:   CosmoDev polyglot showcase port of the `hash` tool, ported from
//           src/tools/HashGenerator.tsx (the canonical TypeScript island).
// License:  display source — part of CosmoDev's polyglot tool pages.
//
// Kotlin/JVM has no crypto in kotlin-stdlib, so the idiomatic path is the
// JDK's java.security.MessageDigest — the same vetted provider set the Java
// port of this tool uses. All four names are standard JCA algorithm strings;
// no external dependencies are needed.
//
// Behavior mirrors the TypeScript reference: UTF-8 input, lowercase hex
// output, and rejection of unknown algorithm names. MessageDigest's checked
// NoSuchAlgorithmException is translated into IllegalArgumentException —
// the Kotlin standing of the Python port's ValueError. SHA-1 is offered for
// legacy compatibility only; it is not collision-resistant.

import java.security.MessageDigest
import java.security.NoSuchAlgorithmException

/** Pure logic of the CosmoDev `hash` tool. */
object HashTool {

    /** Canonical algorithm names. The spellings match the TypeScript union so
     * the same string works across every port. */
    const val SHA1: String = "SHA-1"
    const val SHA256: String = "SHA-256" // default algorithm
    const val SHA384: String = "SHA-384"
    const val SHA512: String = "SHA-512"

    /** Every supported algorithm, in the order the React island renders them. */
    val ALGORITHMS: List<String> = listOf(SHA1, SHA256, SHA384, SHA512)

    /**
     * Computes the named digest of [text] and returns it as lowercase hex.
     *
     * The text is UTF-8 encoded before hashing, so the result is correct for
     * arbitrary Unicode (emoji, accents, CJK). A null or empty [algorithm]
     * selects SHA-256 — the default parameter the TypeScript reference
     * declares. An unknown name throws [IllegalArgumentException].
     */
    fun digest(text: String, algorithm: String = SHA256): String {
        val name = algorithm.takeIf { it.isNotEmpty() } ?: SHA256

        // The supported set is fixed by the tool. Checking it here — before
        // getInstance — rejects unknown names with IllegalArgumentException
        // and stops the JCA from accepting digests the tool does not offer
        // ("MD5" passes the provider lookup but is outside this contract).
        require(name in ALGORITHMS) { "Unsupported hash algorithm: $name" }

        val md: MessageDigest = try {
            // A fresh instance per call: MessageDigest is stateful.
            MessageDigest.getInstance(name)
        } catch (e: NoSuchAlgorithmException) {
            throw IllegalArgumentException("Unsupported hash algorithm: $name", e)
        }

        val hash = md.digest(text.toByteArray(Charsets.UTF_8))

        // Two lowercase hex digits per byte — %02x formats a Byte as its
        // unsigned two-digit hex value.
        return hash.joinToString(separator = "", prefix = "", postfix = "") { "%02x".format(it) }
    }

    /**
     * Computes every supported digest of [text] — the Kotlin shape of the
     * Record the React island renders. Each hash is computed independently.
     * The map preserves the canonical algorithm order (buildMap keeps
     * insertion order through LinkedHashMap, exactly like the Java port).
     */
    fun hashAll(text: String): Map<String, String> = buildMap {
        for (algorithm in ALGORITHMS) {
            put(algorithm, digest(text, algorithm))
        }
    }
}

Also available in 13 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 →