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#}}== |
||
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 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] |
|||
⚫ | |||
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 |
[ [ 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. |
[ 1...64. ] |> List.map (sin |
||
>> abs |
|||
⚫ | |||
>> floor |
|||
>> uint32) |
|||
type MD5 = |
type MD5 = |
||
{ |
{ a : uint32 |
||
⚫ | |||
b : uint32 |
b : uint32 |
||
c : uint32 |
c : uint32 |
||
d : uint32 |
d : uint32 } |
||
⚫ | |||
let initialMD5 = |
let initialMD5 = |
||
⚫ | |||
⚫ | |||
⚫ | |||
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]] |
let a' = b + (a + f + k.[i] + msg.[gIdxs.[i]] |
||
|> rotateL32 s.[i]) |
|||
{a=d; b=a'; c=b; d=c} |
|||
⚫ | |||
b = a' |
|||
c = b |
|||
d = c } |
|||
let md5plus m (bs:byte[]) = |
let md5plus m (bs : byte []) = |
||
let |
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 |
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 |
let padLen = |
||
64 - lastSegmentSize + (if lastSegmentSize >= 56 then 64 |
|||
⚫ | |||
else 0) |
|||
Array.set pad 0 0x80uy |
|||
⚫ | |||
[| yield 128uy |
|||
Array.set pad (Array.length pad - 8 + i) |
|||
for i in 2..padLen - 8 do |
|||
yield 0uy |
|||
⚫ | |||
⚫ | |||
yield ((msgLenInBits >>> (8 * i)) |> byte) |] |
|||
⚫ | |||
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 ( |
|> Array.reduce (+)</lang> |
||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |