Search code examples
javakotlinhashuuid

How to shorten/hash UUID in Kotlin to maximum 20 lenght String?


I have a database and a Kotlin program with unique UUIDs (like '79c89a6e-543f-414a-bd81-f0ee55847390') for the entities/objects and I'm trying to hash/shorten them as Strings to send them via API with a maximum lenght of 20 characters (unfortunately it's a requirement I cannot change).

I'm quite new with Kotlin and I'm struggling to understand the hashing concepts, I read quite a lot about base64 and other concepts but I'm unable to get a result. Is there a short way to do it? Will it be possible to get back the UUID? Thanks a lot


Solution

  • In general a hash function is not reversible. So if you want to keep the original uuid, you have to compress it (a hash function can map multiple values to the same hash). A uuid is a 128-bit number displayed as a 32-character long hex string (excluding hyphens, each character represents 4 bits). You can display 2 hex characters with 1 ascii character. Note that the result can contain special characters (such as line breaks) that may cause problems with your api.

    fun main() {
        val x0 = "79c89a6e-543f-414a-bd81-f0ee55847390"
    
        val x1 = encode(x0)
        println(x1)        // yÈnT?AJ½ðîUs
        println(x1.length) // 16
    
        val x2 = decode(x1)
        println(x0 == x2)  // true
    }
    
    fun encode(uuid: String): String {
        return uuid
            // Remove hyphens
            .replace("-", "")
            // Iterate over 2 character blocks
            .chunked(2)
            // Parse hex number and convert it to a ascii character
            .map { it.toInt(16).toChar() }
            // Join character list to string
            .joinToString("")
    }
    
    fun decode(str: String): String {
        val charList = str
            // Convert ascii character to hex string with leading 0
            .map { it.toInt().toString(16).padStart(2, '0') }
            .toMutableList()
    
        // Readd hyphens
        for (i in (10 downTo  4).step(2)) {
            charList.add(i, "-")
        }
    
        // Join character list to string
        return charList.joinToString("")
    }