将 32 位变量移位 32 位有什么不好?

发布于 2024-08-29 13:00:00 字数 779 浏览 2 评论 0原文

我最近买了一本 Bruce Schneier 写的《应用密码学》,读起来很不错。我现在了解了书中概述的几种算法是如何工作的,我想开始用 C 语言实现其中的一些算法。

许多算法的共同点是将一个 x 位密钥划分为几个较小的 y 位密钥位键。例如,Blowfish 的密钥 X 是 64 位,但您需要将其分成两半 32 位; Xl 和 Xr。

这就是我陷入困境的地方。我对C语言还算不错,但在位运算符之类的方面我并不是最强的。

在 IRC 上的一些帮助之后,我设法想出了这两个宏:

#define splitup(a, b, c) {b = a >> 32; c = a & 0xffffffff; }
#define combine(a, b, c) {a = (c << 32) | a;}

其中 a 是 64 位,b 和 c 是 32 位。但是,编译器警告我,我正在将 32 位变量移位 32 位。

我的问题是:

  • 将 32 位变量移位 32 位有什么不好?我猜它是未定义的,但这些宏似乎确实有效。
  • 另外,你会建议我用另一种方式解决这个问题吗?

正如我所说,我对C相当熟悉,但是位运算符之类的东西仍然让我头疼。

编辑

我发现我的组合宏实际上并不是组合两个32位变量,而是简单地将0与a进行或运算,并得到结果a。
因此,除了我之前的问题之外,我仍然没有一种方法将两个 32 位变量组合起来得到 64 位变量;如果有关于如何做的建议,我们将不胜感激。

I recently picked up a copy of Applied Cryptography by Bruce Schneier and it's been a good read. I now understand how several algorithms outlined in the book work, and I'd like to start implementing a few of them in C.

One thing that many of the algorithms have in common is dividing an x-bit key, into several smaller y-bit keys. For example, Blowfish's key, X, is 64-bits, but you are required to break it up into two 32-bit halves; Xl and Xr.

This is where I'm getting stuck. I'm fairly decent with C, but I'm not the strongest when it comes to bitwise operators and the like.

After some help on IRC, I managed to come up with these two macros:

#define splitup(a, b, c) {b = a >> 32; c = a & 0xffffffff; }
#define combine(a, b, c) {a = (c << 32) | a;}

Where a is 64 bits and b and c are 32 bits. However, the compiler warns me about the fact that I'm shifting a 32 bit variable by 32 bits.

My questions are these:

  • What's bad about shifting a 32-bit variable 32 bits? I'm guessing it's undefined, but these macros do seem to be working.
  • Also, would you suggest I go about this another way?

As I said, I'm fairly familiar with C, but bitwise operators and the like still give me a headache.

EDIT

I figured out that my combine macro wasn't actually combining two 32-bit variables, but simply ORing 0 by a, and getting a as a result.
So, on top of my previous questions, I still don't have a method of combining the two 32-bit variables to get a 64-bit one; a suggestion on how to do it would be appreciated.

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

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

发布评论

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

