半咬合移位
我正在研究一种加密算法,我想知道如何将以下代码更改为更简单的代码以及如何反转该代码。
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您将每个字节的两个半字节设置为相同的值,因为您最终将高半字节设置为与低半字节相同。我假设这是一个错误,并且您的意图是移动数据中的所有半字节,从一个字节传送到另一个字节,然后滚动。 Id est,ABCDEF(半字节顺序从低到高)将变为 FABCDE。如果我错了,请纠正我。
代码应该是这样的:
现在一切都好吗?不会。只有当
nibbles
的对齐方式不比char
的对齐方式更严格时,才可以明确定义到nibbles*
的转换。并且无法保证(但是,使用小改动,GCC 生成具有相同对齐方式的类型)。就我个人而言,我会完全避免这个问题。我会这样做:
做相反的事情相当于将“低”更改为“高”,反之亦然;滚动到最后一口,而不是第一口;并以相反的方向遍历数据:
如果您愿意,您可以删除所有到临时
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:
Is everything okay now? No. The cast to
nibbles*
is only well-defined if the alignment ofnibbles
is not stricter than the alignment ofchar
. 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:
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:
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:看起来您只是将每个半字节移动一个位置,然后取出最后一个字节的低半字节并将其移动到开头。只需执行相反的操作即可解密(从
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)当您使用位字段时,不太可能有移位样式的方法来移动半字节。如果这种移位对您很重要,那么我建议您考虑将它们存储在某种无符号整数中。在这种形式下,可以有效地执行位运算。
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.
凯文的答案在您尝试做的事情中是正确的。然而,你犯了一个低级错误。最终结果是整个数组都充满了零,而不是旋转的半字节。
要了解为什么会出现这种情况,我建议您首先以相同的方式实现字节旋转 (
{a, b, c} -> {c, a, b}
) - 即通过使用循环计数器从 0 增加到数组大小。看看是否可以通过减少对变量last
的传输来做得更好。一旦您了解了如何做到这一点,您就可以简单地将相同的逻辑应用于半字节 (
{al:ah, bl:bh, cl:ch} -> {ch:al, ah:bl, bh:cl }
)。如果您以十六进制值的形式思考,我在这里的表示是不正确的。在我的符号中,十六进制值0xXY
是Y: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 variablelast
.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 value0xXY
isY: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 intolast
.反转代码是不可能的,因为该算法完全删除了第一个字节并丢弃了其余字节的下半部分。
在 for 循环的第一次迭代中,第一个字节的下部设置为零。
它从未在任何地方保存过。它就这么消失了。
扭转它:
...除非我把高点和低点颠倒过来。
但无论如何,这与加密领域相差甚远。这充其量只是混淆视听。通过默默无闻来实现安全是一种可怕的做法,自制加密会给人们带来麻烦。如果你在玩耍,你的力量就会更大。但如果您确实希望某些东西是安全的,请出于对所有字节的热爱而使用众所周知的安全加密方案。
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.
It's never saved off anywhere. It's simply gone.
To reverse it:
... 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.