Skip to content

MAC Address Generator — Kotlin source

Generate random EUI-48 MAC addresses with a chosen separator, optional OUI prefix, uppercase formatting, and a locally-administered flag. Runs entirely in your browser with crypto-grade randomness.

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

// mac-address-generator — random EUI-48 MAC address generator. Kotlin port
// (canonical TS: src/lib/mac-generator.ts; Go twin: cli/mac-address-generator).
// The default rng draws from SecureRandom (the crypto source the TS lib
// uses); the showcase keeps the rng injectable (() -> Double returning
// [0, 1)) so the demo asserts exact MAC strings.
import java.security.SecureRandom

data class MacOptions(
    val separator: String? = null,             // null -> ":"; "" concatenates
    val uppercase: Boolean = false,
    val oui: String? = null,                   // 6 hex digits (separators tolerated)
    val locallyAdministered: Boolean = false,  // force U/L bit (0x02) of the first octet
    val rng: () -> Double = MacGenerator::defaultRng,
)

object MacGenerator {
    private val random = SecureRandom()

    /** 30-bit crypto draw mapped to [0, 1). */
    fun defaultRng(): Double = random.nextInt(1 shl 30) / (1 shl 30).toDouble()

    private fun hex(n: Int) = "%02x".format(n) // two-digit lowercase hex

    // Strip non-hex chars, require exactly 6 digits, parse the 3 OUI octets.
    private fun parseOui(oui: String): List<Int> {
        val clean = oui.filter { it.isDigit() || it.lowercaseChar() in 'a'..'f' }
        require(clean.length == 6) { "OUI must be 6 hex digits, got \"$oui\"" }
        return (0 until 3).map { clean.substring(it * 2, it * 2 + 2).toInt(16) }
    }

    // Build a random EUI-48 MAC: 3 OUI octets (given or random) + 3 random,
    // U/L bit forced when asked, joined as %02x with the separator.
    fun generate(o: MacOptions = MacOptions()): String {
        val oct = ArrayList<Int>()
        if (!o.oui.isNullOrEmpty()) oct += parseOui(o.oui)
        else repeat(3) { oct += (o.rng() * 256).toInt() }
        repeat(3) { oct += (o.rng() * 256).toInt() }
        if (o.locallyAdministered) oct[0] = (oct[0] and 0xFD) or 0x02
        var mac = oct.joinToString(o.separator ?: ":") { hex(it) }
        if (o.uppercase) mac = mac.uppercase()
        return mac
    }
}

fun main() {
    println(MacGenerator.generate(MacOptions(rng = { 0.0 })))                                      // 00:00:00:00:00:00
    println(MacGenerator.generate(MacOptions(separator = "-")))                                    // 6 random pairs, dash-joined
    println(MacGenerator.generate(MacOptions(rng = { 0.7 }, uppercase = true)))                    // B3:B3:B3:B3:B3:B3
    println(MacGenerator.generate(MacOptions(rng = { 0.0 }, oui = "aa-bb-cc")))                    // aa:bb:cc:00:00:00
    println(MacGenerator.generate(MacOptions(rng = { 0.5 }, locallyAdministered = true)))          // 82:80:80:80:80:80
}

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 →