小端数据和sha 256

7

我需要生成小端格式数据的sha256哈希值。我想知道在使用sha256算法之前是否需要将其转换为大端格式,或者该算法是否是“字节序不可知”的。

编辑:抱歉,我认为我没有表达清楚。我想知道的是以下内容:sha256算法要求使用某些位填充消息的末尾。第一步是在消息末尾添加1。然后,用零填充到末尾。最后,必须添加消息长度(以位为单位)。我想知道的是这个填充是否可以以小端方式执行。例如,对于一个640位的消息,我可以将最后一个字写成0x280(大端)或0x8002000(小端)。这个填充可以以小端方式完成吗?


1
这很棘手...虽然通常情况下,SHA不关心字节序。对于哈希来说,任何输入都是二进制“blob”的512位块的倍数(如果需要,它会添加填充)。因此,字节序是无关紧要的。另一方面,如果您例如有一个struct,一次是小端,一次是大端,并且您对它们进行哈希处理,它们当然会产生不同的哈希值。但这是因为它们是不同的二进制数据,而不是哈希关心的原因。 - Damon
3个回答

8

如果您只想得到一个好的哈希值,那么SHA256与大小端无关。但是,如果您需要编写SHA256并希望使用正确的实现获得相同的结果,则必须在小端硬件上进行操作。SHA256结合了算术加法(模2 * 32)和布尔运算,因此内部不是大小端无关的。


2

SHA-256的实现本身应该处理填充 - 除非您正在实现自己专门的SHA-256代码,否则不必处理填充。如果您正在这样做,请注意“预处理步骤”中指定的填充规则,其中长度是一个64位大端整数。请参见SHA-2 - Wikipedia

甚至很难确定“endian-agnostic”是什么意思,但哈希算法的所有位、字节和字的顺序都非常重要,因此我肯定不会使用这个术语。


2
让我来回复关于sha 256和sha 512的问题。 简单来说: 算法本身不受大小端影响。大小端敏感的部分是从字节缓冲区导入数据到算法工作变量以及将其导出回摘要结果 - 这也是一个字节缓冲区。如果导入/导出包括强制转换,则大小端很重要。
强制转换可能发生在哪里: 在sha 512中,有一个128字节的工作缓冲区。 在我的代码中,它被定义为:
    union
    {
        U64   w [80]; (see U64 example below)
        byte  buffer [128];
    };

输入数据被复制到此字节缓冲区,然后在W上进行处理。这意味着数据已转换为某种64位类型。此数据将需要交换。在我的情况下,它被交换为小端机器。

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

当算法完成时,摘要结果从工作变量输出到某些字节缓冲区,如果使用memcpy完成,则还必须进行交换。

在32位机器上实现面向64位机器的sha 512时,可能会发生另一种转换。在我的情况下,定义了一个64位类型。

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

假设我也为小端定义了它,如下所示:
    typedef struct {
        uint low;
        uint high;
    } U64;

然后 k 算法的初始化步骤如下:

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

但是我需要k [0] .high的逻辑值在任何机器上都相同。因此,在这个例子中,我将需要另一个具有高位和低位值交换的k数组。
在数据存储在工作参数中之后,任何位操作都会在大/小端机器上产生相同的结果。
一个好的方法是避免任何强制转换:使用宏从输入缓冲区导入字节到您的工作参数。使用逻辑值处理而不考虑内存映射。使用宏将输出导出到摘要结果。
从字节缓冲区取32位到int32的宏(BE = big endian):
    #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])) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接