评论(5

东京女 2024-09-05 13:00:00

是的,这是未定义的行为。

ISO/IEC 9899:1999 6.5.7 位移运算符 ¶3

对每个操作数执行整数提升。结果的类型是提升后的左操作数的类型。如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

C11 aka ISO/IEC 9899:2011 也有同样的说法。

您应该首先将 b 转换为目标整数类型。另一点是,您应该在宏参数两边加上括号,以避免运算符优先级出现意外。此外,逗号运算符在这里非常有用,它可以让您避免使用大括号,从而可以将宏用作普通命令,并以分号结束。

#define splitup(a,b,c) ( (b) = (a) >> 32, (c) = (a) & 0xffffffff )
#define combine(a,b,c) ( (a) = ((unsigned long long)(b) << 32) | (c) )

`splitup 可能需要额外的转换来消除关于过度偏执的编译器造成的精度损失的警告。

#define splitup(a,b,c) ( (b) = (unsigned long)((a) >> 32), (c) = (unsigned long)((a) & 0xffffffff) )

并且请不要考虑将您自己编写的加密用于生产代码。

Yes, it is undefined behaviour.

ISO/IEC 9899:1999 6.5.7 Bitwise shift operators ¶3

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

C11 aka ISO/IEC 9899:2011 says the same.

You should first cast b to the target integer type. Another point is that you should put parentheses around the macro parameters to avoid surprises by operator precedences. Additionally, the comma operator is very useful here, allowing you to avoid the braces, so that the macro can be used as a normal command, closed with a semicolon.

#define splitup(a,b,c) ( (b) = (a) >> 32, (c) = (a) & 0xffffffff )
#define combine(a,b,c) ( (a) = ((unsigned long long)(b) << 32) | (c) )

Additional casts may be necessary for `splitup to silence warnings about precision loss by over-paranoid compilers.

#define splitup(a,b,c) ( (b) = (unsigned long)((a) >> 32), (c) = (unsigned long)((a) & 0xffffffff) )

And please don't even think about using your self-written encryption for production code.

愛上了 2024-09-05 13:00:00

在 C 和 C++ 中未定义将 32 位值移位 32 位或更多。未定义的原因之一是,在某些硬件平台上,32 位移位指令仅考虑所提供的移位计数的 5 个最低位。这意味着无论您传递多少移位计数,它都将被解释为模 32。尝试在此类平台上移位 32 实际上将移位 0,即根本不移位。

语言作者不想让为此类平台编写的编译器承担在进行移位之前分析移位计数的任务。相反,语言规范表明该行为是未定义的。这意味着,如果您想从 32 位移位 32(或更多)得到 0 值,则需要您了解情况并进行相应处理。

Shifting a 32-bit value by 32 bits or more is undefined in C and C++. One of the reasons it was left undefined is that on some hardware platforms the 32-bit shift instruction only takes into account 5 lowest bits of the supplied shift count. This means that whatever shift count you pass, it will be interpreted modulo 32. Attempting to shift by 32 on such platform will actually shift by 0, i.e. not shift at all.

The language authors did not want to burden the compilers written for such platform with the task of analyzing the shift count before doing the shift. Instead, the language specification says that the behavior is undefined. This means that if you want to get a 0 value from a 32-bit shift by 32 (or more), it is up to you to recognize the situation and process it accordingly.

悟红尘 2024-09-05 13:00:00

将 32 位变量移位 32 位有什么不好?

0 分配给 n 位整数比将其移位 n 位更好。

示例:

 0 0 1 0 1 ----- 5 bit Integer  
 0 1 0 1 0 ----- 1st shift  
 1 0 1 0 0 ----- 2nd shift  
 0 1 0 0 0 ----- 3rd shift  
 1 0 0 0 0 ----- 4th shift  
 0 0 0 0 0 ----- 5th shift (all the bits are shifted!)  

我仍然没有一种方法将两个 32 位变量组合起来得到一个 64 位变量

考虑: a 是 64 位,b 和 c 是 32 位

a = b;
a = a << 32; //Note: a is 64 bit
a = a | c;

what's bad about shifting a 32-bit variable 32 bits?

Its better to assign 0 to n-bit integer than to shift it by n-bits.

Example:

 0 0 1 0 1 ----- 5 bit Integer  
 0 1 0 1 0 ----- 1st shift  
 1 0 1 0 0 ----- 2nd shift  
 0 1 0 0 0 ----- 3rd shift  
 1 0 0 0 0 ----- 4th shift  
 0 0 0 0 0 ----- 5th shift (all the bits are shifted!)  

I still don't have a method of combining the two 32-bit variables to get a 64-bit one

Consider: a is 64 bit, b and c are 32 bit

a = b;
a = a << 32; //Note: a is 64 bit
a = a | c;
疏忽 2024-09-05 13:00:00

除非这是一些“重新发明轮子以了解其工作原理”的项目,否则不要实现自己的加密函数。

曾经。

使用可用的算法来工作(并选择正确的算法)已经足够困难了,不要因为将一些自制的加密 API 投入生产而搬起石头砸自己的脚。很可能您的加密不会加密

Unless this is some "reinventing the wheel to understand how it works" project, don't implement your own crypto functions.

Ever.

It's hard enough to use the available algorithms to work (and to choose the right one), don't shoot yourself in the foot by putting in production some home grown cryptor API. Chances are your encryption won't encrypt

尸血腥色 2024-09-05 13:00:00

将 32 位变量移位 32 位有什么不好?

除了已经说过的之外,第 32 位是符​​号位,您可能会进行符号扩展以保留符号,从而丢失重要位。

What's bad about shifting a 32-bit variable 32 bits?

In addition to what have been already said, the 32nd bit is the sign bit, and you may get sign extension to preserve the sing, thereby losing significant bits.

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