Skip to content

Instantly share code, notes, and snippets.

@etspaceman
Created February 27, 2023 20:34
Show Gist options
  • Save etspaceman/9dd6da04258064a8cc05649b2cabd1e9 to your computer and use it in GitHub Desktop.
Save etspaceman/9dd6da04258064a8cc05649b2cabd1e9 to your computer and use it in GitHub Desktop.
MD5 Hashing - Scala
object MD5 {
private val initA: Int = 0x67452301
private val initB: Int = 0xefcdab89L.toInt
private val initC: Int = 0x98badcfeL.toInt
private val initD: Int = 0x10325476
private val shiftAmts: Array[Int] =
Array(7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21)
private val tableT: Array[Int] = Array.ofDim(64)
for (i <- 0 until 64)
tableT(i) = ((1L << 32) * Math.abs(Math.sin((i + 1).toDouble))).toLong.toInt
def compute(message: Array[Byte]): Array[Byte] = {
val messageLenBytes = message.length
val numBlocks = ((messageLenBytes + 8) >>> 6) + 1
val totalLen = numBlocks << 6
val paddingBytes: Array[Byte] = Array.ofDim(totalLen - messageLenBytes)
paddingBytes(0) = 0x80.toByte
var messageLenBits = messageLenBytes.toLong << 3
for (i <- 0 until 8) {
paddingBytes(paddingBytes.length - 8 + i) = messageLenBits.toByte
messageLenBits = messageLenBits >>> 8
}
var a = initA
var b = initB
var c = initC
var d = initD
val buffer: Array[Int] = Array.ofDim(16)
for (i <- 0 until numBlocks) {
var index = i << 6
for (j <- 0 until 64) {
buffer(j >>> 2) = ((if (index < messageLenBytes) message(index)
else
paddingBytes(
index - messageLenBytes
)) << 24).toInt | (buffer(j >>> 2) >>> 8)
index = index + 1
}
val originalA = a
val originalB = b
val originalC = c
val originalD = d
for (j <- 0 until 64) {
val div16 = j >>> 4
var f = 0
var bufferIndex = j
div16 match {
case 0 =>
f = (b & c) | (~b & d)
case 1 =>
f = (b & d) | (c & ~d)
bufferIndex = (bufferIndex * 5 + 1) & 0x0f
case 2 =>
f = b ^ c ^ d
bufferIndex = (bufferIndex * 3 + 5) & 0x0f
case 3 =>
f = c ^ (b | ~d)
bufferIndex = (bufferIndex * 7) & 0x0f
case _ => ()
}
val temp = b + Integer.rotateLeft(
a + f + buffer(bufferIndex) + tableT(j),
shiftAmts((div16 << 2) | (j & 3))
)
a = d
d = c
c = b
b = temp
}
a = a + originalA
b = b + originalB
c = c + originalC
d = d + originalD
}
val md5: Array[Byte] = Array.ofDim(16)
var count = 0
for (i <- 0 until 4) {
var n = i match {
case 0 => a
case 1 => b
case 2 => c
case _ => d
}
for (_ <- 0 until 4) {
md5(count) = n.toByte
count = count + 1
n = n >>> 8
}
}
md5
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment