MD5/Implementation: Difference between revisions

m
→‎{{header|Raku}}: minor simplification
(→‎{{header|Raku}}: add broken tag)
m (→‎{{header|Raku}}: minor simplification)
 
(21 intermediate revisions by 9 users not shown)
Line 42:
 
[((UInt32, UInt32, UInt32) -> UInt32)] functions
functions [+]= (b, c, d) -> (b [&] c) [|] ((-)~b [&] d)
functions [+]= (b, c, d) -> (d [&] b) [|] ((-)~d [&] c)
functions [+]= (b, c, d) -> b (+) c (+) d
functions [+]= (b, c, d) -> c (+) (b [|] (-)~d)
 
[(Int -> Int)] index_functions
Line 1,598:
Readln;
end.</syntaxhighlight>
 
=={{header|EasyLang}}==
<syntaxhighlight lang="text">
len md5k[] 64
proc md5init . .
for i = 1 to 64
md5k[i] = floor (0x100000000 * abs sin (i * 180 / pi))
.
.
md5init
#
proc md5 inp$ . s$ .
subr addinp
if inp4 = 1
inp[] &= 0
.
inp[len inp[]] += b * inp4
inp4 *= 0x100
if inp4 = 0x100000000
inp4 = 1
.
.
s[] = [ 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 ]
inp[] = [ ]
inp4 = 1
for i = 1 to len inp$
b = strcode substr inp$ i 1
addinp
.
b = 0x80
addinp
while len inp[] mod 16 <> 14 or inp4 <> 1
b = 0
addinp
.
h = len inp$ * 8
for i = 1 to 4
b = h mod 0x100
addinp
h = h div 0x100
.
inp[] &= 0
#
a0 = 0x67452301
b0 = 0xefcdab89
c0 = 0x98badcfe
d0 = 0x10325476
for chunk = 1 step 16 to len inp[] - 15
a = a0 ; b = b0 ; c = c0 ; d = d0
for i = 1 to 64
if i <= 16
h1 = bitand b c
h2 = bitand bitnot b d
f = bitor h1 h2
g = i - 1
elif i <= 32
h1 = bitand d b
h2 = bitand bitnot d c
f = bitor h1 h2
g = (5 * i - 4) mod 16
elif i <= 48
h1 = bitxor b c
f = bitxor h1 d
g = (3 * i + 2) mod 16
else
h1 = bitor b bitnot d
f = bitxor c h1
g = (7 * i - 7) mod 16
.
f = (f + a + md5k[i] + inp[chunk + g])
a = d
d = c
c = b
h1 = bitshift f s[i]
h2 = bitshift f (s[i] - 32)
b = (b + h1 + h2)
.
a0 += a ; b0 += b ; c0 += c ; d0 += d
.
s$ = ""
for a in [ a0 b0 c0 d0 ]
for i = 1 to 4
b = a mod 256
a = a div 256
for h in [ b div 16 b mod 16 ]
h += 48
if h > 57
h += 39
.
s$ &= strchar h
.
.
.
.
repeat
s$ = input
until error = 1
md5 s$ h$
print h$
.
input_data
a
abc
message digest
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
12345678901234567890123456789012345678901234567890123456789012345678901234567890
</syntaxhighlight>
 
