File : sha1.ads
-- Basic core for SHA1 calculation.
-- Child packages will be added for specific sources of bits,
-- as streams, strings, bit arrays or others.
-- See RFC3174 for details.
with Bit_arrays; use Bit_arrays;
with Interfaces;
package Sha1 is
Unimplemented: Exception;
type Digest is private;
function "<" (Left, Right: Digest) return boolean;
-- Empty digest:
Null_digest: constant Digest;
type Method is (Time_efficient, Space_efficient);
-- Message length is measured in bits:
subtype Message_length is Interfaces.Unsigned_64; -- eight bytes
-- functions to easily display digests:
function To_Hex(D: Digest) return String;
function To_Base32(D: Digest) return String;
-- And their converse
function From_Hex (S : in String) return Digest; -- UNTESTED, MAY BE ERRONEOUS
function From_Base32 (S : in String) return Digest; -- TESTED, SAFE
-- conversion to/from binary string:
-- Maintains the word in big endian convention.
function To_char_array (D : in Digest) return String;
function From_char_array (S : in String) return Digest;
subtype Byte is Interfaces.Unsigned_8;
type Byte_array is array(Natural range <>) of Byte;
pragma Pack (Byte_array);
private
subtype Word is Interfaces.Unsigned_32; -- four bytes
type Word_array is array(integer range <>) of Word;
pragma Pack(Word_array);
type Digest is new Word_array(0..4);
pragma Pack(Digest);
Null_digest: constant Digest:= (others => 0);
subtype Block is Word_array(0..15);
Block_size: constant integer:= Block'Size / 8;
type Message is array(integer range <>) of Block;
subtype t_range is integer range 0..79;
type Context_kind is (Byte_context, Bit_context);
type Context
(Kind: Context_kind:= Byte_context;
Implementation: Method:= Time_efficient) is
record
Padded: Boolean:= false;
Length: Message_length:= 0;
H: Digest:=
(16#67452301#,
16#efcdab89#,
16#98badcfe#,
16#10325476#,
16#c3d2e1f0#);
Pos: Natural:= 0;
case Kind is
when Byte_context =>
Byte_data: Byte_array(0..63);
when Bit_context =>
Bit_data: Bit_array(0..511);
end case;
end record;
K: constant array(t_range) of Word:=
( 0..19 => 16#5a827999#,
20..39 => 16#6ed9eba1#,
40..59 => 16#8f1bbcdc#,
60..79 => 16#ca62c1d6#);
function f00_19(B, C, D: Word) return Word;
function f20_39(B, C, D: Word) return Word;
function f40_59(B, C, D: Word) return Word;
function f60_79(B, C, D: Word) return Word;
pragma Inline(f00_19, f20_39, f40_59, f60_79);
function f(t: t_range; B, C, D: Word) return Word;
pragma Inline(f);
function S(n: Interfaces.Unsigned_32; Amount: Natural)
return Interfaces.Unsigned_32
renames Interfaces.Rotate_left;
-- Processing method 1 in rfc3174:
-- Time efficient, space inefficient (364 bytes)
procedure Method1(Mi: Block; H: in out Digest);
-- Processing method 2 in rfc3174:
-- Time inefficient, space efficient (64 bytes)
procedure Method2(Mi: Block; H: in out Digest);
-- Auxiliary functions:
function To_block(B: Byte_array) return Block;
function To_block(B: Bit_array) return Block;
-- Data supplying:
procedure Feed
(C: in out Context; B: Byte_array; Count_size: boolean:= true);
procedure Feed
(C: in out Context; b: Bit_array; Count_size: boolean:= true);
-- Final results:
function Get_SHA1(C: Context) return Digest;
end Sha1;