与c++中的字节、块、en-/解码混淆

confused with bytes, blocks, en-/decoding in c++

本文关键字:解码 en- 字节 c++      更新时间:2023-10-16

我有一个64字节的块,希望在末尾附加一个64位(8字节)的数据块。

typedef unsigned char uint1; // 1 Byte
typedef unsigned int uint4; // 4 Byte
// The 64 Byte-Block:
int BLOCKSIZE=64;
static uint1 padding[BLOCKSIZE] = {
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
// [[10000000][00000000].........[00000000]]

// The 64 Bit (8 Byte-Block):
uint4 appendix[2] = {};
appendix[1] = 0x000000ff;
// [[00000000000000000000000000000000][00000000000000000000000011111111]]

从附录到填充的最后8字节的memcpy 8字节之后

memcpy(&padding[56], &appendix, 8);

看起来像

static uint1 padding[BLOCKSIZE] = {
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0
    };

但它不应该是这样的吗?

static uint1 padding[BLOCKSIZE] = {
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
           0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff
    };

我不知道这里怎么了!?!?

你能帮我吗?

appendix[1] = 0x000000ff;
// [[00000000000000000000000000000000][00000000000000000000000011111111]]

您正在对字节顺序(endianness)进行假设。你不能做出这样的假设。根据体系结构的字节顺序,appendix也可以这样表示:

// [[00000000000000000000000000000000][11111111000000000000000000000000]]

如果要专门设置最后一个字节,则需要对字节进行操作,而不是对多字节整数进行操作。例如:

uint1 appendix[8] = {};
appendix[7] = 0xff;

如果您确实需要最后8个字节来表示两个4字节整数,那么您的代码在这方面是正确的,只有您对内存应该是什么样子的假设是错误的。

若要通过网络发送该整数,该整数必须按照特定的字节顺序,那个么您必须对其进行适当的转换。POSIX提供了htonl及其姊妹函数。这些功能也由msvc提供。

您还假设unsigned int是4个字节。不能保证是。如果需要4字节的整数,请使用int32_t

更新:

我的目标是实现MD5,我需要附加一个文件长度的64位表示。

根据rfc1321:

一系列字节可以解释为32位字的序列,其中四个字节的连续组被解释为具有首先给出的低阶(最低有效)字节。

MD5是小端序。因此,在不转换字节顺序的情况下写入2*4数组只能在小端序处理器上正常工作。

我建议使用8*1字节数组,这样您就可以完全按照规范要求控制字节的顺序。或者,如果您在linux或其他提供它们的平台上,则可以使用htole32le32toh函数转换为正确的字节顺序。在另一个平台上,您可能需要自己实现它们。

因此,就我所能理解的RFC1321而言,我需要原始消息(文件)大小的64位整数表示。文件大小为64字节。在64位整数中,值64是二进制的:

0000000000000000000000000000000000000000000000000000000001000000

或:

0000001000000000000000000000000000000000000000000000000000000000

我对两者都有解码功能,但我不知道哪一个对md5正确?

您应该看看Endianless。你的选择是big-endian。