Попробую объяснить смысл синхропосылки как можно более бытовым языком. Из самого слова "синхропосылка" можно выяснить, что оно посылается с чем-то синхронно. Вопрос: с чем? Ответ: с шифртекстом. Т.е для простоты рассмотрим вариант, когда посылаются несколько зашифрованных сообщений на ключе К. Каждое сообщение выглядит так: синхропосылка || шифртекст. Шифртекст зависит от ключа шифрования К, содержимого открытого текста и синхропосылки. Каким образом эта зависимость выглядит определяется режимом шифрования, в данном ответе это не так существенно. Синхропосылка может передаваться в открытом виде, шифровать её не всегда обязательно. Что от неё требуется? От неё требуется 2 свойства: уникальность и случайность. Уникальность состоит в том, чтобы при различных сообщениях находились различные синхропосылки. Для некоторых режимов шифрования как, например, счётчик(CTR) это свойство критически важно. А случайность можно понимать как независимость от ключа К и открытого текста. Это конечно же неверное определение, но от синхропосылки требуется чтобы злоумышленник перехватив её не узнал ничего для себя полезного. В предыдущем куске кода, который вы привели, синхропосылка зависит от ключа, причём очень простым и незатейливым способом. Это означает, что фактически вы отправляете ключ по сети в незащищённом виде и он попадает в руки злоумышленника в слегка измененном виде. Это сводит в ноль все усилия по шифрованию, т.е. вы с тем же уровнем защиты могли бы просто отправлять открытый текст. Что ещё хочется добавить: если вам нужна защита для чего-либо и качественная реализация ГОСТ на 16-разрядном проце не поленитесь и наймите человека, который за деньги сделает все как положено. Боюсь у вас лично могут возникнуть большие проблемы в реализации, о которых вы и не подозреваете сейчас. Успехов!
Понял, спасибо! Это я более-менее понимаю... Я только не понял и не смог увязать приведенный кусок кода со стандартом... Еще хочу добавить цитату из статьи Винокурова: Для моей задачи наиболее удобно использовать предопределенное значение синхропосылки или вырабатывать ее синхронно источником и приемником по определенному закону. Вопрос встает в реализации... По поводу: Я готов к такому предложению, в том числе в Ваш адрес... Встречные предложения жду в личке.
Я вам дам дружеский совет: напишите краткое резюме того, что нужно сделать и опубликуйте это в ветке WASM.COMMERCE и ждите предложений в личку=)
Опубликовал. Пока жду ответов... Ну а пока жду, хочу продолжить: Код (Text): S0=(S0+C1)mod2^32 S1=(S1+C2–1)mod(2^32–1)+1 правильно ли будет следующее в реализации ANSI C: Код (Text): // S - беззнаковое 64 бит, передается в эту функцию и возвращается обратно // S0 и S1 - беззнаковые 32 бит, используются только внутри этой функции S0 = S & 0xFFFFFFFF; S1 = (S >> 32) & 0xFFFFFFFF; const C1 = 0x01010101, C2 = 0x01010104; S0 += C1; S1 = ((S1 + C2 - 1) % 0xFFFFFFFF) + 1; S = S1; S = (S << 32) | S0; return S;
Ау... Подскажите, плиз, по вышеприведенному примеру. Особенно интересует строчка: Код (Text): S1 = ((S1 + C2 - 1) % 0xFFFFFFFF) + 1; Может ли кто на пальцах как для школьника объяснить смысл этой строчки? Иначе я ничего не понимаю...
Особенно не понимаю следующее: Если мы два 32-битных числа S1 и C2 сложили (и отбросили бит переполнения, если он возник) и затем вычли из этой суммы единицу, то получившееся число будет всегда меньше, чем 0xFFFFFFFF. Или я не прав? И дальше: остатком отделения этого (меньшего) числа на (большее) 0xFFFFFFFF будет это само меньшее число. Тогда зачем вообще делить?
Нашел вот такое: (http://protect.htmlweb.ru/gost.htm) [+] - сложение 32-разрядных чисел по модулю 2^32; {+} - сложение 32-разрядных чисел по модулю 2^32-1. Числа суммируются по следующему правилу: A [+] B = A + B, если A + B < 2^32, A [+] B = A + B - 2^32, если A + B >= 2^32. A {+} B = A + B , если A + B < 2^32 - 1, A {+} B = A + B - (2^32 - 1), если A + B >= 2^32 - 1. И как эту теорию сложения 32-разрядных чисел по модулю 2^32-1 применить на языке Си для A и B, если они изначально 32-битные, как в вышеприведенном примере S1 = ((S1 + C2 - 1) % 0xFFFFFFFF) + 1? То есть, если в Си складывать два 32-битных числа A + B, то лишний бит (в случае переполнения, когда A + B >= 2^32 - 1) у нас все-равно отбросится или как? И если он отбросится, то нам нужно проверять на переполнение, а потом вычитать из суммы: A + B - (2^32 - 1), причем держа в уме бит переполнения?
Добрый день, уважаемые! Раз никто не хочет поддерживать разговор, продолжу дискуссию сам с собой... Вышеприведенная конструкция Код (Text): A {+} B = A + B , если A + B < 2^32 - 1, A {+} B = A + B - (2^32 - 1), если A + B >= 2^32 - 1. - неверна! На указанном выше сайте имеется ошибка, заключающаяся в том, что в оригинальном тексте ГОСТа указано иное: Код (Text): A {+} B = A + B , если A + B < 2^32, A {+} B = A + B - (2^32 - 1), если A + B >= 2^32. Поэтому, конструкция для 32-битной реализации на Си: Код (Text): S1 = ((S1 + C2 - 1) % 0xFFFFFFFF) + 1 в принципе верна, но точнее будет вот так: Код (Text): S1 = ((S1 + (C2 - 1)) % 0xFFFFFFFF) + 1 , иначе при определенных условиях мы можем получить отрицательное число при вычислении S1 + C2 - 1. Если рассматривать файл-исходник Винокурова "GAMMA_.ASM", то там указано так: Код (Text): add EAX,C1 ; N1=(N1+C1)mod 2^32 add EDX,C2 ; N2=(N2+C2)mod 2^32 adc EDX,0 ; N2=(N2+C2)mod(2^32-1) , и, ориентируясь на эту конструкцию, текст самого ГОСТа и статью Винокурова для 32-битной реализации на Си все становится правильно и прозрачно: Код (Text): S1 = ((S1 + (C2 - 1)) % 0xFFFFFFFF) + 1 .
А для 16-битной реализации будет так: Код (Text): // S - беззнаковое 64 бит, виртуально состоит из 4-х 16-битных чисел {S1Hi,S1Lo,S0Hi,S0Lo} // S0 = S & 0xFFFFFFFF; // S1 = (S >> 32) & & 0xFFFFFFFF; // S1Hi, S1Lo, S0Hi, S0Lo - беззнаковые 16-битные числа unsigned long S1Hi, S1Lo, S0Hi, S0Lo; // беззнаковые 16-бит const unsigned long C1Hi=0x0101, C1Lo=0x0101; // C1=0x01010101 const unsigned long C2Hi=0x0101, C2Lo=0x0104; // C2=0x01010104 // S0 += C1, тоже, что и S0 = (S0 + C1)mod2^32 S0Hi += C1Hi; S0Lo += C1Lo; if (S0Lo < C1Lo) ++S0Hi; // S1 = (S1 + C2)mod2^(32-1), тоже, что и S1 = ((S1 + (C2 - 1)) % 0xFFFFFFFF) + 1, // тоже, что и: // add EAX,C1 ; N1=(N1+C1)mod 2^32 // add EDX,C2 ; N2=(N2+C2)mod 2^32 // adc EDX,0 ; N2=(N2+C2)mod(2^32-1) S1Hi += C2Hi; S1Lo += C2Lo; if (S1Lo < C2Lo) ++S1Hi; if (S1Hi < C2Hi) ++S1Lo; Здесь есть сомнения по поводу двух последних подряд идущих условий "If..." Может быть правильнее будет так? Код (Text): if (S1Lo < C2Lo) { ++S1Hi; if (S1Hi < C2Hi) ++S1Lo; } Поправьте меня, если в чем либо ошибаюсь...
У Винокурова в описании имеются неточности. Предлагаю читать первоисточник http://www.fileserver.cc/akacypma482j.html.
Прошу с этого места: поподробнее... Иначе получается голословно... Первоисточник читал... и не раз Но, так как качество Вашего скана выше, чем то, которое у меня имеется, то Ваш скан однозначно пригодится!
kapger В описании основного шага криптопреобразования по ГОСТ 28147 Винокуров на схеме представил вроде бы всё верно. Но в описании алгоритма забыл указать, что перед выполнением "Шаг 1" необходимо сохранить значение заполнения N1, чтобы затем на "Шаг 5" использовать его для заполнения N2. А такая мелочь в описании может сильно испортить жизнь начинающему крипто-кодеру. По-крайней мере я при реализации алгоритма, лишился немалого количества серого вещества из-за такого, на мой взгляд, "вольного" подхода к описанию ГОСТа.
В описании режима гаммирования также нет однозначности. Нет указания на то, что между вторым и третьим шагами алгоритма необходимо сохранить значение синхропосылки. По описанию и схеме выходит, что для каждого последующего цикла выработки гаммы шифра, необходимо использовать выработанную ранее гамму. А это не так.
Вроде бы Винокуров именно так и описал, как должно быть... Или я не прав? Смотрим pdf-файл http://www.enlight.ru/crypto/download/articles/vinokurov/28147_89.zip на странице 6 в самом верху есть рисунок (Рис.1. Схема основного шага криптопреобразования алгоритма ГОСТ 28147-89) и рядом с ним описание шагов. Что в блок-схеме рисунка, что в описании Шага 5 указано, что N2=N1. По моему мнению, соответствует ГОСТу.
kapger Если прослеживать схему - всё верно. Если же читать описание: "Шаг 1. Сложение с ключом. Младшая половина преобразуемого блока складывается по модулю 2^32 с используемым на шаге элементом ключа, результат передается на следующий шаг", то логика подсказывает, что N1 нужно сложить с элементом ключа. На самом деле с ключом складывается копия N1, расположенная в S.
Может быть немного непонятно я объясняю. Попробую иначе. У Винокурова на схеме в Шаг 1 показано: Код (Text): S = (N1 + X) Mod 2^32 На самом же деле, согласно официальному ГОСТу должно быть так: Код (Text): S = N1 S = (S + X) Mod 2^32 В таком случае N1 сохраняется и может быть правильно использован на Шаг 5.
С этим тоже позвольте не согласиться... Синхропосылку (начальное заполнение) мы не сохраняем! А точнее мы ее сохраняем (даже не ее саму, а сначала зашифрованную синхпропосылку, после чего единожды суммированную по частям с соответствующими константами C) только между первым и вторым блоком гаммы, а далее (при выработке второго и далее блоков гаммы) сохраняется уже не сама синхропосылка (пусть даже она уже зашифрованная и единожды суммированная с соответствующими константами C), а ее неоднократное нарастающее суммирование с константами C. Вот, смотрите... Если следовать ГОСТу, то, в соответствии с пунктом 3.1.4 в предложении чуть ниже чертежа 3 указано, что "при этом заполнение N3, N4 сохраняется" для выработки первого блока гаммы, где и используется именно синхропосылка (уже зашифрованная и единожды суммированная с соответствующими константами C). Но только на первом блоке гаммы используется синхропосылка! Далее в ГОСТе указано в пункте 3.1.5, что "Для получения следующего 64-разрядного блока гаммы заполнение N4... и N3...", сохраненные ранее, суммируются, соответственно, с константами C1 и C2, после чего уже эти суммы становятся заполнением N4 и N3, соответственно. И уже после этого "... заполнение N3 и N4 сохраняется". И так далее... То есть, указанное у Винокурова на рисунке 4 в шаге 2 полностью соответствует ГОСТу: S0=S0+C1 (в редакции ГОСТа N4=N4+C1) S1=S1+C2 (в редакции ГОСТа N3=N3+C2)
С этими Вашими утверждениями я согласен. Но, все дело в том, что с точки зрения программирования - эти два варианты одинаковы! Ну разве что одно лишнее (и вроде бы абсолютно ненужное) действие присваивания: Код (Text): S = N1
Доброго времени суток! Проверял ли кто реализацию собственного алгоритма шифрования в режиме простой замены с реализацией Винокурова на примере его файла GOST32.EXE и его же ключа KEY.KEY и таблицы замен CHANGTBL.CHT? Все эти файлы есть в исходниках Винокурова. То есть, если взять какое-либо 64-битное число и зашифровать его в режиме простой замены с помощью Вашего алгоритма с использованием указанных ключа и таблицы замен, то результат шифрования должен совпадать с результатом шифрования, полученным с помощью программы Винокурова GOST32.EXE! И то же самое для расшифрования... Также, в рамках этого вопроса, интересует порядок расположения элементов ключа в файле KEY.KEY и элементов таблицы в таблице замен CHANGTBL.CHT. То есть, если смотреть от начала файла, то элементы ключа идут по порядку в виде key0, key1, ... key7 или в обратном порядке? А в таблице замен элементы идут по порядку в виде k8, k7, ... k0 или в обратном порядке?
Никто не проверял или все в отпуск ушли? Тогда подскажите ссылку на программу (можно Вашу личную), которая однозначно соответствует ГОСТу, имеет возможность каким-либо способом явно указать ключ и таблицу замен, чтобы в итоге можно было получить результат шифрования тестовой строки, и результат которого будет равен результату шифрования с помощью программы Винокурова. Будем считать, что реализация Винокурова наиболее правильная, так? Зачем это надо? Мне нужно проверить свою реализацию (для микропроцессора, скажем так), которой нет никакого доверия с моей же стороны. Зато есть доверие к программе Винокурова, но нет полного понимания о расположении ключевых элементов в соответствующих файлах (см. предыдущий пост). То, что в моей реализации результат шифрования при его последующей расшифровке совпадает с исходным текстом - это еще ни о чем не говорит, насколько я понимаю... Пытался найти в сети подобные программы, чтобы проверить себя же... Есть либо простые программы, которые используют неизвестно какую таблицу замен, либо вообще ничего хорошего нет... Одну программу, правда, нашел, которая позволяет явно указывать и ключ и таблицу замен, так ее результат отличается как от программы Винокурова, так и от моего результата. Получается полная ерунда... Кому верить?