comp.lang.ada
 help / color / mirror / Atom feed
* MD5 Function in Ada
@ 1997-06-03  0:00 Jonathan Guthrie
  1997-06-04  0:00 ` Rolf Ebert
  1997-06-05  0:00 ` Anne & Bill Pritchett
  0 siblings, 2 replies; 5+ messages in thread
From: Jonathan Guthrie @ 1997-06-03  0:00 UTC (permalink / raw)



Is there any available source for calculating MD5 hashes in Ada?

-- 
Jonathan Guthrie (jguthrie@brokersys.com)
Information Broker Systems   +281-895-8101   http://www.brokersys.com/
12703 Veterans Memorial #106, Houston, TX  77014, USA

We sell Internet access and commercial Web space.  We also are general
network consultants in the greater Houston area.





^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: MD5 Function in Ada
       [not found] <199706041300.JAA27378@acmey.gatech.edu>
@ 1997-06-04  0:00 ` Jonathan Guthrie
  0 siblings, 0 replies; 5+ messages in thread
From: Jonathan Guthrie @ 1997-06-04  0:00 UTC (permalink / raw)
  To: jm59


On Wed, 4 Jun 1997, MILLS,JOHN M. wrote:

> In comp.lang.ada you write:
 
> >Is there any available source for calculating MD5 hashes in Ada?
 
> If you don't find a verified source, would it be acceptable to link
> the C-language object into your Ada?  Of course this wouldn't be "pure Ada,"
> but I would still prefer that to verifying a non-trusted source for such
> security-critical functions as MD5 commonly provides.  If you can't find
> the C source publically, I must have an archive address somewhere.
 
> Sorry for not addressing your question directly.

That's okay.  I actually expected someone to suggest linking in a C source
file.  As a matter of fact, I have two different MD5 implementations in C
source (and I could type in the one in APPLIED CRYPTOGRAPHY if I wanted a
third.) I just don't want to have to figure out how to call C code from
Ada in order to implement this.  This is not for a money-making project
(like the guy who's looking for the socket stuff, it's actually intended
to be a learning experience for me) so I don't care if I approach the 
project in the most efficient manner possible or not.

In any case, I don't think that verifying the source is that big a deal. 
The reason is because of the way that MD5 hashes are usually used.  If I
choose my test suite at "random", it is highly unlikely that someone would
be able to create a function that generates the proper MD5 hashes for all
the files in the test suite but has some security hole when used in
practice. 

So, if I have test set of oh, a dozen or so files (both large and small) 
I can compare the hashes with the MD5 generator I'm currently using and 
it will immediately obvious if the algorithm hasn't been implemented 
correctly.

It will also be obvious if something is broken (and, from my perspective, 
security holes are equivalent to a broken implementation, for reasons 
that I hope will soon be clear) the first time I use a bad implementation 
because of the application for which I want this.  What I'm trying to do 
is implement a RADIUS (Remote Authentication for Dial-In User Services) 
server.  I'm currently looking at implementing this in Ada, Modula-3, and 
Scheme.  (I will, no doubt, pick one language before I go very much 
farther.)

RADIUS uses an MD5 hash on parts of the message to encrypt the parts that 
must be kept secret.  Since both the server end and the client end must 
generate the same hash for it to work, and with a client that works 
with a verified MD5 hash generator, it is impossible for a broken 
implementation to work at all.

A RADIUS server would make a good project because although RADIUS has 
been widely deployed, (we use RADIUS here at IBS for authenticating most 
of our callers) there are but two RADIUS servers widely used.  The MERIT 
server doesn't work.  (I can get it to run for as long as two hours at a 
time.)  The Livingston server works, but it's not easily modifyable and 
it's fairly nonportable.  What I'd like to do is create a server that 
is more modular (my model is the Apache Web server) so that end users can 
write modules to link in to the executable and add to or modify the 
server's functionality without digging through half the source.

The languages that I listed all have various strengths and weaknesses, but
although I have good free compilers for all three languages, I have no MD5
code in any of them.  Ada's main strength is standardized multithreading
support on a diverse collection of platforms, and it's the language I'm
least experienced with.  (That's an advantage because it enhances the
effect of the "learning experience".)  Modula-3 has socket support and
built-in multithreading on multiple platforms, but I'm more familiar with
it.  Scheme (a Lisp variant, for those who don't know) matches the problem
domain the best of the three, but the least support for sockets, 
threading, and bit-twiddling.

--  
Jonathan Guthrie (jguthrie@brokersys.com)
Information Broker Systems   +281-895-8101   http://www.brokersys.com/
12703 Veterans Memorial #106, Houston, TX  77014, USA

We sell Internet access and commercial Web space.  We also are general
network consultants in the greater Houston area.







^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: MD5 Function in Ada
  1997-06-03  0:00 Jonathan Guthrie
@ 1997-06-04  0:00 ` Rolf Ebert
  1997-06-05  0:00 ` Anne & Bill Pritchett
  1 sibling, 0 replies; 5+ messages in thread
From: Rolf Ebert @ 1997-06-04  0:00 UTC (permalink / raw)



>>>>> "JG" == Jonathan Guthrie <jguthrie@brokersys.com> writes:

JG> Is there any available source for calculating MD5 hashes in Ada? 

Yes,

I hereby release the following code to the public domain.  Run the
message through gnatchop and then gnatmake md5-test.

The following code is a hand coded translation to Ada of the md5 sample
implementation in C from rfc1321.  It is still very close to the C code
with Ada syntax.

I did that primarily as an excercise to learn more about Ada95 modular
types and shift operations.  If you want to use this code for any
serious work, you should carefully reread every single line and test it
extensively. 

Currently its speed is about 50% of the C implementation.  In both
versions (C and Ada) there are quite a few possibilities to improve the
performance. 


        Rolf
        ebert@waporo.muc.de

P.S.  Any feed back is welcome.

\f
--                              -*- Mode: Ada -*-
-- Filename        : md5.ads
-- Description     :
-- Author          : Rolf Ebert
-- Created On      : Tue Mar 25 20:06:55 1997
-- Last Modified By: Rolf Ebert
-- Last Modified On: Wed Jun  4 21:37:28 1997
-- Update Count    : 24
-- Status          : Unknown, Use with caution!
-- $Revision$
-- $Name$


package MD5 is


   type Byte is mod 2**8;
   type Byte_Array is array (Long_Integer range <>) of Byte;
   pragma Pack (Byte_Array);


   subtype Fingerprint is Byte_Array (1 .. 16);

   subtype Digest_String is String (1 .. 32);

   Malformed : exception;

   function Digest_From_Text (S : in Digest_String) return Fingerprint;

   function Digest_To_Text (A : in Fingerprint) return Digest_String;



   type Context is private;


   procedure Init (Ctx : in out Context);

   procedure Update
     (Ctx  : in out Context;
      Data : in     Byte_Array);

   procedure Update
     (Ctx  : in out Context;
      Data : in     String);

   procedure Final (Ctx : in out Context; Digest : out Fingerprint);



private


   type Word is mod 2**32;
   type Word_Array is array (Long_Integer range <>) of Word;
   pragma Pack (Word_Array);

   function Rotate_Left (Value : in Word; Amount : in Natural) return Word;
   pragma Import (Intrinsic, Rotate_Left);

   function Shift_Left (Value : in Word; Amount : in Natural) return Word;
   pragma Import (Intrinsic, Shift_Left);

   function Shift_Right (Value : in Word; Amount : in Natural) return Word;
   pragma Import (Intrinsic, Shift_Right);


   subtype ABCD_State is Word_Array (1 .. 4);
   subtype Count_T    is Word_Array (1 .. 2); -- long_integer ??

   subtype Buffer_T   is Byte_Array (1 .. 64);

   type Context is record
      State  : ABCD_State := (1 => 16#67452301#,
                              2 => 16#Efcdab89#,
                              3 => 16#98badcfe#,
                              4 => 16#10325476#);
      Count  : Count_T    := (1 => 0,
                              2 => 0);
      Buffer : Buffer_T   := (others => 0);
   end record;

end MD5;

--                             -*- Mode: Ada -*-
-- Filename        : md5.ads
-- Description     :
-- Author          : Rolf Ebert
-- Created On      : Tue Mar 25 20:06:55 1997
-- Last Modified By: Rolf Ebert
-- Last Modified On: Wed Jun  4 21:41:48 1997
-- Update Count    : 93
-- Status          : Unknown, Use with caution!
-- $Revision$
-- $Name$

with Ada.Unchecked_Conversion;

package body MD5 is


   procedure Transform
     (State : in out ABCD_State;
      Block : in     Buffer_T);
   procedure Encode
     (Output :    out Byte_Array;
      Input  : in     Word_Array);
   procedure Decode
     (Output :    out Word_Array;
      Input  : in     Byte_Array);


   --  F, G, H, I are the basic MD5 functions
   function F (X, Y, Z : in Word) return Word;
   function G (X, Y, Z : in Word) return Word;
   function H (X, Y, Z : in Word) return Word;
   function I (X, Y, Z : in Word) return Word;


   procedure FF
     (A          : in out Word;
      B, C, D, X : in     Word;
      S          : in     Natural;
      AC         : in     Word);
   procedure GG
     (A          : in out Word;
      B, C, D, X : in     Word;
      S          : in     Natural;
      AC         : in     Word);
   procedure HH
     (A          : in out Word;
      B, C, D, X : in     Word;
      S          : in     Natural;
      AC         : in     Word);
   procedure II
     (A          : in out Word;
      B, C, D, X : in     Word;
      S          : in     Natural;
      AC         : in     Word);


   --
   function F (X, Y, Z : in Word) return Word is
   begin
      return (X and Y) or ((not X) and Z);
   end F;
   pragma Inline (F);


   function G (X, Y, Z : in Word) return Word is
   begin
      return (X and Z) or (Y and (not Z));
   end G;
   pragma Inline (G);


   function H (X, Y, Z : in Word) return Word is
   begin
      return X xor Y xor Z;
   end H;
   pragma Inline (H);


   function I (X, Y, Z : in Word) return Word is
   begin
      return Y xor (X or (not Z));
   end I;
   pragma Inline (I);

--    generic
--       function basic_bit_op (X, y, z : in word) return word;
--    procedure generic_mang (A          : in out Word;
--                            B, C, D, X : in     Word;
--                            S          : in     Natural;
--                            AC         : in     Word);

   --
   procedure FF
     (A          : in out Word;
      B, C, D, X : in     Word;
      S          : in     Natural;
      AC         : in     Word)
   is
   begin
      A := A + F (B, C, D) + X + AC;
      A := Rotate_Left (A, S);
      A := A + B;
   end FF;
   pragma Inline (FF);


   procedure GG
     (A          : in out Word;
      B, C, D, X : in     Word;
      S          : in     Natural;
      AC         : in     Word)
   is
   begin
      A := A + G (B, C, D) + X + AC;
      A := Rotate_Left (A, S);
      A := A + B;
   end GG;
   pragma Inline (GG);


   procedure HH
     (A          : in out Word;
      B, C, D, X : in     Word;
      S          : in     Natural;
      AC         : in     Word)
   is
   begin
      A := A + H (B, C, D) + X + AC;
      A := Rotate_Left (A, S);
      A := A + B;
   end HH;
   pragma Inline (HH);


   procedure II
     (A          : in out Word;
      B, C, D, X : in     Word;
      S          : in     Natural;
      AC         : in     Word)
   is
   begin
      A := A + I (B, C, D) + X + AC;
      A := Rotate_Left (A, S);
      A := A + B;
   end II;
   pragma Inline (II);


   --  MD5 Initialization.  Begin an MD5 operation, writing a new context.
   procedure Init (Ctx : in out Context)
   is
   begin --  Init
      Ctx.Count (1) := 0;
      Ctx.Count (2) := 0;

      Ctx.State (1) := 16#67452301#;
      Ctx.State (2) := 16#Efcdab89#;
      Ctx.State (3) := 16#98badcfe#;
      Ctx.State (4) := 16#10325476#;

      Ctx.Buffer    := (others => 0);
   end Init;



   procedure Update
     (Ctx  : in out Context;
      Data : in     Byte_Array)
   is
      I        : Long_Integer;
      Index    : Long_Integer;
      Part_Len : Long_Integer;
   begin --  Update
      -- compute number of bytes mod 64
      Index := Long_Integer (Shift_Right (Ctx.Count (1), 3) and 16#3F#);

      -- update number of bits
      Ctx.Count (1) := Ctx.Count (1) + Shift_Left (Word (Data'Length), 3);
      if Ctx.Count (1) < Shift_Left (Word (Data'Length), 3) then
         Ctx.Count (2) := Ctx.Count (2) + 1;
      end if;
      Ctx.Count (2) := Ctx.Count (2) + Shift_Right (Word (Data'Length), 29);

      Part_Len := 64 - Index;
      -- Transform as many times as possible.
      if Data'Length >= Part_Len then
         Ctx.Buffer (Index + 1 .. Index + Part_Len) :=
           Data (Data'First .. Data'First + Part_Len - 1);

         Transform (Ctx.State, Ctx.Buffer);

         I := Part_Len;
         while I + 63 < Data'Length loop
            Transform (Ctx.State, Data (I + 1 .. I + 64));
            I := I + 64;
         end loop;
         Index := 0;
      else
         I := 0;
      end if;

      -- Buffer remaining input
      Ctx.Buffer (Index + 1 .. Index + Data'Length - I) :=
        Data (I + 1 .. Data'Length);

   end Update;


   procedure Update
     (Ctx  : in out Context;
      Data : in     String)
   is
      subtype Constrained_Byte_Array is Byte_Array (1 .. Data'Length);
      subtype Constrained_String is String (1 .. Data'Length);

      function String_To_Byte_Array is new Ada.Unchecked_Conversion
        (Source => Constrained_String,
         Target => Constrained_Byte_Array);

      Data_As_Byte : Constrained_Byte_Array;

   begin
      Data_As_Byte := String_To_Byte_Array (Constrained_String (Data));
      Update (Ctx, Data_As_Byte);
   end Update;



   -- MD5 finalization.  Ends an MD5 message-digest operation, writing the
   -- message digest and zeroizing the context.
   procedure Final (Ctx : in out Context; Digest : out Fingerprint)
   is
      Bits       : Byte_Array (1 .. 8);
      Index      : Long_Integer;
      Pad_Length : Long_Integer;

      Padding : constant Buffer_T := (1 => 16#80#, others => 0);

   begin --  Final
      -- save number of bits
      Encode (Bits, Ctx.Count);

      -- Pad out to 56 mod 64.
      Index := Long_Integer (Shift_Right (Ctx.Count(1), 3) and 16#3F#);
      if Index < 56 then
         Pad_Length := 56 - Index;
      else
         Pad_Length := 120 - Index;
      end if;

      Update (Ctx, Padding (1 .. Pad_Length));

      -- Append length (before padding)
      Update (Ctx, Bits);

      -- Store state in digest
      Encode (Digest, Ctx.State);

      -- Zeroize sensitive information.
      Ctx.State := (others => 0);
      Ctx.Count := (others => 0);
      Ctx.Buffer := (others => 0);

   end Final;


   procedure Transform
     (State : in out ABCD_State;
      Block : in     Buffer_T)
   is

      S11 : constant :=  7;
      S12 : constant := 12;
      S13 : constant := 17;
      S14 : constant := 22;
      S21 : constant :=  5;
      S22 : constant :=  9;
      S23 : constant := 14;
      S24 : constant := 20;
      S31 : constant :=  4;
      S32 : constant := 11;
      S33 : constant := 16;
      S34 : constant := 23;
      S41 : constant :=  6;
      S42 : constant := 10;
      S43 : constant := 15;
      S44 : constant := 21;

      A : Word := State (1);
      B : Word := State (2);
      C : Word := State (3);
      D : Word := State (4);

      X : Word_Array (0 .. 15);
   begin
      Decode (X, Block);

      --  Round 1
      FF (A, B, C, D, X ( 0), S11, 16#D76AA478#); --  1
      FF (D, A, B, C, X ( 1), S12, 16#E8C7B756#); --  2
      FF (C, D, A, B, X ( 2), S13, 16#242070DB#); --  3
      FF (B, C, D, A, X ( 3), S14, 16#C1BDCEEE#); --  4
      FF (A, B, C, D, X ( 4), S11, 16#F57C0FAF#); --  5
      FF (D, A, B, C, X ( 5), S12, 16#4787C62A#); --  6
      FF (C, D, A, B, X ( 6), S13, 16#A8304613#); --  7
      FF (B, C, D, A, X ( 7), S14, 16#FD469501#); --  8
      FF (A, B, C, D, X ( 8), S11, 16#698098D8#); --  9
      FF (D, A, B, C, X ( 9), S12, 16#8B44F7AF#); --  10
      FF (C, D, A, B, X (10), S13, 16#FFFF5BB1#); --  11
      FF (B, C, D, A, X (11), S14, 16#895CD7BE#); --  12
      FF (A, B, C, D, X (12), S11, 16#6B901122#); --  13
      FF (D, A, B, C, X (13), S12, 16#FD987193#); --  14
      FF (C, D, A, B, X (14), S13, 16#A679438E#); --  15
      FF (B, C, D, A, X (15), S14, 16#49B40821#); --  16

      --  Round 2
      GG (A, B, C, D, X ( 1), S21, 16#F61E2562#); --  17
      GG (D, A, B, C, X ( 6), S22, 16#C040B340#); --  18
      GG (C, D, A, B, X (11), S23, 16#265E5A51#); --  19
      GG (B, C, D, A, X ( 0), S24, 16#E9B6C7AA#); --  20
      GG (A, B, C, D, X ( 5), S21, 16#D62F105D#); --  21
      GG (D, A, B, C, X (10), S22,  16#2441453#); --  22
      GG (C, D, A, B, X (15), S23, 16#D8A1E681#); --  23
      GG (B, C, D, A, X ( 4), S24, 16#E7D3FBC8#); --  24
      GG (A, B, C, D, X ( 9), S21, 16#21E1CDE6#); --  25
      GG (D, A, B, C, X (14), S22, 16#C33707D6#); --  26
      GG (C, D, A, B, X ( 3), S23, 16#F4D50D87#); --  27
      GG (B, C, D, A, X ( 8), S24, 16#455A14ED#); --  28
      GG (A, B, C, D, X (13), S21, 16#A9E3E905#); --  29
      GG (D, A, B, C, X ( 2), S22, 16#FCEFA3F8#); --  30
      GG (C, D, A, B, X ( 7), S23, 16#676F02D9#); --  31
      GG (B, C, D, A, X (12), S24, 16#8D2A4C8A#); --  32

      --  Round 3
      HH (A, B, C, D, X ( 5), S31, 16#FFFA3942#); --  33
      HH (D, A, B, C, X ( 8), S32, 16#8771F681#); --  34
      HH (C, D, A, B, X (11), S33, 16#6D9D6122#); --  35
      HH (B, C, D, A, X (14), S34, 16#FDE5380C#); --  36
      HH (A, B, C, D, X ( 1), S31, 16#A4BEEA44#); --  37
      HH (D, A, B, C, X ( 4), S32, 16#4BDECFA9#); --  38
      HH (C, D, A, B, X ( 7), S33, 16#F6BB4B60#); --  39
      HH (B, C, D, A, X (10), S34, 16#BEBFBC70#); --  40
      HH (A, B, C, D, X (13), S31, 16#289B7EC6#); --  41
      HH (D, A, B, C, X ( 0), S32, 16#EAA127FA#); --  42
      HH (C, D, A, B, X ( 3), S33, 16#D4EF3085#); --  43
      HH (B, C, D, A, X ( 6), S34,  16#4881D05#); --  44
      HH (A, B, C, D, X ( 9), S31, 16#D9D4D039#); --  45
      HH (D, A, B, C, X (12), S32, 16#E6DB99E5#); --  46
      HH (C, D, A, B, X (15), S33, 16#1FA27CF8#); --  47
      HH (B, C, D, A, X ( 2), S34, 16#C4AC5665#); --  48

      --  Round 4
      II (A, B, C, D, X ( 0), S41, 16#F4292244#); --  49
      II (D, A, B, C, X ( 7), S42, 16#432AFF97#); --  50
      II (C, D, A, B, X (14), S43, 16#AB9423A7#); --  51
      II (B, C, D, A, X ( 5), S44, 16#FC93A039#); --  52
      II (A, B, C, D, X (12), S41, 16#655B59C3#); --  53
      II (D, A, B, C, X ( 3), S42, 16#8F0CCC92#); --  54
      II (C, D, A, B, X (10), S43, 16#FFEFF47D#); --  55
      II (B, C, D, A, X ( 1), S44, 16#85845DD1#); --  56
      II (A, B, C, D, X ( 8), S41, 16#6FA87E4F#); --  57
      II (D, A, B, C, X (15), S42, 16#FE2CE6E0#); --  58
      II (C, D, A, B, X ( 6), S43, 16#A3014314#); --  59
      II (B, C, D, A, X (13), S44, 16#4E0811A1#); --  60
      II (A, B, C, D, X ( 4), S41, 16#F7537E82#); --  61
      II (D, A, B, C, X (11), S42, 16#BD3AF235#); --  62
      II (C, D, A, B, X ( 2), S43, 16#2AD7D2BB#); --  63
      II (B, C, D, A, X ( 9), S44, 16#EB86D391#); --  64

      State (1) := State (1) + A;
      State (2) := State (2) + B;
      State (3) := State (3) + C;
      State (4) := State (4) + D;

      --  Zeroize sensitive information.
      X := (others => 0);

   end Transform;


   -- Encodes input into output 
   procedure Encode
     (Output :    out Byte_Array;
      Input  : in     Word_Array)
   is
      J : Long_Integer;
   begin
--       if Output'Length / 4 /= Input'Length then
--          raise Constraint_Error;
--       end if;

      J := Output'First;
      for I in Input'range loop
         Output (J) := Byte (Input (I) and 16#FF#);
         Output (J + 1) := Byte (Shift_Right (Input (I), 8) and 16#FF#);
         Output (J + 2) := Byte (Shift_Right (Input (I), 16) and 16#FF#);
         Output (J + 3) := Byte (Shift_Right (Input (I), 24) and 16#FF#);
         J := J + 4;
      end loop;

   end Encode;


   -- Decodes input into output.
   procedure Decode
     (Output :    out Word_Array;
      Input  : in     Byte_Array)
   is
      J : Long_Integer;
   begin
--       if Output'Length /= Input'Length / 4 then
--          raise Constraint_Error;
--       end if;

      J := Input'First;
      for I in Output'range loop
         Output (I) := Word (Input (J)) or
           Shift_Left (Word (Input (J+1)), 8) or
           Shift_Left (Word (Input (J+2)), 16) or
           Shift_Left (Word (Input (J+3)), 24);
         J := J + 4;
      end loop;

   end Decode;




   type Conv_Array is array (0 .. 15) of Character;
   Hex_Tab : constant Conv_Array := "0123456789abcdef";


   function Digest_From_Text (S : in Digest_String) return Fingerprint is
      Digest : Fingerprint;
      Val    : Word;
      Ch     : Character;
   begin
      for I in Digest'range loop
         Ch := S (2 * Integer (I));
         case Ch is
            when '0' .. '9' =>
               Val := Character'Pos (Ch) - Character'Pos ('0');
            when 'a' .. 'f' =>
               Val := Character'Pos (Ch) - Character'Pos ('a') + 10;
            when 'A' .. 'F' =>
               Val := Character'Pos (Ch) - Character'Pos ('A') + 10;
            when others =>
               raise Malformed;
         end case;

         Val := Shift_Left (Val, 4);

         Ch := S (2 * Integer (I) + 1);
         case Ch is
            when '0' .. '9' =>
               Val := Val + (Character'Pos (Ch) - Character'Pos ('0'));
            when 'a' .. 'f' =>
               Val := Val + (Character'Pos (Ch) - Character'Pos ('a') + 10);
            when 'A' .. 'F' =>
               Val := Val + (Character'Pos (Ch) - Character'Pos ('A') + 10);
            when others =>
               raise Malformed;
         end case;

         Digest (I) := Byte (Val);
      end loop;
      return Digest;
   end Digest_From_Text;



   function  Digest_To_Text (A : in Fingerprint) return Digest_String is
      Str : Digest_String;
      J   : Positive;
   begin
      for I in A'range loop
         J           := 2 * Integer (I) - 1;
         Str (J)     := Hex_Tab (Natural (Shift_Right (Word (A (I)), 4)));
         Str (J + 1) := Hex_Tab (Natural (A (I) and 16#F#));
      end loop;
      return Str;
   end Digest_To_Text;


end MD5;
--                              -*- Mode: Ada -*-
-- Filename        : md5-driver.ads
-- Description     :
-- Author          : R. Ebert
-- Created On      : Wed Mar 26 12:37:44 1997
-- Last Modified By: Rolf Ebert
-- Last Modified On: Wed Jun  4 21:43:09 1997
-- Update Count    : 20
-- Status          : Unknown, Use with caution!
-- CVS             : $Id$
-- Release         : $Name$

with Ada.Calendar;
with Ada.Text_IO;

package body MD5.Driver is

   procedure Text (S : in String) is
      use Ada.Text_IO;

      C  : Context;
      FP : Fingerprint;

   begin -- Text
      Init (C);
      Update (C, S);
      Final (C, FP);

      Put ("MD5 ("""); Put (S); Put (""") = ");
      Put (Digest_To_Text (FP));
      New_Line;
   end Text;


   procedure Time_Trial is
      use Ada.Text_IO;
      use Ada.Calendar;

      C  : Context;
      FP : Fingerprint;

      Test_Block_Len   : constant := 1000;
      Test_Block_Count : constant := 10_000;
      Block : Byte_Array (1 .. Test_Block_Len);

      Start : Time;
      Stop  : Time;
      Dur   : Long_Float;

   begin
      Put ("MD5 time trial. Digesting" & Test_Block_Count'Img & Test_Block_Len'Img & "-byte blocks ...");

      -- Initialize block */
      for I in Block'range loop
         Block (I) := Byte (I) and 16#FF#;
      end loop;

      -- start timer
      Start := Clock;

      -- digest blocks
      Init (C);
      for I in 1 .. TEST_BLOCK_COUNT loop
         Update (C, Block);
      end loop;
      Final (C, Fp);

      -- stop timer
      Stop := Clock;

      Put_Line (" done");
      Put_Line ("Digest = " & Digest_To_Text (Fp));
      Dur := Long_Float (Stop - Start);
      Put_Line ("Time = " & Dur'Img & " seconds");
      Dur := Long_Float (TEST_BLOCK_LEN * TEST_BLOCK_COUNT) / Dur;
      Put_Line ("Speed = " & Dur'Img & " bytes/second");
   end Time_Trial;

   procedure Test_Suite is
   begin
      Ada.Text_IO.Put_Line ("MD5 test suite:");
      Text ("");
      Text ("a");
      Text ("abc");
      Text ("message digest");
      Text ("abcdefghijklmnopqrstuvwxyz");
      Text ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
      Text ("12345678901234567890123456789012345678901234567890123456789012345678901234567890");
      Text ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912345678901234567890123456789012345678901234567890123456789012345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
      Text ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
& "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
& "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912345678901234567890123456789012345678901234567890123456789012345678901234567890");
      Text ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRS"
& "TUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv"
& "wxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912345678901234567890123456789012345678901234567890123456789012345678901234567"
& "890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
& "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012"
& "3456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912345678901234567890123456789012345678901234567890123456789012345678901234567890ABCD"
& "EFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg"
& "hijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
& "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678912345678901234567890123456789012345678901234567890123456789012345678901234567890");
   end Test_Suite;

   procedure File (Filename : in String)
   is
   begin -- File
      null;
   end File;


   procedure Filter is
   begin
      null;
   end Filter;

end MD5.Driver;
--                              -*- Mode: Ada -*-
-- Filename        : md5-driver.ads
-- Description     :
-- Author          : R. Ebert
-- Created On      : Wed Mar 26 12:37:44 1997
-- Last Modified By: Rolf Ebert
-- Last Modified On: Wed Jun  4 21:42:08 1997
-- Update Count    : 2
-- Status          : Unknown, Use with caution!
-- CVS             : $Id$
-- Release         : $Name$


package MD5.Driver is

   procedure Text (S : in String);

   procedure Time_Trial;

   procedure Test_Suite;

   procedure File (Filename : in String);

   procedure Filter;

end MD5.Driver;
--                              -*- Mode: Ada -*-
-- Filename        : md5-test.adb
-- Description     :
-- Author          : R. Ebert
-- Created On      : Wed Mar 26 12:17:15 1997
-- Last Modified By: Rolf Ebert
-- Last Modified On: Wed Jun  4 21:44:27 1997
-- Update Count    : 10
-- Status          : Unknown, Use with caution!
-- CVS             : $Id$
-- Release         : $Name$


with Ada.Command_Line;
with MD5.Driver;

procedure MD5.Test is
   use Ada.Command_Line;
   I : Natural;
begin
   if Argument_Count > 0 then
      I := 1;
      while I <=  Argument_Count loop
         if Argument (I)(1..2) = "-s" then
            MD5.Driver.Text (Argument (I + 1));
            I := I + 1;
         elsif Argument (I) = "-t" then
            MD5.Driver.Time_Trial;
         elsif Argument (I) = "-x" then
            MD5.Driver.Test_Suite;
         else
            MD5.Driver.File (Argument (I));
         end if;
         I := I + 1;
      end loop;
   else
      MD5.Driver.Filter;
   end if;
end MD5.Test;

--                              -*- Mode: Ada -*-
-- Filename        : md5-test.ads
-- Description     :
-- Author          : R. Ebert
-- Created On      : Wed Mar 26 12:17:15 1997
-- Last Modified By: Rolf Ebert
-- Last Modified On: Wed Jun  4 21:43:30 1997
-- Update Count    : 1
-- Status          : Unknown, Use with caution!
-- CVS             : $Id$
-- Release         : $Name$


procedure MD5.Test;
MD5 test suite:
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f
MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a





^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: MD5 Function in Ada
  1997-06-03  0:00 Jonathan Guthrie
  1997-06-04  0:00 ` Rolf Ebert
