小端数据和 sha 256

发布于 11-14 11:19 字数 275 浏览 5 评论 0原文

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

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

I have to generate sha256 hashes of data that is in little endian form. I would like to know if I have to convert it to big endian first, before using the sha 256 algorithm. Or if, the algorithm is "endian-agnostic".

EDIT: Sorry, I think I wasnt clear. What I would like to know is the following: The sha256 algorithm requires to pad the end of a message with certain bits. The first step is to add a 1 at the end of the message. Then, to pad it with zero up to the end. At the very end, you must add the length of the message in bits. What I would like to know is if this padding can be performed in little endian. For example, for a 640 bit message, I could write the last word as 0x280 (in big endian), or 0x8002000 (in little endian). Can this padding be done in little endian?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

等待圉鍢2024-11-21 11:19:25

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

SHA256 is endian-agnostic if all you want is a good hash. But if you are writing SHA256 and want to the same results with a correct implementation then you must play games on little endian hardware. SHA256 combines arithmetic addition (mod 2*32) and boolean operation thus is not endian-agnostic internally.

他夏了夏天2024-11-21 11:19:25

SHA-256 实现本身应该负责填充 - 除非您正在实现自己的专用 SHA-256 代码,否则您不必处理这个问题。如果是,请注意“预处理步骤”中指定的填充规则表示长度是 64 位大端整数。请参阅 SHA-2 - 维基百科

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

The SHA-256 implementation itself should take care of padding - you shouldn't have to deal with that unless you're implementing your own specialized SHA-256 code. If you are, note that the padding rules specified in the "pre-processing step" say that the length is a 64-bit big-endian integer. See SHA-2 - Wikipedia

It's hard to even figure out what "endian-agnostic" would mean, but the order of all the bits, bytes and words for a hash algorithm matter a whole lot, so I sure wouldn't use that term.

偏爱你一生2024-11-21 11:19:25

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

铸造可能发生在哪里:
在 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 算法初始化是这样完成的:

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

Let me reply regarding sha 256 as well as sha 512.
in short:
The algorithm itself is endian agnostic. The endian sensitive parts are when data is imported from a byte buffer to the algorithm working variables and when it is exported back to the digest result - also a byte buffer. If the import / export include casting, then endian matters.

Where could casting occur:
In sha 512 there is a working buffer of 128 bytes.
In my code its defined like this:

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

Input data is copied to this byte buffer and then work is done on W. This means the data was casted to some 64 bit type. This data will have to be swapped. in my case its swapped for little endian machines.

A better method would be to prepare a get macro that takes each byte and places it in its correct place in the u64 type.

When the algorithm is done the digest result is output from the working variables to some byte buffer, if this is done by memcpy it will also have to be swapped.

Another casting could occur when implementing sha 512 - which is designed for 64 bit machines - on 32 bit machines. In my case I have a 64 bit type that is defined:

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

Assume I define it for little endian as well, as follows:

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

And then the k algorithm init is done like this:

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

But i need the logic value of k[0].high to be the same in any machine.
So in this example I will need another k array with high and low values swapped.

After the data is stored in the working parameters any bitwise manipulation would have the same result on both big/little endian machines.

Good method would be to avoid any casting:
Import bytes from input buffer to your working parameters using macro.
Work with logical values without thinking about the memory mapping.
Export output to digest result with a macro.

Macro for taking 32 bits from a byte buffer to 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])) 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文