MD5/Implementation: Difference between revisions

m
→‎{{header|Raku}}: minor simplification
m (→‎{{header|11l}}: `(-)` -> `~`)
m (→‎{{header|Raku}}: minor simplification)
 
(2 intermediate revisions by 2 users not shown)
Line 4,812:
=={{header|Raku}}==
(formerly Perl 6)
{{works with|rakudo|20222024-0702}}
<syntaxhighlight lang="raku" line>proto md5($msg) returns Blob is export {*}
multi md5(Str $msg) { md5 $msg.encode }
multi md5(Blob $msg) {
my \bits = 8 * $msg.elems;
my buf8 $buf .= new;
$buf.write-uint32: $buf.elems, $_, LittleEndian for
Line 4,844 ⟶ 4,843:
|map { blob32.new: @$_ },
{
$^b.push(blob8.new(@$_).read-uint32(0)) for (@$msg, 0x80, 0x00 xx (-(bits div 8$msg.elems + 1 + 8) % 64))
.flat.rotor(4);
$b.write-uint64: $b.elems, bits8*$msg.elems, LittleEndian;
$b;
}(buf32.new)
Line 5,526 ⟶ 5,525:
 
=={{header|Scala}}==
{{incorrect}}
<syntaxhighlight lang="scala">object MD5 extends App {
 
{{trans|Java}}
def hash(s: String) = {
def b = s.getBytes("UTF-8")
 
def m = java.security.MessageDigest.getInstance("MD5").digest(b)
 
Based on RFC-1321.
BigInt(1, m).toString(16).reverse.padTo(32, "0").reverse.mkString
 
 
<syntaxhighlight lang="Scala">
import java.lang.Math
 
object MD5 {
private val INIT_A = 0x67452301
private val INIT_B = 0xEFCDAB89
private val INIT_C = 0x98BADCFE
private val INIT_D = 0x10325476
 
private val SHIFT_AMTS = Array(
7, 12, 17, 22,
5, 9, 14, 20,
4, 11, 16, 23,
6, 10, 15, 21
)
 
private val TABLE_T = Array.tabulate(64)(i => (Math.abs(Math.sin(i + 1)) * (1L << 32)).toLong.toInt)
 
def computeMD5(message: Array[Byte]): Array[Byte] = {
val messageLenBytes = message.length
val numBlocks = ((messageLenBytes + 8) >>> 6) + 1
val totalLen = numBlocks << 6
val paddingBytes = Array.fill[Byte](totalLen - messageLenBytes)(0)
paddingBytes(0) = 0x80.toByte
 
var messageLenBits = messageLenBytes.toLong << 3
for (i <- 0 until 8) {
paddingBytes(paddingBytes.length - 8 + i) = messageLenBits.toByte
messageLenBits >>>= 8
}
 
var a = INIT_A
var b = INIT_B
var c = INIT_C
var d = INIT_D
val buffer = new Array[Int](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) | (buffer(j >>> 2) >>> 8)).toInt
index += 1
}
val originalA = a
val originalB = b
val originalC = c
val originalD = d
 
for (j <- 0 until 64) {
val div16 = j >>> 4
val bufferIndex = j match {
case j if j < 16 => j
case j if j < 32 => (j * 5 + 1) & 0x0F
case j if j < 48 => (j * 3 + 5) & 0x0F
case j => (j * 7) & 0x0F
}
 
val f = div16 match {
case 0 => (b & c) | (~b & d)
case 1 => (b & d) | (c & ~d)
case 2 => b ^ c ^ d
case 3 => c ^ (b | ~d)
}
 
val temp = b + Integer.rotateLeft(a + f + buffer(bufferIndex) + TABLE_T(j), SHIFT_AMTS((div16 << 2) | (j & 3)))
a = d
d = c
c = b
b = temp
}
 
a += originalA
b += originalB
c += originalC
d += originalD
}
 
val md5 = new Array[Byte](16)
var count = 0
for (i <- 0 until 4) {
var n = i match {
case 0 => a
case 1 => b
case 2 => c
case 3 => d
}
for (j <- 0 until 4) {
md5(count) = n.toByte
n >>>= 8
count += 1
}
}
md5
}
 
def toHexString(b: Array[Byte]): String = b.map(byte => f"$byte%02X").mkString
assert("d41d8cd98f00b204e9800998ecf8427e" == hash(""))
assert("0000045c5e2b3911eb937d9d8c574f09" == hash("iwrupvqb346386"))
assert("0cc175b9c0f1b6a831c399e269772661" == hash("a"))
assert("900150983cd24fb0d6963f7d28e17f72" == hash("abc"))
assert("f96b697d7cb7938d525a2f31aaf161d0" == hash("message digest"))
assert("c3fcd3d76192e4007dfb496cca67e13b" == hash("abcdefghijklmnopqrstuvwxyz"))
assert("d174ab98d277d9f5a5611c2c9f419d9f" == hash("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"))
assert("57edf4a22be3c955ac49da2e2107b67a" == hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890"))
 
def main(args: Array[String]): Unit = {
}</syntaxhighlight>
val testStrings = Array("", "a", "abc", "message digest", "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "12345678901234567890123456789012345678901234567890123456789012345678901234567890")
testStrings.foreach { s =>
println(s"0x${toHexString(computeMD5(s.getBytes))} <== \"$s\"")
}
}
}
</syntaxhighlight>
{{out}}
<pre>
0xD41D8CD98F00B204E9800998ECF8427E <== ""
0x0CC175B9C0F1B6A831C399E269772661 <== "a"
0x900150983CD24FB0D6963F7D28E17F72 <== "abc"
0xF96B697D7CB7938D525A2F31AAF161D0 <== "message digest"
0xC3FCD3D76192E4007DFB496CCA67E13B <== "abcdefghijklmnopqrstuvwxyz"
0xD174AB98D277D9F5A5611C2C9F419D9F <== "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
0x57EDF4A22BE3C955AC49DA2E2107B67A <== "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
 
</pre>
 
=={{header|Seed7}}==
Line 5,581 ⟶ 5,682:
const array integer: k is createMd5Table;
var integer: length is 0;
var integer: chunkIndexwordIndex is 01;
var integer: index is 0;
var array bin32: m is 16 times bin32.value;
Line 5,602 ⟶ 5,703:
message &:= "\0;" mult 63 - (length + 8) mod 64;
# Append length of message (before pre-processing), in bits, as 64-bit little-endian integer.
message &:= int64AsEightBytesLebytes(8 * length, UNSIGNED, LE, 8);
 
# Process the message in successive 512-bit chunks:
forwhile chunkIndexwordIndex range 1 to<= length(message) step 64 do
# Break chunk into sixteen 32-bit little-endian words.
for index range 1 to 16 do
m[index] := bin32(bytes2Int(message[chunkIndexwordIndex + 4 * pred(index) lenfixLen 4], UNSIGNED, LE));
wordIndex +:= 4;
end for;
 
Line 5,622 ⟶ 5,724:
elsif index <= 32 then
f := c >< (d & (b >< c));
g := succ((5 * index - 4) mod 16 + 1);
elsif index <= 48 then
f := b >< c >< d;
g := succ((3 * index + 2) mod 16 + 1);
else
f := c >< (b | (bin32(16#ffffffff) >< d));
g := succ((7 * pred(index)) mod 16 + 1);
end if;
 
Line 5,645 ⟶ 5,747:
c0 +:= ord(c);
d0 +:= ord(d);
end forwhile;
 
# Produce the final hash value:
digest := int32AsFourBytesLebytes(a0 mod 16#100000000, UNSIGNED, LE, 4) &
int32AsFourBytesLebytes(b0 mod 16#100000000, UNSIGNED, LE, 4) &
int32AsFourBytesLebytes(c0 mod 16#100000000, UNSIGNED, LE, 4) &
int32AsFourBytesLebytes(d0 mod 16#100000000, UNSIGNED, LE, 4);
end func;
 
1,934

edits