半咬合移位

发布于 2024-12-06 07:05:31 字数 489 浏览 1 评论 0原文

我正在研究一种加密算法,我想知道如何将以下代码更改为更简单的代码以及如何反转该代码。

typedef struct 
{
    unsigned low : 4;
    unsigned high : 4;
} nibles;

static void crypt_enc(char *data, int size)
{
    char last = 0;

    //...

    // Pass 2
    for (i = 0; i < size; i++)
    {
        nibles *n = (nibles *)&data[i];

        n->low = last;
        last = n->high;
        n->high = n->low;
    }
    ((nibles *)&data[0])->low = last;
}

data 是此代码的输入和输出。

I was working on an encryption algorithm and I wonder how I can change the following code into something simpler and how to reverse this code.

typedef struct 
{
    unsigned low : 4;
    unsigned high : 4;
} nibles;

static void crypt_enc(char *data, int size)
{
    char last = 0;

    //...

    // Pass 2
    for (i = 0; i < size; i++)
    {
        nibles *n = (nibles *)&data[i];

        n->low = last;
        last = n->high;
        n->high = n->low;
    }
    ((nibles *)&data[0])->low = last;
}

data is the input and the output for this code.

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

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

发布评论

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

评论(5

寂寞清仓 2024-12-13 07:05:31

您将每个字节的两个半字节设置为相同的值,因为您最终将高半字节设置为与低半字节相同。我假设这是一个错误,并且您的意图是移动数据中的所有半字节,从一个字节传送到另一个字节,然后滚动。 Id est,ABCDEF(半字节顺序从低到高)将变为 FABCDE。如果我错了,请纠正我。

代码应该是这样的:

static void crypt_enc(char *data, int size)
{
    char last = 0;

    //...

    // Pass 2
    for (i = 0; i < size; i++)
    {
        nibles *n = (nibles *)&data[i];

        unsigned char old_low = n->low;
        n->low = last;
        last = n->high;
        n->high = old_low;
    }
    ((nibles *)&data[0])->low = last;
}

现在一切都好吗?不会。只有当 nibbles 的对齐方式不比 char 的对齐方式更严格时,才可以明确定义到 nibbles* 的转换。并且无法保证(但是,使用小改动,GCC 生成具有相同对齐方式的类型)。

就我个人而言,我会完全避免这个问题。我会这样做:

void set_low_nibble(char& c, unsigned char nibble) {
    // assumes nibble has no bits set in the four higher bits)
    unsigned char& b = reinterpret_cast<unsigned char&>(c);
    b = (b & 0xF0) | nibble;
}

void set_high_nibble(char& c, unsigned char nibble) {
    unsigned char& b = reinterpret_cast<unsigned char&>(c);
    b = (b & 0x0F) | (nibble << 4);
}

unsigned char get_low_nibble(unsigned char c) {
    return c & 0x0F;
}

unsigned char get_high_nibble(unsigned char c) {
    return (c & 0xF0) >> 4;
}

static void crypt_enc(char *data, int size)
{
    char last;

    //...

    // Pass 2
    for (i = 0; i < size; ++i)
    {
        unsigned char old_low = get_low_nibble(data[i]);
        set_low_nibble(data[i], last);
        last = get_high_nibble(data[i]);
        set_high_nibble(data[i], old_low);
    }
    set_low_nibble(data[0], last);
}

做相反的事情相当于将“低”更改为“高”,反之亦然;滚动到最后一口,而不是第一口;并以相反的方向遍历数据:

for (i = size-1; i >= 0; --i)
{
    unsigned char old_high = get_high_nibble(data[i]);
    set_high_nibble(data[i], last);
    last = get_low_nibble(data[i]);
    set_low_nibble(data[i], old_high);
}
set_high_nibble(data[size-1], last);

如果您愿意,您可以删除所有到临时 last 的传输。您只需要保存最后一个半字节,然后直接移动半字节,而不使用另一个变量:

last = get_high_nibble(data[size-1]);
for (i = size-1; i > 0; --i) // the last one needs special care
{
    set_high_nibble(data[i], get_low_nibble(data[i]));
    set_low_nibble(data[i], get_high_nibble(data[i-1]));
}
set_high_nibble(data[0], get_low_nibble(data[0]));
set_low_nibble(data[0], last);

You are setting both nibbles of every byte to the same thing, because you set the high nibble to the same as the low nibble in the end. I'll assume this is a bug and that your intention was to shift all the nibbles in the data, carrying from one byte to the other, and rolling around. Id est, ABCDEF (nibbles order from low to high) would become FABCDE. Please correct me if I got that wrong.

The code should be something like:

static void crypt_enc(char *data, int size)
{
    char last = 0;

    //...

    // Pass 2
    for (i = 0; i < size; i++)
    {
        nibles *n = (nibles *)&data[i];

        unsigned char old_low = n->low;
        n->low = last;
        last = n->high;
        n->high = old_low;
    }
    ((nibles *)&data[0])->low = last;
}

Is everything okay now? No. The cast to nibbles* is only well-defined if the alignment of nibbles is not stricter than the alignment of char. And that is not guaranteed (however, with a small change, GCC generates a type with the same alignment).

Personally, I'd avoid this issue altogether. Here's how I'd do it:

void set_low_nibble(char& c, unsigned char nibble) {
    // assumes nibble has no bits set in the four higher bits)
    unsigned char& b = reinterpret_cast<unsigned char&>(c);
    b = (b & 0xF0) | nibble;
}

void set_high_nibble(char& c, unsigned char nibble) {
    unsigned char& b = reinterpret_cast<unsigned char&>(c);
    b = (b & 0x0F) | (nibble << 4);
}

unsigned char get_low_nibble(unsigned char c) {
    return c & 0x0F;
}

unsigned char get_high_nibble(unsigned char c) {
    return (c & 0xF0) >> 4;
}

static void crypt_enc(char *data, int size)
{
    char last;

    //...

    // Pass 2
    for (i = 0; i < size; ++i)
    {
        unsigned char old_low = get_low_nibble(data[i]);
        set_low_nibble(data[i], last);
        last = get_high_nibble(data[i]);
        set_high_nibble(data[i], old_low);
    }
    set_low_nibble(data[0], last);
}

Doing the reverse amounts to changing "low" to "high" and vice-versa; rolling to the last nibble, not the first; and going through the data in the opposite direction:

for (i = size-1; i >= 0; --i)
{
    unsigned char old_high = get_high_nibble(data[i]);
    set_high_nibble(data[i], last);
    last = get_low_nibble(data[i]);
    set_low_nibble(data[i], old_high);
}
set_high_nibble(data[size-1], last);

If you want you can get rid of all the transfers to the temporary last. You just need to save the last nibble of all, and then shift the nibbles directly without the use of another variable:

last = get_high_nibble(data[size-1]);
for (i = size-1; i > 0; --i) // the last one needs special care
{
    set_high_nibble(data[i], get_low_nibble(data[i]));
    set_low_nibble(data[i], get_high_nibble(data[i-1]));
}
set_high_nibble(data[0], get_low_nibble(data[0]));
set_low_nibble(data[0], last);
笑咖 2024-12-13 07:05:31

看起来您只是将每个半字节移动一个位置,然后取出最后一个字节的低半字节并将其移动到开头。只需执行相反的操作即可解密(从data末尾开始,移至开头)

It looks like you're just shifting each nibble one place and then taking the low nibble of the last byte and moving it to the beginning. Just do the reverse to decrypt (start at the end of data, move to the beginning)

一身骄傲 2024-12-13 07:05:31

当您使用位字段时,不太可能有移位样式的方法来移动半字节。如果这种移位对您很重要,那么我建议您考虑将它们存储在某种无符号整数中。在这种形式下,可以有效地执行位运算。

As you are using bit fields, it is very unlikely that there will be a shift style method to move nibbles around. If this shifting is important to you, then I recommend you consider storing them in an unsigned integer of some sort. In that form, bit operations can be performed effectively.

秋叶绚丽 2024-12-13 07:05:31

凯文的答案在您尝试做的事情中是正确的。然而,你犯了一个低级错误。最终结果是整个数组都充满了零,而不是旋转的半字节。

要了解为什么会出现这种情况,我建议您首先以相同的方式实现字节旋转 ({a, b, c} -> {c, a, b}) - 即通过使用循环计数器从 0 增加到数组大小。看看是否可以通过减少对变量 last 的传输来做得更好。

一旦您了解了如何做到这一点,您就可以简单地将相同的逻辑应用于半字节 ({al:ah, bl:bh, cl:ch} -> {ch:al, ah:bl, bh:cl })。如果您以十六进制值的形式思考,我在这里的表示是不正确的。在我的符号中,十六进制值 0xXYY:X。如果您考虑如何完成字节旋转,您可以弄清楚如何仅保存一个半字节,并简单地传输半字节而不实际将它们移至最后

Kevin's answer is right in what you are attempting to do. However, you've made an elementary mistake. The end result is that your whole array is filled with zeros instead of rotating nibbles.

To see why that is the case, I'd suggest you first implement a byte rotation ({a, b, c} -> {c, a, b}) the same way - which is by using a loop counter increasing from 0 to array size. See if you can do better by reducing transfers into the variable last.

Once you see how you can do that, you can simply apply the same logic to nibbles ({al:ah, bl:bh, cl:ch} -> {ch:al, ah:bl, bh:cl}). My representation here is incorrect if you think in terms of hex values. The hex value 0xXY is Y:X in my notation. If you think about how you've done the byte rotation, you can figure out how to save only one nibble, and simply transfer nibbles without actually moving them into last.

望笑 2024-12-13 07:05:31

反转代码是不可能的,因为该算法完全删除了第一个字节并丢弃了其余字节的下半部分。

在 for 循环的第一次迭代中,第一个字节的下部设置为零。

n->low = last;

它从未在任何地方保存过。它就这么消失了。

// I think this is what you were trying for
last = ((nibbles *)&data[0])->low;
for (i = 0; i < size-1; i++)
{
    nibbles *n = (nibbles *)&data[i];
    nibbles *next = (nibbles *)&data[i+1];
    n->low = n->high;
    n->high = next->low;
}
((nibbles *)&data[size-1])->high = last;

扭转它:

last = ((nibbles *)&data[size-1])->high;
for (i = size-1; i > 0; i--)
{
    nibbles *n = (nibbles *)&data[i];
    nibbles *prev = (nibbles *)&data[i-1];
    n->high = n->low;
    n->low = prev->high;
}
((nibbles *)&data[0])->low = last;

...除非我把高点和低点颠倒过来。

但无论如何,这与加密领域相差甚远。这充其量只是混淆视听。通过默默无闻来实现安全是一种可怕的做法,自制加密会给人们带来麻烦。如果你在玩耍,你的力量就会更大。但如果您确实希望某些东西是安全的,请出于对所有字节的热爱而使用众所周知的安全加密方案。

Reversing the code is impossible as the algorithm nukes the first byte entirely and discards the lower half of the rest.

On the first iteration of the for loop, the lower part of the first byte is set to zero.

n->low = last;

It's never saved off anywhere. It's simply gone.

// I think this is what you were trying for
last = ((nibbles *)&data[0])->low;
for (i = 0; i < size-1; i++)
{
    nibbles *n = (nibbles *)&data[i];
    nibbles *next = (nibbles *)&data[i+1];
    n->low = n->high;
    n->high = next->low;
}
((nibbles *)&data[size-1])->high = last;

To reverse it:

last = ((nibbles *)&data[size-1])->high;
for (i = size-1; i > 0; i--)
{
    nibbles *n = (nibbles *)&data[i];
    nibbles *prev = (nibbles *)&data[i-1];
    n->high = n->low;
    n->low = prev->high;
}
((nibbles *)&data[0])->low = last;

... unless I got high and low backwards.

But anyway, this is NOWHERE near the field of encryption. This is obfuscation at best. Security through obscurity is a terrible terrible practice and home-brew encryption get's people in trouble. If you're playing around, all the more power to you. But if you actually want something to be secure, please for the love of all your bytes use a well known and secure encryption scheme.

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