小端数据和sha 256

时间:2011-06-07 18:10:12

标签: endianness sha256

我必须以小端形式生成sha256数据哈希值。在使用sha 256算法之前,我想知道是否必须先将其转换为big endian。或者,如果算法是“与endian无关的”。

编辑:对不起,我想我不清楚。我想知道的是:sha256算法需要用某些位填充消息的结尾。第一步是在消息的末尾添加1。然后,用零填充它直到结束。最后,您必须以位为单位添加消息的长度。我想知道的是这个填充是否可以用小端进行。例如,对于640位消息,我可以将最后一个字写为0x280(大端)或0x8002000(小端)。这个填充可以用小端进行吗?

3 个答案:

答案 0 :(得分:6)

如果你想要的只是一个好的哈希,SHA256是与字节无关的。但是如果你正在编写SHA256并希望在正确实现时获得相同的结果,那么你必须在小端硬件上玩游戏。 SHA256结合了算术加法(mod 2 * 32)和布尔运算,因此在内部不与字节序无关。

答案 1 :(得分:2)

让我回答关于sha 256以及sha 512的问题。 简而言之: 算法本身是endian不可知的。字节序敏感部分是将数据从字节缓冲区导入算法工作变量时以及何时导出回摘要结果 - 也是字节缓冲区。如果导入/导出包括转换,则endian很重要。

铸造可能发生在哪里: 在sha 512中,有一个128字节的工作缓冲区。 在我的代码中,它的定义如下:

    union
    {
        U64   w [80]; (see U64 example below)
        byte  buffer [128];
    };

输入数据被复制到该字节缓冲区,然后在W上完成工作。这意味着数据被转换为某种64位类型。必须交换此数据。在我的情况下,它换成了小端机器。

更好的方法是准备一个get宏,它接受每个字节并将其放在u64类型的正确位置。

当算法完成时,摘要结果从工作变量输出到某个字节缓冲区,如果这是由memcpy完成的,那么它也必须被交换。

在32位计算机上实现sha 512(专为64位计算机设计)时,可能会发生另一次转换。在我的情况下,我有一个定义的64位类型:

    typedef struct {
        uint high;
        uint low;
    } U64;

假设我也为小端定义它,如下所示:

    typedef struct {
        uint low;
        uint high;
    } U64;

然后k算法init就像这样完成:

    static const SHA_U64 k[80] =  
    { 
        {0xD728AE22, 0x428A2F98}, {0x23EF65CD, 0x71374491}, ...
        ...
        ...
    }

但我需要k [0] .high的逻辑值才能在任何机器上都相同。 所以在这个例子中,我需要另一个k值数组,其中交换了高值和低值。

在将数据存储在工作参数中之后,任何按位操作在大/小端机器上都会产生相同的结果。

好的方法是避免任何演员: 使用宏将输入缓冲区中的字节导入工作参数。 使用逻辑值而不考虑内存映射。 使用宏将输出导出为摘要结果。

从字节缓冲区取32位到int32(BE =大端)的宏:

    #define GET_BE_BYTES_FROM32(a) 
    ((((NQ_UINT32) (a)[0]) << 24) | 
    (((NQ_UINT32) (a)[1]) << 16)  | 
    (((NQ_UINT32) (a)[2]) << 8)   | 
    ((NQ_UINT32) (a)[3])) 

    #define GET_LE_BYTES_FROM32(a) 
    ((((NQ_UINT32) (a)[3]) << 24) | 
    (((NQ_UINT32) (a)[2]) << 16)  | 
    (((NQ_UINT32) (a)[1]) << 8)   | 
    ((NQ_UINT32) (a)[0])) 

答案 2 :(得分:1)

SHA-256实现本身应该处理填充 - 除非你实现自己专门的SHA-256代码,否则你不应该处理它。如果是,请注意“预处理步骤”中指定的填充规则表示长度是64位大端整数。见SHA-2 - Wikipedia

甚至很难弄清楚“endian-anostic”意味着什么,但是哈希算法的所有位,字节和单词的顺序都很重要,所以我肯定不会使用那个术语。