How to Generate an MD5 hash in Kotlin?

16,716

Solution 1

Using java.security.MessageDigest is the simplest way

import java.math.BigInteger
import java.security.MessageDigest

fun md5(input:String): String {
    val md = MessageDigest.getInstance("MD5")
    return BigInteger(1, md.digest(input.toByteArray())).toString(16).padStart(32, '0')
}

Solution 2

In general, hash (digest) functions take a byte array as input and produce a byte array as an output. Therefore, to hash a string, you first need to convert it into a byte array. A common way of doing this is to encode the string as an array of UTF-8 bytes: string.toByteArray(UTF_8)

A common way to display a byte array as a string, is to convert the individual bytes to their hexadecimal values and concatenate them. Here is an extension function that does that:

fun ByteArray.toHex() = joinToString(separator = "") { byte -> "%02x".format(byte) }

MD5 produces a byte array of length 16. When converted to hex, it is represented by a string of length 32.

The entire code looks like this:

import java.security.MessageDigest
import kotlin.text.Charsets.UTF_8

fun md5(str: String): ByteArray = MessageDigest.getInstance("MD5").digest(str.toByteArray(UTF_8))
fun ByteArray.toHex() = joinToString(separator = "") { byte -> "%02x".format(byte) }

fun main() {
    println(md5("Hello, world!").toHex()) //6cd3556deb0da54bca060b4c39479839
    println(md5("").toHex())              //d41d8cd98f00b204e9800998ecf8427e
}

Note that MD5 has well known weaknesses that make it inappropriate for many use cases. Alternatives include the SHA family of hashing functions. Here is how apply SHA-256 on a string:

fun sha256(str: String): ByteArray = MessageDigest.getInstance("SHA-256").digest(str.toByteArray(UTF_8))

Solution 3

import java.math.BigInteger
import java.security.MessageDigest

fun main(args: Array<String>) {
    println(md5Hash("Hello, world!"))
}

fun md5Hash(str: String): String {
    val md = MessageDigest.getInstance("MD5")
    val bigInt = BigInteger(1, md.digest(str.toByteArray(Charsets.UTF_8)))
    return String.format("%032x", bigInt)
}

Solution 4

I would suggest utilsing version 1.15 of Apache commons codec

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>
import org.apache.commons.codec.digest.DigestUtils

fun main(args: Array<String>) {
    println(DigestUtils.md5Hex("Hello world!"))
}
Share:
16,716
Anisuzzaman Babla
Author by

Anisuzzaman Babla

I have been working in Java for more than 7 years. During this time I have worked for several companies including fintech and food delivery where I have been repeatedly recognized for developing innovative solutions. I am responsible for code reviewing and creating reusable libraries, and tools that accelerate the development process. I have a hands-on experience with Java, Spring boot, Microservices and PostgreSQL, AWS and AWS RDS. Read my article on medium.

Updated on July 26, 2022

Comments

  • Anisuzzaman Babla
    Anisuzzaman Babla almost 2 years

    Generate MD5 hash of a string using standard library in Kotlin?

    I have tried below mention code

    import java.math.BigInteger
    import java.security.MessageDigest
    
    fun md5(input:String): String {
        val md = MessageDigest.getInstance("MD5")
        return BigInteger(1, md.digest(input.toByteArray())).toString(16).padStart(32, '0')
    }
    

    Is this the best way or which?

    • Gabor Lengyel
      Gabor Lengyel over 3 years
      Note that md5 as a cryptography hash is broken and should not be used anymore. Any static scanner will flag it as a weakness / potential vulnerability.
  • Vlad
    Vlad over 3 years
    It is too big just for md5
  • duffymo
    duffymo over 2 years
    Why add a whole dependency when the JDK has a built in class?
  • Vlad
    Vlad about 2 years
    @duffymo this implementation is more tested and is simple in usage
  • duffymo
    duffymo about 2 years
    More tested than the JDK? I doubt that. Wrong two years ago, wrong now.