【问题标题】:Little endian data and sha 256小端数据和 sha 256
【发布时间】:2011-06-07 18:10:12
【问题描述】:

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

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

【问题讨论】:

  • 这很棘手......虽然一般来说,SHA 并不关心字节顺序。对于散列,任何输入都是 512 位二进制“blob”块的倍数(如有必要,它将添加填充)。就目前而言,字节顺序是微不足道的。另一方面,如果你有一个struct,一次是小端,一次是大端,并且你对它们进行哈希处理,它们当然会产生不同的哈希值。但那是因为它们是不同的二进制数据,而不是因为哈希值很重要。

标签: endianness sha256


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    让我回复一下关于 sha 256 和 sha 512 的问题。 简而言之: 该算法本身与字节序无关。字节序敏感部分是数据从字节缓冲区导入算法工作变量以及将其导出回摘要结果时 - 也是字节缓冲区。如果导入/导出包括强制转换,那么字节序很重要。

    可能在哪里进行强制转换: 在 sha 512 中有一个 128 字节的工作缓冲区。 在我的代码中,它的定义如下:

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

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

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

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

    在 32 位计算机上实施 sha 512(专为 64 位计算机设计)时,可能会发生另一种转换。就我而言,我定义了一个 64 位类型:

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

    假设我也为little endian定义了它,如下:

        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])) 
    

    【讨论】:

      【解决方案3】:

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

      甚至很难弄清楚“与字节序无关”是什么意思,但是哈希算法的所有位、字节和字的顺序非常重要,所以我肯定不会使用这个术语。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-09
        • 2012-08-07
        • 2021-11-27
        • 2022-07-04
        • 1970-01-01
        • 2021-01-22
        • 2013-06-03
        • 2014-08-19
        相关资源
        最近更新 更多