-- --
-- B o d y --
-- --
--- Copyright (C) 2002 Ada Core Technologies, Inc. --
+-- Copyright (C) 2002-2006, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING. If not, write --
--- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
--- MA 02111-1307, USA. --
+-- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
+-- Boston, MA 02110-1301, USA. --
-- --
-- As a special exception, if other files instantiate generics from this --
-- unit, or you link this unit with other files to produce an executable, --
procedure Transform
(C : in out Context;
Block : String);
- -- Process one block of 64 characters.
+ -- Process one block of 64 characters
------------
-- Decode --
(Block : String;
X : out Sixteen_Words)
is
- Cur : Positive := Block'First;
+ Cur : Positive := Block'First;
begin
pragma Assert (Block'Length = 64);
Result : Message_Digest;
Cur : Natural := 1;
- -- Index in Result where the next character will be placed.
+ -- Index in Result where the next character will be placed
+
+ Last_Block : String (1 .. 64);
+
+ C1 : Context := C;
procedure Convert (X : Unsigned_32);
-- Put the contribution of one of the four words (A, B, C, D) of the
procedure Convert (X : Unsigned_32) is
Y : Unsigned_32 := X;
-
begin
for J in 1 .. 4 loop
Result (Cur + 1) := Hex_Digit (Y and Unsigned_32'(16#0F#));
-- Start of processing for Digest
begin
- Convert (C.A);
- Convert (C.B);
- Convert (C.C);
- Convert (C.D);
+ -- Process characters in the context buffer, if any
+
+ Last_Block (1 .. C.Last) := C.Buffer (1 .. C.Last);
+
+ -- Too many magic literals below, should be defined as constants ???
+
+ if C.Last > 55 then
+ Last_Block (C.Last + 1 .. 64) := Padding (1 .. 64 - C.Last);
+ Transform (C1, Last_Block);
+ Last_Block := (others => ASCII.NUL);
+
+ else
+ Last_Block (C.Last + 1 .. 56) := Padding (1 .. 56 - C.Last);
+ end if;
+
+ -- Add the input length (as stored in the context) as 8 characters
+
+ Last_Block (57 .. 64) := (others => ASCII.NUL);
+
+ declare
+ L : Unsigned_64 := Unsigned_64 (C.Length) * 8;
+ Idx : Positive := 57;
+
+ begin
+ while L > 0 loop
+ Last_Block (Idx) := Character'Val (L and 16#Ff#);
+ L := Shift_Right (L, 8);
+ Idx := Idx + 1;
+ end loop;
+ end;
+
+ Transform (C1, Last_Block);
+
+ Convert (C1.A);
+ Convert (C1.B);
+ Convert (C1.C);
+ Convert (C1.D);
return Result;
end Digest;
function Digest (S : String) return Message_Digest is
C : Context;
-
begin
Update (C, S);
return Digest (C);
end Digest;
function Digest
- (A : Ada.Streams.Stream_Element_Array)
- return Message_Digest
+ (A : Ada.Streams.Stream_Element_Array) return Message_Digest
is
C : Context;
-
begin
Update (C, A);
return Digest (C);
(C : in out Context;
Input : String)
is
- Cur : Positive := Input'First;
- Last_Block : String (1 .. 64);
+ Inp : constant String := C.Buffer (1 .. C.Last) & Input;
+ Cur : Positive := Inp'First;
begin
- while Cur + 63 <= Input'Last loop
- Transform (C, Input (Cur .. Cur + 63));
+ C.Length := C.Length + Input'Length;
+
+ while Cur + 63 <= Inp'Last loop
+ Transform (C, Inp (Cur .. Cur + 63));
Cur := Cur + 64;
end loop;
- Last_Block (1 .. Input'Last - Cur + 1) := Input (Cur .. Input'Last);
-
- if Input'Last - Cur + 1 > 56 then
- Cur := Input'Last - Cur + 2;
- Last_Block (Cur .. 64) := Padding (1 .. 64 - Cur + 1);
- Transform (C, Last_Block);
- Last_Block := (others => ASCII.NUL);
-
- else
- Cur := Input'Last - Cur + 2;
- Last_Block (Cur .. 56) := Padding (1 .. 56 - Cur + 1);
- end if;
-
- -- Add the input length as 8 characters
-
- Last_Block (57 .. 64) := (others => ASCII.NUL);
-
- declare
- L : Unsigned_64 := Unsigned_64 (Input'Length) * 8;
-
- begin
- Cur := 57;
- while L > 0 loop
- Last_Block (Cur) := Character'Val (L and 16#Ff#);
- L := Shift_Right (L, 8);
- Cur := Cur + 1;
- end loop;
- end;
-
- Transform (C, Last_Block);
+ C.Last := Inp'Last - Cur + 1;
+ C.Buffer (1 .. C.Last) := Inp (Cur .. Inp'Last);
end Update;
procedure Update
function Wide_Digest (W : Wide_String) return Message_Digest is
C : Context;
-
begin
Wide_Update (C, W);
return Digest (C);
(C : in out Context;
Input : Wide_String)
is
-
String_Input : String (1 .. 2 * Input'Length);
Cur : Positive := 1;