This is MD5 ZScript library by 3saster, repackaged as a DoomToolbox module by m8f. Also, truncation parameter is removed, and signed integer warning fixed.
SPDX-FileCopyrightText: © 2020 3saster
SPDX-FileCopyrightText: © 2026 Alexander Kromm <mmaulwurff@gmail.com>
SPDX-License-Identifier: BSD-3-Clause
// <<license>>
// Copyright 2020 3saster
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. The name of the author may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//===========================================================================
//
// MD5 Implementation in ZScript
// by 3saster
//
// A class that returns a string containing the MD5 of an input string, using
// the Hash method.
//
// You are welcome to to use this in your mods, no need to ask for permission,
// as long as the above copyright notice is included, and credit is given.
//
//===========================================================================
Class NAMESPACE_MD5
{
// Some functions needed for MD5
protected static uint F (uint B, uint C, uint D) { return (B & C) | (~B & D); }
protected static uint G (uint B, uint C, uint D) { return (B & D) | (C & ~D); }
protected static uint H (uint B, uint C, uint D) { return B ^ C ^ D; }
protected static uint I (uint B, uint C, uint D) { return C ^ (B | ~D); }
protected static uint leftrotate (uint x, uint c) { return (x << c) | (x >> (32-c)); }
// Swap endianness of byte bitwise
protected static uint swapByte (uint x)
{
uint r = 0;
for(int i=0; i<8; i++)
r += ((x>>i) & 1) << (7-i);
return r;
}
// Swap endianness of word bytewise
protected static uint swapWord (uint x)
{
uint r = 0;
for(int i=0; i<32; i += 8)
r += ((x>>i) & 0xFF) << (24-i);
return r;
}
static string Hash(string key)
{
// s specifies the per-round shift amounts
uint s[64] = { 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 };
// Constants
uint K[64] = { 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 };
// Initialize variables:
uint a0 = 0x67452301; // A
uint b0 = 0xefcdab89; // B
uint c0 = 0x98badcfe; // C
uint d0 = 0x10325476; // D
// Turn string to byte array
Array<uint> input;
for(uint i=0; i < key.length(); i++)
{
input.push(key.ByteAt(i));
}
// Padding - add a single 1 bit, then add zeros until the number of bytes is 56 mod 64
input.push(0x80);
while( input.size()%64 != 56 )
{
input.push(0x00);
}
// Pad the remaining 8 bytes with the original message length in little endian
uint strLen = 8*key.length();
for(uint i=0; i<8; i++)
{
input.push(strLen & 0xFF);
strLen >>= 8;
}
// Swap endianness of each byte
uint inputSize = uint(input.size());
for(uint i=0; i < inputSize; i++)
{
input[i] = swapByte(input[i]);
}
// Break into 64 byte chunks
for(uint front=0; front < inputSize; front += 64)
{
//break chunk into 16 four-byte words
Array<uint> M;
for(int k=0; k<64; k += 4)
{
M.push(
( swapByte(input[front + k + 0]) << 0 ) +
( swapByte(input[front + k + 1]) << 8 ) +
( swapByte(input[front + k + 2]) << 16) +
( swapByte(input[front + k + 3]) << 24)
);
}
// Initialize hash value for this chunk:
uint A = a0;
uint B = b0;
uint C = c0;
uint D = d0;
uint f;
uint g;
// Main Loop
for(uint i=0; i<64; i++)
{
if(0 <= i && i <= 15)
{
f = F(B,C,D);
g = i;
}
else if(16 <= i && i <= 31)
{
f = G(B,C,D);
g = (5*i+1)%16;
}
else if(32 <= i && i <= 47)
{
f = H(B,C,D);
g = (3*i+5)%16;
}
else //if(48 <= i && i <= 63)
{
f = I(B,C,D);
g = (7*i)%16;
}
f = f + A + K[i] + M[g];
A = D;
D = C;
C = B;
B = B + leftrotate(f, s[i]);
}
// Add this chunk's hash to result so far:
a0 += A;
b0 += B;
c0 += C;
d0 += D;
}
return string.format("%08x%08x%08x%08x",swapWord(a0),swapWord(b0),swapWord(c0),swapWord(d0));
}
}GameInfo { EventHandlers = "md5_TestEventHandler" }version 4.14.3
#include "MD5.zs"
class md5_TestEventHandler : StaticEventHandler
{
override void networkProcess(ConsoleEvent event)
{
if (event.name != "md5-test") return;
Map<string, string> cases;
cases.insert("", "d41d8cd98f00b204e9800998ecf8427e");
cases.insert("The quick brown fox jumps over the lazy dog",
"9e107d9d372bb6826bd81d3542a419d6");
// Note the dot at the end.
cases.insert("The quick brown fox jumps over the lazy dog.",
"e4d909c290d0fb1ca068ffaddf22cbd0");
foreach (input, expected: cases)
{
string actual = NAMESPACE_MD5.hash(input);
if (actual == expected) continue;
Console.printf("ERROR: input: %s, actual: %s, expected: %s",
input,
actual,
expected);
}
}
}wait 2; map map01; wait 2; netevent md5-test; wait 2; quit