Что плохо о смещении 32-разрядных переменных 32 битов?

Я недавно забрал копию Прикладной Криптографии Bruce Schneier, и это было хорошее чтение. Я теперь понимаю, как несколько алгоритмов обрисовали в общих чертах в книжной работе, и я хотел бы начать реализовывать несколько из них в C.

Одна вещь, которую имеют общего многие алгоритмы, делит x-bit ключ в несколько меньших y-bit ключей. Например, ключ Шифров, 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;}

Где 64 бита и b, и c составляют 32 бита. Однако компилятор предупреждает меня о том, что я смещаю переменную на 32 бита на 32 бита.

Мои вопросы - они:

  • Что плохо о смещении 32-разрядных переменных 32 битов? Я предполагаю, что это не определено, но они макросы, действительно кажется, работают.
  • Кроме того, Вы предложили бы, чтобы я пошел об этом иначе?

Как я сказал, я довольно знаком с C, но побитовые операторы и т.п. все еще дают мне головную боль.

Править

Я выяснил, что мой макрос объединения на самом деле не комбинировал две 32-разрядных переменные, но просто осуществление операции ИЛИ 0 a, и добирался в результате.
Так, сверх моих предыдущих вопросов у меня все еще нет метода объединения двух 32-разрядных переменных для получения 64-разрядной; предложение о том, как сделать это, ценилось бы.

20
задан Jonathan Leffler 5 September 2015 в 22:11
поделиться

4 ответа

Да, это неопределенное поведение.

ISO / IEC 9899: 1999 6.5.7 Операторы побитового сдвига ¶3

Целочисленные повышения выполняются для каждого из операндов. Тип результата - это тип продвинутого левого операнда. Если значение правого операнда отрицательное или больше или равно ширине выдвинутого левого операнда, поведение не определено.

C11, также известный как 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) )

И, пожалуйста, даже не думайте об использовании собственного шифрования для производственного кода.

22
ответ дан 30 November 2019 в 00:00
поделиться

Если это не проект «изобретать колесо, чтобы понять, как оно работает», не надо • реализовать свои собственные криптографические функции.

Когда-либо.

Достаточно сложно использовать доступные алгоритмы для работы (и выбрать правильный), не стреляйте себе в ногу, запустив в производство какой-нибудь самодельный криптографический API. Скорее всего ваше шифрование не зашифрует

0
ответ дан 30 November 2019 в 00:00
поделиться

Сдвиг 32-битного значения на 32 бит или более не определен в C и C ++. Одна из причин, по которой он был оставлен неопределенным, заключается в том, что на некоторых аппаратных платформах 32-битная инструкция сдвига учитывает только 5 младших битов предоставленного счетчика сдвига. Это означает, что какой бы счетчик сдвига вы ни прошли, он будет интерпретироваться по модулю 32.Попытка переключиться на 32 на такой платформе фактически приведет к сдвигу на 0, то есть вообще не сдвинется.

Авторы языка не хотели обременять компиляторы, написанные для такой платформы, задачей анализа количества сдвигов перед выполнением сдвига. Вместо этого в спецификации языка сказано, что поведение не определено. Это означает, что если вы хотите получить значение 0 из 32-битного сдвига на 32 (или более), вы должны распознать ситуацию и обработать ее соответствующим образом.

13
ответ дан 30 November 2019 в 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;
3
ответ дан 30 November 2019 в 00:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: