Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> переполнение int 
V
    Опции темы
ReFLeXive
Дата 1.3.2011, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 30.3.2009
Где: г. Уфа

Репутация: нет
Всего: 1



Здраввствуйте!
Задали лабу - реализовать алгоритм шифрования ГОСТ28147. Прочитал ГОСТ, нашел готовую библиотеку (BouncyCastle), просмотрел, понял как и что работает, пересчитал все шаги ручками, чтобы понять как что и куда и начал писать сам. ВСе реализовал!
Но вот проблема: в одном из методов класса происходит сложение 2х чисел типа int. Т.к. числа большие, то при сложении происходит переполнение. Однако в готовой библиотеке также стоит сложение 2х чисел типа int! никаких long! Однако у них этот алгоритм наверняка нормально работает.
Вот кусок кода (модифицированная версия метода из библиотеки)
Код

private int sBlockSwap( int num, int key )
    {
        //сложение по модулю 2^32
        int cm = ( num + key );
        //подстановки
        int result = sBlock.get( 7 )[ ( ( cm >> 28 ) & 0xF ) ] << 28;
        result += sBlock.get( 6 )[ ( ( cm >> 24 ) & 0xF ) ] << 24;
        result += sBlock.get( 5 )[ ( ( cm >> 20 ) & 0xF ) ] << 20;
        result += sBlock.get( 4 )[ ( ( cm >> 16 ) & 0xF ) ] << 16;
        result += sBlock.get( 3 )[ ( ( cm >> 12 ) & 0xF ) ] << 12;
        result += sBlock.get( 2 )[ ( ( cm >> 8 ) & 0xF ) ] << 8;
        result += sBlock.get( 1 )[ ( ( cm >> 4 ) & 0xF ) ] << 4;
        result += sBlock.get( 0 )[ ( ( cm >> 0 ) & 0xF ) ] << 0;
        //циклический сдвиг влево на 11 битов
        int subresult = result << 11 | result >>> ( 32 - 11 );
        return subresult;
    }


PS. Решил было все на long перевести, но столько ошибок повылезало о том, что нельзя привести long к int при битовых операциях сдвига >>, <<  в строках 6-13. Я даже не знаю теперь, что делать...


Это сообщение отредактировал(а) ReFLeXive - 1.3.2011, 23:15
PM MAIL   Вверх
carper
Дата 2.3.2011, 09:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 1
Всего: 8



Цитата(ReFLeXive @ 1.3.2011,  23:14)
нельзя привести long к int при битовых операциях сдвига >>, <<  в строках 6-13. Я даже не знаю теперь, что делать...

Операции типа << >> для long не запрещены.
Вот такой код будет работать:
Код

   long result = -12344L;
   System.out.println("result = " + ((result >>2)& 0xF));


Если у "них" все нормально работает с int, то не надо "модифицировать" код библиотеки, плохо понимая что делаешь.

Дам один практический совет: берете ту самую библиотеку и начинаете маленькими шажками ухудшать код, после каждого шага ОБЯЗАТЕЛЬНО прогоняем тест.
Так можно изуродовать текст до такого состояния, что преподаватель сможет  сделать вид, что он поверил в то, что код написан самостоятельно.

Максимум час и лаба, да еще и с набором тестов, у вас готова.

PM MAIL   Вверх
math64
Дата 2.3.2011, 09:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



А ты учитываешь, что в Java byte и int знаковые?
PM   Вверх
ReFLeXive
Дата 2.3.2011, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 30.3.2009
Где: г. Уфа

Репутация: нет
Всего: 1



Цитата(carper @  2.3.2011,  09:47 Найти цитируемый пост)
Операции типа << >> для long не запрещены.

Действительно, алгоритм на long я переписал..

Цитата(carper @  2.3.2011,  09:47 Найти цитируемый пост)
Если у "них" все нормально работает с int, то не надо "модифицировать" код библиотеки, плохо понимая что делаешь.

ЧТобы понять что там происходит, я потратил не один час времени)) Их библиотеку я не модифицирую - у меня метод просто делает аналогичные операции.

Цитата(carper @  2.3.2011,  09:47 Найти цитируемый пост)
ам один практический совет: берете ту самую библиотеку и начинаете маленькими шажками ухудшать код, после каждого шага ОБЯЗАТЕЛЬНО прогоняем тест.

Спасибо за совет!



Цитата(carper @  2.3.2011,  09:47 Найти цитируемый пост)
Так можно изуродовать текст до такого состояния, что преподаватель сможет  сделать вид, что он поверил в то, что код написан самостоятельно.

Максимум час и лаба, да еще и с набором тестов, у вас готова.

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

Цитата(math64 @  2.3.2011,  09:53 Найти цитируемый пост)
А ты учитываешь, что в Java byte и int знаковые? 

Поначалу не учитывал, потому и напоролся на переполнение... Хотя, если бы в Java были бы беззнаковые целые - было бы гораздо легче ))

PM MAIL   Вверх
ReFLeXive
Дата 9.3.2011, 22:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 30.3.2009
Где: г. Уфа