=={{header|F_Sharp|F#}}==
Line 3,914 ⟶ 4,022:
{{works with|ooRexx|4.2.0 (and later)}}
<syntaxhighlight lang="oorexx">
#!/usr/bin/env rexx
 
/* Expected results:
Line 3,988 ⟶ 4,096:
index = 65
end
-- Only procesprocess completely filled buffer
do while index=65
A = a0
Line 4,045 ⟶ 4,153:
 
-- A convenience class to encapsulate operations on non OORexx-like
-- things such as little-endian 32-bit words
::class int32 public
 
Line 4,098 ⟶ 4,206:
bstring = bstring~substr(bits+1)~left(bstring~length,'0')
return .int32~new(bstring~b2x~x2d)
 
-- For those who like to code the shift operation in a traditional way
::method '<<'
forward to (self) message("bitleft")
 
::method bitright -- OORexx shift (>>) implementation
Line 4,107 ⟶ 4,219:
bstring = bstring~left(bstring~length-bits)~right(bstring~length,fill)
return .int32~new(bstring~b2x~x2d)
 
-- For those who like to code the shift operation in a traditional way
::method '>>'
forward to (self) message("bitright")
 
::method bitnot -- OORexx not implementation
Line 4,169 ⟶ 4,285:
}
 
sub rotate_left($$) {
($_[0] << $_[1]) | (( $_[0] >> (32 - $_[1]) ) & ((1 << $_[1]) - 1));
}
Line 4,696 ⟶ 4,812:
=={{header|Raku}}==
(formerly Perl 6)
{{works with|rakudo|2018.032024-02}}
<syntaxhighlight lang="raku" line>proto md5($msg) returns Blob is export {*}
{{Broken|raku}}
multi md5(Str $msg) { md5 $msg.encode }
<syntaxhighlight lang="raku" line>sub infix:<⊞>(uint32 $a, uint32 $b --> uint32) { ($a + $b) +& 0xffffffff }
multi md5(Blob $msg) {
sub infix:«<<<»(uint32 $a, UInt $n --> uint32) { ($a +< $n) +& 0xffffffff +| ($a +> (32-$n)) }
my buf8 $buf .= new;
$buf.write-uint32: $buf.elems, $_, LittleEndian for
constant FGHI = { ($^a +& $^b) +| (+^$a +& $^c) },
reduce -> Blob $blob, blob32 $X {
{ ($^a +& $^c) +| ($^b +& +^$c) },
blob32.new: $blob Z+
{ $^a +^ $^b +^ $^c },
reduce {-> $^b, +^ ($^ai +| +^$^c) };{
blob32.new:
constant _S = flat (7, 12, 17, 22) xx 4 $b[3],
$b[1] (5, 9, 14, 20) xx 4,+
-> uint32 \x, \n { (4,x 11,+< 16, 23n) xx+| 4,(x +> (32-n)) }(
($b[0] + (6, 10, 15, 21) xxBEGIN 4;Array.new:
{ ($^x +& $^y) +| (+^$x +& $^z) },
constant T = (floor(abs(sin { ($_^x +& 1)$^z) *+| 2**32)($^y for+& +^64$z); },
{ $^x +^ $^y +^ $^z },
constant k = flat ( $_ { $^y +^ ($^x for+| +^16$^z), }
)[$i div 16]((5*|$_ + b[1..3]) % 16 for ^16),+
(BEGIN blob32.new: map &floor ∘ ((3*$_ +* 5)2**32 % 16&abs for∘ &sin ∘ * + 1, ^1664),[$i] +
$X[(BEGIN Blob.new: 16 X[R%] flat ((7$++, 5*$_++ + 1, 3*$++ )+ %5, 167*$++) forXxx ^16);[$i]]
) mod 2**32,
(BEGIN flat < 7 12 17 22 5 9 14 20 4 11 16 23 6 10 15 21 >.rotor(4) Xxx 4)[$i]
sub little-endian($w, $n, *@v) {
my \step1 = $w X* ^$n; ),
my \step2 = @v X+> step1; $b[1],
step2 X% 2** $w;b[2]
}, $blob, |^64;
}
},
(BEGIN blob32.new: 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476),
sub md5-pad(Blob $msg)
|map { blob32.new: @$_ },
{
{
my $bits = 8 * $msg.elems;
my @padded = flat $msg^b.listpush(blob8.new(@$_).read-uint32(0)) for (@$msg, 0x80, 0x00 xx (-($bits div 8msg.elems + 1 + 8) % 64;))
.flat.rotor(4);
flat @padded.map({ :256[$^d,$^c,$^b,$^a] }), little-endian(32, 2, $bits);
$b.write-uint64: $b.elems, 8*$msg.elems, LittleEndian;
}
$b;
}(buf32.new)
sub md5-block(@H, @X)
.rotor(16);
{
$buf;
my uint32 ($A, $B, $C, $D) = @H;
($A, $B, $C, $D) = ($D, $B ⊞ (($A ⊞ FGHI[$_ div 16]($B, $C, $D) ⊞ T[$_] ⊞ @X[k[$_]]) <<< _S[$_]), $B, $C) for ^64;
@H «⊞=» ($A, $B, $C, $D);
}
 
CHECK {
sub md5(Blob $msg --> Blob)
use Test;
{
 
my uint32 @M = md5-pad($msg);
for 'd41d8cd98f00b204e9800998ecf8427e', '',
my uint32 @H = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476;
'0cc175b9c0f1b6a831c399e269772661', 'a',
md5-block(@H, @M[$_ .. $_+15]) for 0, 16 ...^ +@M;
'900150983cd24fb0d6963f7d28e17f72', 'abc',
Blob.new: little-endian(8, 4, @H);
'f96b697d7cb7938d525a2f31aaf161d0', 'message digest',
}
'c3fcd3d76192e4007dfb496cca67e13b', 'abcdefghijklmnopqrstuvwxyz',
'd174ab98d277d9f5a5611c2c9f419d9f', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
use Test;
'57edf4a22be3c955ac49da2e2107b67a', '12345678901234567890123456789012345678901234567890123456789012345678901234567890'
plan 7;
-> $expected, $msg {
my $digest = md5($msg).list».fmt('%02x').join;
for 'd41d8cd98f00b204e9800998ecf8427e', '',
is($digest, $expected, "$digest is MD5 digest of '$msg'");
'0cc175b9c0f1b6a831c399e269772661', 'a',
}
'900150983cd24fb0d6963f7d28e17f72', 'abc',
done-testing;
'f96b697d7cb7938d525a2f31aaf161d0', 'message digest',
'c3fcd3d76192e4007dfb496cca67e13b', 'abcdefghijklmnopqrstuvwxyz',
'd174ab98d277d9f5a5611c2c9f419d9f', 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
'57edf4a22be3c955ac49da2e2107b67a', '12345678901234567890123456789012345678901234567890123456789012345678901234567890'
-> $expected, $msg {
my $digest = md5($msg.encode('ascii')).list».fmt('%02x').join;
is($digest, $expected, "$digest is MD5 digest of '$msg'");
}</syntaxhighlight>
 
Line 5,417 ⟶ 5,525:
 
=={{header|Scala}}==
<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,471 ⟶ 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,492 ⟶ 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,512 ⟶ 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,535 ⟶ 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;
 
Line 5,655 ⟶ 5,867:
 
for i in (range(0, M.end, 16)) {
md5_block(H, M.ftslice(i, i+15).first(16))
}
 
Line 6,197 ⟶ 6,409:
{{libheader|Wren-fmt}}
This is a translation of the C code [https://github.com/pod32g/MD5/blob/master/md5.c here]. In the interests of brevity, the original comments have been omitted.
<syntaxhighlight lang="ecmascriptwren">import "./fmt" for Fmt
 
var k = [
1,934

edits