How to resolve the algorithm MD5/Implementation step by step in the REXX programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm MD5/Implementation step by step in the REXX programming language

Table of Contents

Problem Statement

The purpose of this task to code and validate an implementation of the MD5 Message Digest Algorithm by coding the algorithm directly (not using a call to a built-in or external hashing library). For details of the algorithm refer to MD5 on Wikipedia or the MD5 definition in IETF RFC (1321).

The solutions shown here will provide practical illustrations of bit manipulation, unsigned integers, working with little-endian data. Additionally, the task requires an attention to details such as boundary conditions since being out by even 1 bit will produce dramatically different results. Subtle implementation bugs can result in some hashes being correct while others are wrong. Not only is it critical to get the individual sub functions working correctly, even small errors in padding, endianness, or data layout will result in failure. In addition, intermediate outputs to aid in developing an implementation can be found here. The MD5 Message-Digest Algorithm was developed by RSA Data Security, Inc. in 1991.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm MD5/Implementation step by step in the REXX programming language

Source code in the rexx programming language

/*REXX program tests the MD5 procedure (below) as per a test suite from IETF RFC (1321).*/
@.1 =                                            /*─────MD5 test suite [from above doc].*/
@.2 = 'a'
@.3 = 'abc'
@.4 = 'message digest'
@.5 = 'abcdefghijklmnopqrstuvwxyz'
@.6 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
@.7 =  12345678901234567890123456789012345678901234567890123456789012345678901234567890
@.0 = 7                                          /* [↑]  last value doesn't need quotes.*/
                do m=1  for  @.0;         say    /*process each of the seven messages.  */
                say ' in ='  @.m                 /*display the      in      message.    */
                say 'out ='  MD5(@.m)            /*   "     "       out        "        */
                end   /*m*/
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
MD5: procedure; parse arg !;  numeric digits 20  /*insure there's enough decimal digits.*/
     a= '67452301'x;         b= "efcdab89"x;         c= '98badcfe'x;        d= "10325476"x
     #= length(!)                                /*length in bytes of the input message.*/
     L= #*8//512;   if L<448  then plus= 448 - L /*is the length  less   than  448 ?    */
                    if L>448  then plus= 960 - L /* "  "     "   greater   "    "       */
                    if L=448  then plus= 512     /* "  "     "    equal   to    "       */
                                                 /* [↓]  a little of this, ···          */
     $=! || "80"x || copies('0'x,plus%8-1)reverse(right(d2c(8*#), 4, '0'x)) || '00000000'x
                                                 /* [↑]       ···  and a little of that.*/
         do j=0  for length($) % 64              /*process the message  (lots of steps).*/
         a_= a;     b_= b;     c_= c;      d_= d /*save the  original values  for later.*/
         chunk= j * 64                           /*calculate the  size  of the chunks.  */
                       do k=1  for 16            /*process the message in chunks.       */
                       !.k= reverse( substr($, chunk + 1 + 4*(k-1), 4) )  /*magic stuff.*/
                       end   /*k*/                                        /*────step────*/
         a  =  .p1( a,   b,   c,   d,    0,    7,   3614090360)           /*■■■■  1 ■■■■*/
         d  =  .p1( d,   a,   b,   c,    1,   12,   3905402710)           /*■■■■  2 ■■■■*/
         c  =  .p1( c,   d,   a,   b,    2,   17,    606105819)           /*■■■■  3 ■■■■*/
         b  =  .p1( b,   c,   d,   a,    3,   22,   3250441966)           /*■■■■  4 ■■■■*/
         a  =  .p1( a,   b,   c,   d,    4,    7,   4118548399)           /*■■■■  5 ■■■■*/
         d  =  .p1( d,   a,   b,   c,    5,   12,   1200080426)           /*■■■■  6 ■■■■*/
         c  =  .p1( c,   d,   a,   b,    6,   17,   2821735955)           /*■■■■  7 ■■■■*/
         b  =  .p1( b,   c,   d,   a,    7,   22,   4249261313)           /*■■■■  8 ■■■■*/
         a  =  .p1( a,   b,   c,   d,    8,    7,   1770035416)           /*■■■■  9 ■■■■*/
         d  =  .p1( d,   a,   b,   c,    9,   12,   2336552879)           /*■■■■ 10 ■■■■*/
         c  =  .p1( c,   d,   a,   b,   10,   17,   4294925233)           /*■■■■ 11 ■■■■*/
         b  =  .p1( b,   c,   d,   a,   11,   22,   2304563134)           /*■■■■ 12 ■■■■*/
         a  =  .p1( a,   b,   c,   d,   12,    7,   1804603682)           /*■■■■ 13 ■■■■*/
         d  =  .p1( d,   a,   b,   c,   13,   12,   4254626195)           /*■■■■ 14 ■■■■*/
         c  =  .p1( c,   d,   a,   b,   14,   17,   2792965006)           /*■■■■ 15 ■■■■*/
         b  =  .p1( b,   c,   d,   a,   15,   22,   1236535329)           /*■■■■ 16 ■■■■*/
         a  =  .p2( a,   b,   c,   d,    1,    5,   4129170786)           /*■■■■ 17 ■■■■*/
         d  =  .p2( d,   a,   b,   c,    6,    9,   3225465664)           /*■■■■ 18 ■■■■*/
         c  =  .p2( c,   d,   a,   b,   11,   14,    643717713)           /*■■■■ 19 ■■■■*/
         b  =  .p2( b,   c,   d,   a,    0,   20,   3921069994)           /*■■■■ 20 ■■■■*/
         a  =  .p2( a,   b,   c,   d,    5,    5,   3593408605)           /*■■■■ 21 ■■■■*/
         d  =  .p2( d,   a,   b,   c,   10,    9,     38016083)           /*■■■■ 22 ■■■■*/
         c  =  .p2( c,   d,   a,   b,   15,   14,   3634488961)           /*■■■■ 23 ■■■■*/
         b  =  .p2( b,   c,   d,   a,    4,   20,   3889429448)           /*■■■■ 24 ■■■■*/
         a  =  .p2( a,   b,   c,   d,    9,    5,    568446438)           /*■■■■ 25 ■■■■*/
         d  =  .p2( d,   a,   b,   c,   14,    9,   3275163606)           /*■■■■ 26 ■■■■*/
         c  =  .p2( c,   d,   a,   b,    3,   14,   4107603335)           /*■■■■ 27 ■■■■*/
         b  =  .p2( b,   c,   d,   a,    8,   20,   1163531501)           /*■■■■ 28 ■■■■*/
         a  =  .p2( a,   b,   c,   d,   13,    5,   2850285829)           /*■■■■ 29 ■■■■*/
         d  =  .p2( d,   a,   b,   c,    2,    9,   4243563512)           /*■■■■ 30 ■■■■*/
         c  =  .p2( c,   d,   a,   b,    7,   14,   1735328473)           /*■■■■ 31 ■■■■*/
         b  =  .p2( b,   c,   d,   a,   12,   20,   2368359562)           /*■■■■ 32 ■■■■*/
         a  =  .p3( a,   b,   c,   d,    5,    4,   4294588738)           /*■■■■ 33 ■■■■*/
         d  =  .p3( d,   a,   b,   c,    8,   11,   2272392833)           /*■■■■ 34 ■■■■*/
         c  =  .p3( c,   d,   a,   b,   11,   16,   1839030562)           /*■■■■ 35 ■■■■*/
         b  =  .p3( b,   c,   d,   a,   14,   23,   4259657740)           /*■■■■ 36 ■■■■*/
         a  =  .p3( a,   b,   c,   d,    1,    4,   2763975236)           /*■■■■ 37 ■■■■*/
         d  =  .p3( d,   a,   b,   c,    4,   11,   1272893353)           /*■■■■ 38 ■■■■*/
         c  =  .p3( c,   d,   a,   b,    7,   16,   4139469664)           /*■■■■ 39 ■■■■*/
         b  =  .p3( b,   c,   d,   a,   10,   23,   3200236656)           /*■■■■ 40 ■■■■*/
         a  =  .p3( a,   b,   c,   d,   13,    4,    681279174)           /*■■■■ 41 ■■■■*/
         d  =  .p3( d,   a,   b,   c,    0,   11,   3936430074)           /*■■■■ 42 ■■■■*/
         c  =  .p3( c,   d,   a,   b,    3,   16,   3572445317)           /*■■■■ 43 ■■■■*/
         b  =  .p3( b,   c,   d,   a,    6,   23,     76029189)           /*■■■■ 44 ■■■■*/
         a  =  .p3( a,   b,   c,   d,    9,    4,   3654602809)           /*■■■■ 45 ■■■■*/
         d  =  .p3( d,   a,   b,   c,   12,   11,   3873151461)           /*■■■■ 46 ■■■■*/
         c  =  .p3( c,   d,   a,   b,   15,   16,    530742520)           /*■■■■ 47 ■■■■*/
         b  =  .p3( b,   c,   d,   a,    2,   23,   3299628645)           /*■■■■ 48 ■■■■*/
         a  =  .p4( a,   b,   c,   d,    0,    6,   4096336452)           /*■■■■ 49 ■■■■*/
         d  =  .p4( d,   a,   b,   c,    7,   10,   1126891415)           /*■■■■ 50 ■■■■*/
         c  =  .p4( c,   d,   a,   b,   14,   15,   2878612391)           /*■■■■ 51 ■■■■*/
         b  =  .p4( b,   c,   d,   a,    5,   21,   4237533241)           /*■■■■ 52 ■■■■*/
         a  =  .p4( a,   b,   c,   d,   12,    6,   1700485571)           /*■■■■ 53 ■■■■*/
         d  =  .p4( d,   a,   b,   c,    3,   10,   2399980690)           /*■■■■ 54 ■■■■*/
         c  =  .p4( c,   d,   a,   b,   10,   15,   4293915773)           /*■■■■ 55 ■■■■*/
         b  =  .p4( b,   c,   d,   a,    1,   21,   2240044497)           /*■■■■ 56 ■■■■*/
         a  =  .p4( a,   b,   c,   d,    8,    6,   1873313359)           /*■■■■ 57 ■■■■*/
         d  =  .p4( d,   a,   b,   c,   15,   10,   4264355552)           /*■■■■ 58 ■■■■*/
         c  =  .p4( c,   d,   a,   b,    6,   15,   2734768916)           /*■■■■ 59 ■■■■*/
         b  =  .p4( b,   c,   d,   a,   13,   21,   1309151649)           /*■■■■ 60 ■■■■*/
         a  =  .p4( a,   b,   c,   d,    4,    6,   4149444226)           /*■■■■ 61 ■■■■*/
         d  =  .p4( d,   a,   b,   c,   11,   10,   3174756917)           /*■■■■ 62 ■■■■*/
         c  =  .p4( c,   d,   a,   b,    2,   15,    718787259)           /*■■■■ 63 ■■■■*/
         b  =  .p4( b,   c,   d,   a,    9,   21,   3951481745)           /*■■■■ 64 ■■■■*/
         a  =  .a(a_, a);         b=.a(b_, b);          c=.a(c_, c);        d=.a(d_, d)
         end   /*j*/
     return .rx(a).rx(b).rx(c).rx(d)             /*same as:  .rx(a) || .rx(b) ||  ···   */
/*──────────────────────────────────────────────────────────────────────────────────────*/
.a:  return  right( d2c( c2d( arg(1) )   +   c2d( arg(2) ) ),  4, '0'x)
.h:  return  bitxor( bitxor( arg(1), arg(2) ), arg(3) )
.i:  return  bitxor( arg(2), bitor(arg(1),  bitxor(arg(3),        'ffffffff'x) ) )
.f:  return  bitor( bitand(arg(1), arg(2)), bitand(bitxor(arg(1), 'ffffffff'x), arg(3) ) )
.g:  return  bitor( bitand(arg(1), arg(3)), bitand(arg(2), bitxor(arg(3), 'ffffffff'x) ) )
.rx: return  c2x( reverse( arg(1) ) )
.Lr: procedure;  parse arg _,#;    if #==0  then return _             /*left bit rotate.*/
                 ?=x2b(c2x(_));    return x2c( b2x( right(? || left(?, #), length(?) ) ) )
.p1: procedure expose !.;   parse arg w,x,y,z,n,m,_;             n=n + 1
               return .a(.Lr(right(d2c(_+c2d(w) + c2d(.f(x,y,z)) + c2d(!.n)),4,'0'x),m),x)
.p2: procedure expose !.;   parse arg w,x,y,z,n,m,_;             n=n + 1
               return .a(.Lr(right(d2c(_+c2d(w) + c2d(.g(x,y,z)) + c2d(!.n)),4,'0'x),m),x)
.p3: procedure expose !.;   parse arg w,x,y,z,n,m,_;             n=n + 1
               return .a(.Lr(right(d2c(_+c2d(w) + c2d(.h(x,y,z)) + c2d(!.n)),4,'0'x),m),x)
.p4: procedure expose !.;   parse arg w,x,y,z,n,m,_;             n=n + 1
               return .a(.Lr(right(d2c(c2d(w) + c2d(.i(x,y,z)) + c2d(!.n)+_),4,'0'x),m),x)


  

You may also check:How to resolve the algorithm XML/Input step by step in the Wren programming language
You may also check:How to resolve the algorithm Sierpinski carpet step by step in the C# programming language
You may also check:How to resolve the algorithm K-means++ clustering step by step in the JavaScript programming language
You may also check:How to resolve the algorithm First power of 2 that has leading decimal digits of 12 step by step in the Python programming language
You may also check:How to resolve the algorithm Phrase reversals step by step in the Raku programming language