@ 1997-06-05  0:00 ` Anne & Bill Pritchett
  1 sibling, 0 replies; 5+ messages in thread
From: Anne & Bill Pritchett @ 1997-06-05  0:00 UTC (permalink / raw)



Jonathan Guthrie wrote:
> 
> Is there any available source for calculating MD5 hashes in Ada?
> 
> --
> Jonathan Guthrie (jguthrie@brokersys.com)
> Information Broker Systems   +281-895-8101   http://www.brokersys.com/
> 12703 Veterans Memorial #106, Houston, TX  77014, USA
> 
> We sell Internet access and commercial Web space.  We also are general
> network consultants in the greater Houston area.

I've written a partial Ada 95 binding to the BSafe software (C
Libraries) by RSA security which has, among other things, an MD5 Hashing
algorithm.  BSafe isn't free, 
but it's not very expensive (~$300) and it works very well.  The binding
I have works with ObjectAda and I assume it will work with GNAT also.

Bill Pritchett
DCS Corporation
wpritche@dcscorp.com




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: MD5 Function in Ada
@ 1997-06-06  0:00 Jerry van Dijk
  0 siblings, 0 replies; 5+ messages in thread
From: Jerry van Dijk @ 1997-06-06  0:00 UTC (permalink / raw)



Jon, long time since C_ECHO :-)

In article <Pine.LNX.3.91.970604091908.3334A-100000@weck.bro jguthrie@brokersys.com writes:

>That's okay.  I actually expected someone to suggest linking in a C source
>file.  As a matter of fact, I have two different MD5 implementations in C
>source (and I could type in the one in APPLIED CRYPTOGRAPHY if I wanted a
>third.) I just don't want to have to figure out how to call C code from
>Ada in order to implement this.

Actually, using GNAT, this doesn't take much figuring out:

   /* interface to 'int do_something(int input) */
   function Do_Something (Input : in Integer) return Integer;
   pragma Import (C, Do_Something, "do_something);

as in GNAT there's a direct correspondence between the Ada and C type's.

If you do not want to rely on this, standard Ada95 with support for
Annex B (Interface to other languages), has the package Interfaces.C
defining them portably (and also have Interfaces.C.Strings and
Interfaces.C.Pointers).

--

-- Jerry van Dijk       | Leiden, Holland
-- Consultant           | Team Ada
-- Ordina Finance       | jdijk@acm.org




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~1997-06-06  0:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-06-06  0:00 MD5 Function in Ada Jerry van Dijk
     [not found] <199706041300.JAA27378@acmey.gatech.edu>
1997-06-04  0:00 ` Jonathan Guthrie
  -- strict thread matches above, loose matches on Subject: below --
1997-06-03  0:00 Jonathan Guthrie
1997-06-04  0:00 ` Rolf Ebert
1997-06-05  0:00 ` Anne & Bill Pritchett

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox