MD5/Implementation: Difference between revisions
m
→{{header|Raku}}: minor simplification
m (→{{header|Raku}}: minor simplification) |
|||
(10 intermediate revisions by 8 users not shown) | |||
Line 42:
[((UInt32, UInt32, UInt32) -> UInt32)] functions
functions [+]= (b, c, d) -> (b [&] c) [|] (
functions [+]= (b, c, d) -> (d [&] b) [|] (
functions [+]= (b, c, d) -> b (+) c (+) d
functions [+]= (b, c, d) -> c (+) (b [|]
[(Int -> Int)] index_functions
Line 1,607:
.
.
#
proc md5 inp$ . s$ .
Line 1,625:
for i = 1 to len inp$
b = strcode substr inp$ i 1
.
b = 0x80
while len inp[] mod 16 <> 14 or inp4 <> 1
b = 0
.
h = len inp$ * 8
for i = 1 to 4
b = h mod 0x100
h = h div 0x100
.
Line 1,695:
s$ = input
until error = 1
print h$
.
input_data
a
abc
Line 4,023 ⟶ 4,022:
{{works with|ooRexx|4.2.0 (and later)}}
<syntaxhighlight lang="oorexx">
#!/usr/bin/env rexx
/* Expected results:
Line 4,097 ⟶ 4,096:
index = 65
end
-- Only
do while index=65
A = a0
Line 4,154 ⟶ 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,207 ⟶ 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,216 ⟶ 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,805 ⟶ 4,812:
=={{header|Raku}}==
(formerly Perl 6)
{{works with|rakudo|
<syntaxhighlight lang="raku" line>proto md5($msg) returns Blob is export {*}
multi md5(Str $msg) { md5 $msg.encode }
multi md5(Blob $msg) {
my buf8 $buf .= new;
$buf.write-uint32: $buf.elems, $_, LittleEndian for
reduce -> Blob $blob, blob32 $X {
blob32.new: $blob Z+
reduce -> $b, $i {
blob32.new:
$b[3],
$b[1] +
($b[0] + (BEGIN Array.new:
{ ($^x +& $^y) +| (+^$x +& $^z) },
{ ($^x +& $^z) +| ($^y +& +^$z) },
Line 4,826 ⟶ 4,832:
)[$i div 16](|$b[1..3]) +
(BEGIN blob32.new: map &floor ∘ * * 2**32 ∘ &abs ∘ &sin ∘ * + 1, ^64)[$i] +
$X[(BEGIN Blob.new: 16 X[R%] flat ($++, 5*$++ + 1, 3*$++ + 5, 7*$++) Xxx 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]
),
Line 4,835 ⟶ 4,842:
(BEGIN blob32.new: 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476),
|map { blob32.new: @$_ },
{
$^b.push(blob8.new(@$_).read-uint32(0)) for (@$msg, 0x80, 0x00 xx (-($msg.elems + 1 + 8) % 64))
.flat.rotor(4);
$b.write-uint64: $b.elems, 8*$msg.elems, LittleEndian;
$b;
}(buf32.new)
.rotor(16);
$buf;
}
CHECK {
use Test;
Line 5,514 ⟶ 5,525:
=={{header|Scala}}==
{{trans|Java}}
Based on RFC-1321.
<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
def main(args: Array[String]): Unit = {
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,569 ⟶ 5,682:
const array integer: k is createMd5Table;
var integer: length is 0;
var integer:
var integer: index is 0;
var array bin32: m is 16 times bin32.value;
Line 5,590 ⟶ 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 &:=
# Process the message in successive 512-bit chunks:
# Break chunk into sixteen 32-bit little-endian words.
for index range 1 to 16 do
m[index] := bin32(bytes2Int(message[
wordIndex +:= 4;
end for;
Line 5,610 ⟶ 5,724:
elsif index <= 32 then
f := c >< (d & (b >< c));
g := succ((5 * index - 4) mod 16
elsif index <= 48 then
f := b >< c >< d;
g := succ((3 * index + 2) mod 16
else
f := c >< (b | (bin32(16#ffffffff) >< d));
g := succ((7 * pred(index)) mod 16
end if;
Line 5,633 ⟶ 5,747:
c0 +:= ord(c);
d0 +:= ord(d);
end
# Produce the final hash value:
digest :=
end func;
Line 5,753 ⟶ 5,867:
for i in (range(0, M.end, 16)) {
md5_block(H, M.
}
Line 6,295 ⟶ 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="
var k = [
|