Репутация: нет
Всего: 1



Алгоритм я переписал под long, проверил ручками, что должно получится - все сходится, вроде все норм. Проблема вот какая возникла.
Алгоритм отрабатывает, левая и правая части 64 битного блока данных получилась в виде чисел N1 и N2:
Код

N1=4207706485
N2=583880265

В двоичном виде эти числа представлены вот так(использую только младшие 32 бита у типа long):
Код

N1=11111010 11001100 10000001 01110101
N2=00100010 11001101 01001110 01001001

Далее, я получаю их этих чисел 2 массива по 4 элемента (каждый элемент массива соответствует одному байту в long):
Код

N1={117, 129, 204, 250}
N2={73, 78, 205, 304}

В тип byte элементы массива не влезут, а если использовать int, то потом не получается преобразовать это все в строку....
Как сделать отображение получившихся чисел?
PM MAIL   Вверх
carper
Дата 10.3.2011, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 1
Всего: 8



Цитата

каждый элемент массива соответствует одному байту ....
В тип byte элементы массива не влезут ...


Это как это  получается, что байт не лезет в байт?
Да, на всякий пожарный, N2= {73,78,205,34}, а не 304.

Цитата

Как сделать отображение получившихся чисел? 


Вы это сейчас вообще о чем?
Что int, что byte замечательно отображаются сами по себе, не требуя от вас никаких действий.

Нужен какой-то особый формат?
Кому вы вообще хотите отображать свой массив?


И еще раз, если в исходном классе хватало int, а вам потребовался long, то может повнимательней глянуть на алгоритм?
PM MAIL   Вверх
ReFLeXive
Дата 10.3.2011, 20:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 30.3.2009
Где: г. Уфа

Репутация: нет
Всего: 1



Цитата(carper @  10.3.2011,  10:08 Найти цитируемый пост)
Это как это  получается, что байт не лезет в байт?

тип byte может принимать значения в диапазоне -128 до 127, соответственно символ с кодом 129 в тип byte засунуть не получится в явном виде... Хотя, с другой стороны, знаковая единица в старшем разряде по сути ни на что не влияет с точки зрения битового содержимого числа. Т.е. число 129 в двоичном виде выглядит как 10000001, а для типа byte это битовое представление равно числу -1. Если импользовать >>>, то знак не будет учитываться...

Цитата(carper @  10.3.2011,  10:08 Найти цитируемый пост)
Да, на всякий пожарный, N2= {73,78,205,34}, а не 304.

Опечатался, извините =)

Цитата(carper @  10.3.2011,  10:08 Найти цитируемый пост)
Вы это сейчас вообще о чем?

Пример: в результате работы алгоритма получилось число 129. Если использовать тип byte, то вместо 129 будет число -1, а символа с кодом -1 нету... Можно к примеру, это число 129 записать в int, а потом делать явное приведение к char, а из этих char'ов сделать строку... Или даже не засовывать это число в int, a просто использовать >>> при приведении к char. Вобщем, попробую сделать!

Цитата(carper @  10.3.2011,  10:08 Найти цитируемый пост)
И еще раз, если в исходном классе хватало int, а вам потребовался long, то может повнимательней глянуть на алгоритм? 

В принципе, я  теперь понял, что можно обойтись int, используя операцию >>>, чтобы доставать старший байт без учета знаковой единицы... Благо,что использую svn, откатиться несложно...

Тут еще другой вопрос возник... Сейчас у меня заточено на тот случай, что каждый символ занимает 1 байт... Соответственно в алгоритме 64битный блок состоит из 8 символов... А ведь если кодировка UTF-8, к примеру, то каждый символ занимает не 1 байт.... как быть в этом случае?

Это сообщение отредактировал(а) ReFLeXive - 10.3.2011, 20:43
PM MAIL   Вверх
ReFLeXive
Дата 10.3.2011, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 30.3.2009
Где: г. Уфа

Репутация: нет
Всего: 1



Видимо, у меня неверное представление чисел в яве:
Код

byte b = -77;
long res = b & 0xFF;
System.out.println( res );
//
int i = 179;
System.out.println( ( byte ) i );

Результат будет вот какой:

179
-77

Я думал вот как: число 205 в двоичном виде выглядит 1100 1101; в яве старший байт (самый левый) отвечает за знак, соответственно, если не учитывать эту единицу, то получается число 77 (0100 1101), т.е. получается, в итоге, что число 205 это как бы -77... А тут получается, что -77 соответствует числу 179 без учета знака, которое в двоичном виде выглядит как 1011 0011...
Почему так, объясните плиз?



Это сообщение отредактировал(а) ReFLeXive - 10.3.2011, 22:06
PM MAIL   Вверх
jk1
Дата 11.3.2011, 04:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 40
Всего: 75



Цитата

Почему так, объясните плиз?

Потому что установить ведущий бит для смены знака мало. Отрицательные числа представлены так называемым дополнительным кодом:

Прямой код. Прямой код двоичного числа совпадает по изображению с записью самого числа. Значение знакового разряда для положительных чисел равно 0, а для отрицательных чисел 1. 

