= Message Digest (MD5) = [[http://en.wikipedia.org/wiki/Md5|Message Digest]] (MD5) is an algorithm that maps an ASCII character vector of indeterminate length onto a 16-digit hex hash that is hypersensitive to small changes in the message. MD5 is widely used for checking passwords without storing information from which the password could be derived. An original function [[attachment:md5.DWS|∆md5]] by Conrad Hoesle-Kienzlen and BrianOliver has been here rewritten as [[attachment:MD5.dyalog|class MD5]], with two methods. Both functions are written for [[http://www.dyalog.com|Dyalog APL]]. An alternative approach is to use the .NET System.Security.Cryptography framework, as illustrated by [[MessageDigestHashNet|this APLX example]] (Note that APLX was discontinued in 2016) == Methods == {{{ hash ← MD5.Hash msg ⍝ message digest ok ← MD5.SelfTest ⍝ Boolean: results match the test answers }}} == Notes == 1. Although their listings appear very different, {{{MD5}}} was derived from {{{∆md5}}} by a series of substitutions, each followed by {{{SelfTest}}}. Substitutions removed repeating patterns in the code and symbol reassignments, with the notable exception of {{{ABCD}}}. 2. The encoding functions {{{F G H I}}} correspond closely to the [[http://en.wikipedia.org/wiki/Md5#Algorithm|CMN versions on Wikipedia]]. 3. The {{{apply}}} operator was the result of refactoring the {{{∆F ∆G ∆H ∆I}}} functions in the original 4. The {{{round}}} operator was the result of refactoring the four 'rounds' of {{{∆md5}}} 5. {{{⎕NXLATE}}} is now deprecated and should be replaced by use of {{{⎕UCS}}} in Dyalog 12 == External links == 1. [[http://en.wikipedia.org/wiki/Md5|Wikipedia article on MD5 Message Digest]] 2. [[http://code.wikia.com/wiki/MD5_checksum|Wikia MD5 code examples]] == Listing == {{{ :Class MD5 ⍝ create a message digest with the MD5-algorithm (RFC1321) ⍝ static class: no instances ⍝ see also http://en.wikipedia.org/wiki/Md5 ⍝ Written 07.07.1999 Conrad Hoesle-Kienzlen ⍝ Revised 17.03.2002 Brian W. Oliver ⍝ Revised 09.04.2008 Stephen Taylor ⍝----------------------------------- public methods ∇ r←Hash msg;chunk;bits;rawbits;ABCD;chunks;start ⍝ msg: message of arbitrary length ⍝ r: digest, always 16 hex digits (32 characters) :Access Public Shared ⎕SIGNAL 11/⍨0∊msg∊ASCII ⍝ reject non-ASCII characters rawbits←,⍉(8/2)⊤¯1+ASCII⍳msg ⍝ convert message to binary bits←512{⍵↑⍨⍺×⊃0 ⍺⊤⊃⍴⍵}rawbits,512↑1 ⍝ pad to multiple of 512 bits (¯64↑bits)←,⊖8 8⍴,(64⍴2)⊤⍴rawbits ⍝ write length at end ABCD←INITIALSTATES ⍝ convert to decimal word length, chunks←16 cols 2⊥⍉(32 cols bits)[;,24 16 8 0∘.+⍳8] ⍝ reverse byte-order, encode to decimal :For chunk :In ↓chunks start←ABCD ⍝ initial state for this chunk ABCD←ABCD(chunk round F)Fshifts ⍝ round F ABCD←ABCD(chunk round G)Gshifts ⍝ round G ABCD←ABCD(chunk round H)Hshifts ⍝ round H ABCD←ABCD(chunk round I)Ishifts ⍝ round I ABCD{MAX|⍺+⍵}←start ⍝ add to initial cycle state :EndFor r←⊃,/hex¨ABCD ∇ ∇ ok←SelfTest :Access Public Shared :If ok←'0cc175b9c0f1b6a831c399e269772661'≡Hash'a' :AndIf ok←'d41d8cd98f00b204e9800998ecf8427e'≡Hash'' :AndIf ok←'7215ee9c7d9dc229d2921a40e899ec5f'≡Hash' ' :AndIf ok'f96b697d7cb7938d525a2f31aaf161d0'≡Hash'message digest' ok←'9e107d9d372bb6826bd81d3542a419d6'≡Hash'The quick brown fox jumps over the lazy dog' :EndIf ∇ ⍝----------------------------------- vocabulary ⎕IO ⎕ML←1 0 MAX←4294967296 ⍝ maximum integer ASCII←⎕AV[⍋1+⎕NXLATE 0] ⍝ ASCII character string cols←{⍵⍴⍨((⍴⍵)÷⍺),⍺} ⍝ reshape in ⍺ cols bin←(32/2)∘⊤ ⍝ convert to 32-bit binary hex←{'0123456789abcdef'[1+,⌽4 2⍴⌽(8/16)⊤⍵]} ⍝ convert to hex CONVERSIONTABLE←⌊MAX×|1○⍳64 INITIALSTATES←1732584193 4023233417 2562383102 271733878 ⍝ initial variable states ⍝ '67452301'h 'efcdab89'h '98badcfe'h '10325476'h (low byte order) F←{X Y Z←⍵ ⋄ (X∧Y)∨(~X)∧Z} ⍝ encoding function G←{X Y Z←⍵ ⋄ (X∧Z)∨Y∧~Z} ⍝ encoding function H←{X Y Z←⍵ ⋄ X≠Y≠Z} ⍝ encoding function I←{X Y Z←⍵ ⋄ Y≠X∨~Z} ⍝ encoding function ⍝ cf http://en.wikipedia.org/wiki/Md5#Algorithm apply←{ ⍝ apply encoding function ⍺⍺ A B C D k s i←⍵ ⍝ with arguments ⍵ B+2⊥s⌽bin ⍺[k]+CONVERSIONTABLE[i]+A+2⊥⍺⍺ bin¨B C D ⍝ to message chunk ⍺ } ∇ ABCD←ABCD(chunk round fn)shifts;tgt;rot;shft ⍝ perform a round on chunk :For tgt rot shft :InEach (16⍴1 4 3 2)(1-⍳16)(shifts) ⍝ using fn and shifts, ABCD[tgt]←chunk(fn apply)(rot⌽ABCD),shft ⍝ modifying ABCD :EndFor ∇ Fshifts←(1 7 1)(2 12 2)(3 17 3)(4 22 4) ⍝ shifts for round F Fshifts,←(5 7 5)(6 12 6)(7 17 7)(8 22 8) Fshifts,←(9 7 9)(10 12 10)(11 17 11)(12 22 12) Fshifts,←(13 7 13)(14 12 14)(15 17 15)(16 22 16) Gshifts←(2 5 17)(7 9 18)(12 14 19)(1 20 20) ⍝ shifts for round G Gshifts,←(6 5 21)(11 9 22)(16 14 23)(5 20 24) Gshifts,←(10 5 25)(15 9 26)(4 14 27)(9 20 28) Gshifts,←(14 5 29)(3 9 30)(8 14 31)(13 20 32) Hshifts←(6 4 33)(9 11 34)(12 16 35)(15 23 36) ⍝ shifts for round H Hshifts,←(2 4 37)(5 11 38)(8 16 39)(11 23 40) Hshifts,←(14 4 41)(1 11 42)(4 16 43)(7 23 44) Hshifts,←(10 4 45)(13 11 46)(16 16 47)(3 23 48) Ishifts←(1 6 49)(8 10 50)(15 15 51)(6 21 52) ⍝ shifts for round I Ishifts,←(13 6 53)(4 10 54)(11 15 55)(2 21 56) Ishifts,←(9 6 57)(16 10 58)(7 15 59)(14 21 60) Ishifts,←(5 6 61)(12 10 62)(3 15 63)(10 21 64) :EndClass }}} StephenTaylor