MD5/Implementation: Difference between revisions

Content added Content deleted
m (→‎{{header|Sidef}}: updated code)
(Updated F# implementation)
Line 1,312: Line 1,312:


=={{header|F#}}==
=={{header|F#}}==
Functional, hand-written implementation (slower than library function):
Pure functional implementation (slower than library function):
<lang F#>let fxyz x y z : uint32 = (x &&& y) ||| (~~~x &&& z)
<lang F#>let fxyz x y z : uint32 = (x &&& y) ||| (~~~x &&& z)
let gxyz x y z : uint32 = (z &&& x) ||| (~~~z &&& y)
let gxyz x y z : uint32 = (z &&& x) ||| (~~~z &&& y)
let hxyz x y z : uint32 = x ^^^ y ^^^ z
let hxyz x y z : uint32 = x ^^^ y ^^^ z
let ixyz x y z : uint32 = y ^^^ (x ||| ~~~z)
let ixyz x y z : uint32 = y ^^^ (x ||| ~~~z)
let fghi = [ fxyz; gxyz; hxyz; ixyz ] |> List.collect (List.replicate 16)

let g1Idx = id
let g1Idx = id
let g2Idx i = (5*i + 1) % 16
let g2Idx i = (5 * i + 1) % 16
let g3Idx i = (3*i + 5) % 16
let g3Idx i = (3 * i + 5) % 16
let g4Idx i = (7*i) % 16
let g4Idx i = (7 * i) % 16

let fghi =
[fxyz; gxyz; hxyz; ixyz]
|> List.collect (List.replicate 16)


let gIdxs =
let gIdxs =
[g1Idx; g2Idx; g3Idx; g4Idx]
[ g1Idx; g2Idx; g3Idx; g4Idx ]
|> List.collect (List.replicate 16)
|> List.collect (List.replicate 16)
|> List.map2 (fun idx func -> func idx) [0..63]
|> List.map2 (fun idx func -> func idx) [ 0..63 ]


let s =
let s =
[[7; 12; 17; 22]; [5; 9; 14; 20]; [4; 11; 16; 23]; [6; 10; 15; 21]]
[ [ 7; 12; 17; 22 ]
[ 5; 9; 14; 20 ]
[ 4; 11; 16; 23 ]
[ 6; 10; 15; 21 ] ]
|> List.collect (List.replicate 4)
|> List.collect (List.replicate 4)
|> List.concat
|> List.concat


let k =
let k =
[1. .. 64.] |> List.map (sin >> abs >> (( * ) (2.**32.)) >> floor >> uint32)
[ 1...64. ] |> List.map (sin
>> abs
>> ((*) (2. ** 32.))
>> floor
>> uint32)


type MD5 =
type MD5 =
{
{ a : uint32
a : uint32
b : uint32
b : uint32
c : uint32
c : uint32
d : uint32
d : uint32 }
}


let initialMD5 =
let initialMD5 =
{ a = 0x67452301u
{
a = 0x67452301u
b = 0xefcdab89u
b = 0xefcdab89u
c = 0x98badcfeu
c = 0x98badcfeu
d = 0x10325476u
d = 0x10325476u }
}


let md5round (msg:uint32[]) {MD5.a=a; MD5.b=b; MD5.c=c; MD5.d=d} i =
let md5round (msg : uint32 []) { MD5.a = a; MD5.b = b; MD5.c = c; MD5.d = d } i =
let rotateL32 r x = (x<<<r) ||| (x>>>(32-r))
let rotateL32 r x = (x <<< r) ||| (x >>> (32 - r))
let f = fghi.[i] b c d
let f = fghi.[i] b c d
let a' = b + (a + f + k.[i] + msg.[gIdxs.[i]] |> rotateL32 s.[i])
let a' = b + (a + f + k.[i] + msg.[gIdxs.[i]]
|> rotateL32 s.[i])
{a=d; b=a'; c=b; d=c}
{ a = d
b = a'
c = b
d = c }


let md5plus m (bs:byte[]) =
let md5plus m (bs : byte []) =
let datA =
let msg =
bs
bs
|> Array.chunkBySize 4
|> Array.chunkBySize 4
|> Array.take 16
|> Array.take 16
|> Array.map (fun elt -> System.BitConverter.ToUInt32(elt, 0))
|> Array.map (fun elt -> System.BitConverter.ToUInt32(elt, 0))
let m' = List.fold (md5round datA) m [0..63]
let m' = List.fold (md5round msg) m [ 0..63 ]
{a=m.a+m'.a; b=m.b+m'.b; c=m.c+m'.c; d=m.d+m'.d}
{ a = m.a + m'.a
b = m.b + m'.b
c = m.c + m'.c
d = m.d + m'.d }


let padMessage(msg : byte []) =
let padMessage (msg : byte []) =
let msgLen = Array.length msg
let msgLen = Array.length msg
let msgLenInBits = (uint64 msgLen) * 8UL
let msgLenInBits = (uint64 msgLen) * 8UL
let lastSegmentSize =
let lastSegmentSize =
let m = msgLen % 64
let m = msgLen % 64
if m = 0 then 64
if m = 0 then 64
else m
else m
let pad =
let padLen =
Array.create (if lastSegmentSize >= 56 then (64 - lastSegmentSize + 64)
64 - lastSegmentSize + (if lastSegmentSize >= 56 then 64
else 64 - lastSegmentSize) 0uy
else 0)
Array.set pad 0 0x80uy
for i = 0 to 7 do
[| yield 128uy
Array.set pad (Array.length pad - 8 + i)
((msgLenInBits >>> (8 * i)) |> byte)
for i in 2..padLen - 8 do
yield 0uy
Array.append msg pad
for i in 0..7 do
yield ((msgLenInBits >>> (8 * i)) |> byte) |]
|> Array.append msg


let md5sum (msg: string) =
let md5sum (msg : string) =
System.Text.Encoding.ASCII.GetBytes msg
System.Text.Encoding.ASCII.GetBytes msg
|> padMessage
|> padMessage
|> Array.chunkBySize 64
|> Array.chunkBySize 64
|> Array.fold md5plus initialMD5
|> Array.fold md5plus initialMD5
|> (fun {MD5.a=a; MD5.b=b; MD5.c=c; MD5.d=d} ->
|> (fun { MD5.a = a; MD5.b = b; MD5.c = c; MD5.d = d } ->
System.BitConverter.GetBytes a
System.BitConverter.GetBytes a
|> (fun x -> System.BitConverter.GetBytes b |> Array.append x)
|> (fun x -> System.BitConverter.GetBytes b |> Array.append x)
Line 1,398: Line 1,409:
|> (fun x -> System.BitConverter.GetBytes d |> Array.append x))
|> (fun x -> System.BitConverter.GetBytes d |> Array.append x))
|> Array.map (sprintf "%02X")
|> Array.map (sprintf "%02X")
|> Array.reduce ( + )</lang>
|> Array.reduce (+)</lang>


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==