How to resolve the algorithm MD5/Implementation step by step in the Wren programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm MD5/Implementation step by step in the Wren programming language

Table of Contents

Problem Statement

The purpose of this task to code and validate an implementation of the MD5 Message Digest Algorithm by coding the algorithm directly (not using a call to a built-in or external hashing library). For details of the algorithm refer to MD5 on Wikipedia or the MD5 definition in IETF RFC (1321).

The solutions shown here will provide practical illustrations of bit manipulation, unsigned integers, working with little-endian data. Additionally, the task requires an attention to details such as boundary conditions since being out by even 1 bit will produce dramatically different results. Subtle implementation bugs can result in some hashes being correct while others are wrong. Not only is it critical to get the individual sub functions working correctly, even small errors in padding, endianness, or data layout will result in failure. In addition, intermediate outputs to aid in developing an implementation can be found here. The MD5 Message-Digest Algorithm was developed by RSA Data Security, Inc. in 1991.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm MD5/Implementation step by step in the Wren programming language

Source code in the wren programming language

import "/fmt" for Fmt

var k = [
    0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
    0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
    0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
    0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
    0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
    0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
    0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
    0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
    0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
    0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
    0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
    0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
    0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
    0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
    0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
    0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
]

var r = [
    7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
    5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
    4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
    6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
]

var leftRotate = Fn.new { |x, c| (x << c) | (x >> (32 - c)) }

var toBytes = Fn.new { |val|
    var bytes = List.filled(4, 0)
    bytes[0] = val         & 255
    bytes[1] = (val >> 8)  & 255
    bytes[2] = (val >> 16) & 255
    bytes[3] = (val >> 24) & 255
    return bytes
}

var toInt = Fn.new { |bytes| bytes[0] | bytes[1] << 8 | bytes[2] << 16 | bytes[3] << 24 }

var md5 = Fn.new { |initMsg|
    var h0 = 0x67452301
    var h1 = 0xefcdab89
    var h2 = 0x98badcfe
    var h3 = 0x10325476
    var initBytes = initMsg.bytes
    var initLen = initBytes.count
    var newLen = initLen + 1
    while (newLen % 64 != 56) newLen = newLen + 1
    var msg = List.filled(newLen + 8, 0)
    for (i in 0...initLen) msg[i] = initBytes[i]
    msg[initLen] = 0x80 // remaining bytes already 0
    var lenBits = toBytes.call(initLen * 8)
    for (i in newLen...newLen+4) msg[i] = lenBits[i-newLen]
    var extraBits = toBytes.call(initLen >> 29)
    for (i in newLen+4...newLen+8) msg[i] = extraBits[i-newLen-4]
    var offset = 0
    var w = List.filled(16, 0)
    while (offset < newLen) {
        for (i in 0...16) w[i] = toInt.call(msg[offset+i*4...offset + i*4 + 4])
        var a = h0
        var b = h1
        var c = h2
        var d = h3
        var f 
        var g
        for (i in 0...64) {
            if (i < 16) {
                f = (b & c) | ((~b) & d)
                g = i
            } else if (i < 32) {
                f = (d & b) | ((~d) & c)
                g = (5*i + 1) % 16
            } else if (i < 48) {
                f = b ^ c ^ d
                g = (3*i + 5) % 16
            } else {
                f = c ^ (b | (~d))
                g = (7*i) % 16
            }
            var temp = d
            d = c
            c = b
            b = b + leftRotate.call((a + f + k[i] + w[g]), r[i])
            a = temp
        }
        h0 = h0 + a
        h1 = h1 + b
        h2 = h2 + c
        h3 = h3 + d
        offset = offset + 64
    }
    var digest = List.filled(16, 0)
    var dBytes = toBytes.call(h0)
    for (i in 0...4) digest[i] = dBytes[i]
    dBytes = toBytes.call(h1)
    for (i in 0...4) digest[i+4] = dBytes[i]
    dBytes = toBytes.call(h2)
    for (i in 0...4) digest[i+8] = dBytes[i]
    dBytes = toBytes.call(h3)
    for (i in 0...4) digest[i+12] = dBytes[i]
    return digest
}

var strings = [
    "",
    "a",
    "abc",
    "message digest",
    "abcdefghijklmnopqrstuvwxyz",
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
    "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
]

for (s in strings) {
    var digest = md5.call(s)
    Fmt.print("0x$s <== '$0s'", Fmt.v("xz", 2, digest, 0, "", ""), s)
}

  

You may also check:How to resolve the algorithm Call a function step by step in the Elixir programming language
You may also check:How to resolve the algorithm Array concatenation step by step in the Wren programming language
You may also check:How to resolve the algorithm Bitmap step by step in the ARM Assembly programming language
You may also check:How to resolve the algorithm Loops/For with a specified step step by step in the Hy programming language
You may also check:How to resolve the algorithm Count in factors step by step in the Perl programming language