Обратный код. Обратный код для положительного числа совпадает с прямым кодом. Для отрицательного числа все цифры числа заменяются на противоположные (1 на 0, 0 на 1), а в знаковый разряд заносится единица. 

Дополнительный код. Дополнительный код положительного числа совпадает с прямым кодом. Для отрицательного числа дополнительный код образуется путем получения обратного кода и добавлением к младшему разряду единицы. 
В любом представлении старший бит определяет знак числа: 
0 - положительное число; 
1 - отрицательное число

Теперь возвращаемся к примеру. Запишем 77 как 0100 1101. Теперь по алгоритму выше сделаем из него -77, получим 1011 0011. Расширим диапазон: 0000 0000 1011 0011. Теперь этот дополнительный код будет воспринят как прямой из-за того, что знаковый бит не установлен, а для положительных чисел дополнительный код совпадает с прямым. Читаем его как прямой - получаем 179.

Это сообщение отредактировал(а) jk1 - 11.3.2011, 04:24


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
ReFLeXive
Дата 13.3.2011, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 30.3.2009
Где: г. Уфа

Репутация: нет
Всего: 1



Цитата(jk1 @  11.3.2011,  04:22 Найти цитируемый пост)
Потому что установить ведущий бит для смены знака мало. Отрицательные числа представлены так называемым дополнительным кодом:

Прямой код. Прямой код двоичного числа совпадает по изображению с записью самого числа. Значение знакового разряда для положительных чисел равно 0, а для отрицательных чисел 1. 

Обратный код. Обратный код для положительного числа совпадает с прямым кодом. Для отрицательного числа все цифры числа заменяются на противоположные (1 на 0, 0 на 1), а в знаковый разряд заносится единица. 

Дополнительный код. Дополнительный код положительного числа совпадает с прямым кодом. Для отрицательного числа дополнительный код образуется путем получения обратного кода и добавлением к младшему разряду единицы. 
В любом представлении старший бит определяет знак числа: 
0 - положительное число; 
1 - отрицательное число

Теперь возвращаемся к примеру. Запишем 77 как 0100 1101. Теперь по алгоритму выше сделаем из него -77, получим 1011 0011. Расширим диапазон: 0000 0000 1011 0011. Теперь этот дополнительный код будет воспринят как прямой из-за того, что знаковый бит не установлен, а для положительных чисел дополнительный код совпадает с прямым. Читаем его как прямой - получаем 179.

jk1, спасибо вам большое за подробный и исчерпывающий ответ!

Алгоритм шифрования у меня в принципе работает, все проверено вручную, вполне нормально считается, вычисляется и т.д. 
Мне нужно справиться с проблемой представления данных в алгоритме. Т.е. в какой кодировке подавать данные на вход алгоритма? Если к примеру использовать UTF-8, то метод getBytes() для русских символов будет возвращать по 2 байта за каждый символ, если win-1251, то по одному... Соответственно, в первом случае, входной массив данных будет больше и длиннее... 
Специфика еще такова, что дома я пишу под Linux (кодировка по умолчанию UTF-8), а сдавать лабу буду в универе под windows.
Вобщем, подскажите плиз, как правильно и лучше сделать?

PM MAIL   Вверх
Alexandr87
Дата 14.3.2011, 09:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


дыкий псых
***


Профиль
Группа: Завсегдатай
Сообщений: 1459
Регистрация: 27.11.2004
Где: Алматы, Казахстан

Репутация: 9
Всего: 39



Цитата(ReFLeXive @  2.3.2011,  02:14 Найти цитируемый пост)
Но вот проблема: в одном из методов класса происходит сложение 2х чисел типа int. Т.к. числа большие, то при сложении происходит переполнение. Однако в готовой библиотеке также стоит сложение 2х чисел типа int! никаких long! Однако у них этот алгоритм наверняка нормально работает.

внимательно алгоритм смотри. там не просто сложение 2х чисел типа int. А сложение по модулю 2^32.
PM Jabber   Вверх
ReFLeXive
Дата 14.3.2011, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 30.3.2009
Где: г. Уфа

Репутация: нет
Всего: 1



Цитата(Alexandr87 @  14.3.2011,  09:25 Найти цитируемый пост)
внимательно алгоритм смотри. там не просто сложение 2х чисел типа int. А сложение по модулю 2^32. 

Для типа int сложение по модулю 2^32 и есть просто сложение чисел

PM MAIL   Вверх
ReFLeXive
Дата 19.3.2011, 22:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 120
Регистрация: 30.3.2009
Где: г. Уфа

Репутация: нет
Всего: 1



Фуух, разобрался, заработало)) Нормально шифрует и расшифровывает!!! 
Алгоритм у меня работал верно, косяки были с представлением текстовых данных... Сделал явное указание кодировки windows-1251 и все заработало! 
Если вдруг кому понадобиться, пишите в лс или на почту (reflexive007_собака_gmail.ru), либо, при желании, могу сюда выложить))
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1555 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.