2012-01-14 39 views
1

我使用​​在Ada中创建SHA1字符串的散列。我的代码基数很小,所以我想避免将任何库导入到我的编译器未提供的项目中,因此我使用的是​​。据我所知,检索散列的唯一“公共”方法是通过Digest函数以字符串形式。我想取而代之的是Context类型的H成员的160位块。不幸的是,Context记录是私密的。有什么办法可以解决吗?或者,他们是由GNAT还是Ada标准库提供的替代方法?从GNAT.SHA1获取SHA1块

+0

在执行(的一个优点寻找),看起来'Digest(C:Context)'比将'C'中的位转换为hex'好多了,所以除非你打算重新做这个,否则我会认为你的最好的选择是凯基汤普森所暗示的。 – 2012-01-14 12:19:35

+0

我认为@Keith Thompson的建议是对我的具体问题的最好回答。最终,我d准备下载John Halleck的SHA1 [实施](http://home.utah.edu/~nahaj/ada/sha/);只有3个源文件添加到我的项目。 – Anthony 2012-01-15 12:14:42

回答

4

我不知道任何直接的方式来获得160位块,但当然你可以从十六进制字符串计算它。

下面是我刚才扔在一起的一个例子。 (当然,通过添加"16#""#"到十六进制串中提取32位整数可能不是最好的解决方法

with GNAT.SHA1; 
with Interfaces; 
with Ada.Text_IO; use Ada.Text_IO; 
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; 
procedure SHA1_Demo is 
    C: GNAT.SHA1.Context; 
    package U32_IO is new Ada.Text_IO.Modular_IO(Interfaces.Unsigned_32); 
    use U32_IO; 
begin 
    GNAT.SHA1.Update(C, "hello"); 
    declare 
     SHA1: constant String := GNAT.SHA1.Digest(C); 
     H: array(0..4) of Interfaces.Unsigned_32; 
    begin 
     Put_Line("SHA1(""hello"") = " & GNAT.SHA1.Digest(C)); 
     for I in Integer range 0 .. 4 loop 
      H(I) := Interfaces.Unsigned_32'Value 
         ("16#" & SHA1(I*8+1 .. I*8+8) & "#"); 
      Put("H("); 
      Put(I, Width => 0); 
      Put(") = "); 
      Put(H(I), Base => 16); 
      New_Line; 
     end loop; 
    end; 
end SHA1_Demo; 

的输出是:

SHA1("hello") = aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d 
H(0) = 16#AAF4C61D# 
H(1) = 16#DCC5E8A2# 
H(2) = 16#DABEDE0F# 
H(3) = 16#3B482CD9# 
H(4) = 16#AEA9434D# 
+0

我认为这是正确的答案。我只是不满意GNAT将二进制数组转换为十六进制字符串,并在我的代码中再次转换回来。我下载了GPL许可的SHA1实现,它将摘要作为5x32位整数数组返回。 – Anthony 2012-01-15 12:20:47

+1

GNAT的实施是GPL;您可以重新命名并修改它以使“H”可见。您也可以考虑联系GNAT人员,并要求他们在将来的版本中使“H”可见。 – 2012-01-15 16:01:34

+0

GOOD的主意!我没有想到这一点。从来没有真正发生过,我们只能更改编译器库。 – Anthony 2012-01-15 23:09:59