How to Generate an MD5 hash in Kotlin?

Viewed 21201

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?

4 Answers

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')
}

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))
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)
}

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!"))
}
Related