处理具有不同密钥大小和字节顺序的异或

发布于 2024-11-17 18:21:38 字数 1350 浏览 13 评论 0原文

我正在通过一个小 C 文件进行异或解码,并且遇到了字节序问题......我对如何解决它们有点困惑。这确实是我第一次在 C 语言中深入研究按位运算。

如果我使用单字节异或键并将多个异或编码值放入 uint8_t 指针中,我的基本代码就可以正常工作。遍历每个字节,将其与密钥进行异或,并将结果存储在解码的字节数组/缓冲区中,然后将其打印回控制台。

但是,如果我尝试使用两字节异或密钥,那么字节序就会开始出现问题。我目前将密钥粘贴到 uint32_t 中,因为我不打算处理大于 32 位的异或密钥。在小端系统上,0xc39f 的异或密钥存储为 0x9fc3。如果我一次播放一个字节,要解码的字节是大端字节序,但如果我尝试一次播放两个字节(与异或键大小相同),它们也会翻转为小端字节序)。

我很想#include,然后调用bswap_32()。但是,虽然这对小端有效,但对大端可能会产生相反的效果。我假设我需要丑陋的 #ifdef 来仅将 bswap_32() 用于小端架构。我想,必须有一种更便携的方式才能实现这一点。

随机样本字符串:

g   e   n   e   r   a   t   e
67  65  6e  65  72  61  74  65

Xor 0xc39f

a4  fa  ad  fa  b1  fe  b7  fa


如果我用两字节(uint16_t)指针回放异或编码的缓冲区,我会得到这个(通过基本的 printf):

0xfaa4 0xfaad 0xfeb1 0xfab7


并且用四字节指针(uint32_t):

0xfaadfaa4 0xfab7feb1



我希望上述内容能够得到两字节指针:

0xa4fa 0xadfa 0xb1fe 0xb7fa

和四字节指针:

0xa4faadfa 0xb1feb7fa


想法?



编辑:有人接受吗?当前的答案不足以满足我的需求。

I am playing around with xor decoding via a small C file, and am running into issues with endianness ...I am a bit stuck on how to work around them. This is really the first time I've played this deeply with bitwise operations in C.

If I use a one-byte xor key and pick up several xor-encoded values into a uint8_t pointer, my basic code works fine. Walk each byte, xor it against the key, and store the result in a decoded byte array/buffer and then print it back to the console.

However, if I try a two-byte xor key, then endianness starts to get in the way. I currently stick the key into a uint32_t, because I don't plan on dealing with xor keys greater than 32bits. On a little-endian system, a xor key of 0xc39f gets stored as 0x9fc3. The bytes to be decoded are big-endian if I play them back one byte at a time, but they too, get flipped to little-endian if I try to play them back two-bytes at a time (same size as the xor key).

I am tempted to #include <byteswap.h> and then call bswap_32(). But while this will work on little endian, it might have the opposite effect on big-endian. I assume then I'd need ugly #ifdef's to only use bswap_32() for little-endian archs. I figure, there has got to be a more portable way for this to work.

Random sample string:

g   e   n   e   r   a   t   e
67  65  6e  65  72  61  74  65

Xor 0xc39f

a4  fa  ad  fa  b1  fe  b7  fa

If I play back the xor-encoded buffer with two-byte (uint16_t) pointers, I get this (via a basic printf):

0xfaa4 0xfaad 0xfeb1 0xfab7

And with four-byte pointers (uint32_t):

0xfaadfaa4 0xfab7feb1

I would expect for the above, to get instead for two-byte pointers:

0xa4fa 0xadfa 0xb1fe 0xb7fa

And four-byte pointers:

0xa4faadfa 0xb1feb7fa

Thoughts?

Edit: Any takers? Current answers aren't adequate to my needs.

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

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

发布评论

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

评论(2

樱花落人离去 2024-11-24 18:21:38

您想得太多了 - 只需将您的异或密钥视为无字节序的二进制 blob,并将其转换为本机 uint32_t 以提高性能:

void xor_encrypt_slow(uint8_t *data, size_t len, uint8_t key[4])
{
    // key is a 4-byte xor key
    size_t i;
    for(i = 0; i < len; i++)
        data[i] ^= key[i % 4];
}

void xor_encrypt_fast(uint8_t *data, size_t len, uint8_t key[4])
{
    // Convert key to a 32-bit value
    uint32_t key32 = *(uint32_t *)key;

    // This assumes that data is aligned on a 4-byte boundary; if not, adjust
    // accordingly
    size_t i;
    for(i = 0; i + 3 < len; i += 4)
        ((uint32_t *)data)[i] ^= key32;
    // Handle the remainder, if len is not a multiple of 4
    for( ; i < len; i++)
        data[i] ^= key[i % 4];
}

You're overthinking this—just treat your xor key as an endianless binary blob, and convert it to a native uint32_t for performance:

void xor_encrypt_slow(uint8_t *data, size_t len, uint8_t key[4])
{
    // key is a 4-byte xor key
    size_t i;
    for(i = 0; i < len; i++)
        data[i] ^= key[i % 4];
}

void xor_encrypt_fast(uint8_t *data, size_t len, uint8_t key[4])
{
    // Convert key to a 32-bit value
    uint32_t key32 = *(uint32_t *)key;

    // This assumes that data is aligned on a 4-byte boundary; if not, adjust
    // accordingly
    size_t i;
    for(i = 0; i + 3 < len; i += 4)
        ((uint32_t *)data)[i] ^= key32;
    // Handle the remainder, if len is not a multiple of 4
    for( ; i < len; i++)
        data[i] ^= key[i % 4];
}
你的往事 2024-11-24 18:21:38

尝试使用 htonl() 宏,它正是为此目的而设计的。它代表“十六进制到网络长”,并被定义为交换(或不交换)字节以使结果值成为大端字节序,根据需要在通过网络传输它们之前。

Try using the htonl() macro, which is designed exactly for this purpose. It stands for "hex to network long" and is defined to swap (or not swap) bytes to make the resulting values big-endian, as required before transmitting them over the network.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文