Простые алгоритмы скремблирования данных

Иногда нужно что-то зашифровать, но привлекать серьёзные алгоритмы шифрования вроде и не к месту — будет как из пушки по воробьям. Например, нужна простая защита траффика от пользователей/троянов со снифферами, но сами данные не стоят того, чтобы на них тратилось много времени на шифровку-расшифровку, ну и на саму реализацию тоже. Или вам нужно как-то обеспечить закрытость неких хранимых данных от обычных пользователей. Понятно, что подобные алгоритмы не устоят против целенаправленных попыток взлома профессионалами, но мы попытаемся усложнить работу и им, хотя такая задача обычно и не ставится. Вот это-то обычно и называется scrambling.

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

Предпосылки

Предполагается, что потенциальный взломщик либо не имеет доступа к коду, который осуществляет шифрование, либо не имеет достаточной квалификации для реверс-инжениринга, либо данные не настолько ценны, чтобы тратить время на более тяжёлые методы взлома.

Наверно все знают, что в подобных случаях чаще всего применяют простое циклическое наложение ключа фиксированой длины с помощью операции XOR. И все так же хорошо знают, что такая защита не выдерживает даже начинающего «хакера» или продвинутого пользователя. Хотелось бы что-нибудь посложнее, но простое в реализации.

А если генерировать ключ?

Первое, что приходит в голову, это генерировать достаточно длинный ключ, чтобы хотя бы усложнить нахождение длины ключа. Например, использовать некий генератор псевдослучайных чисел с входными данными, известными и отправителю, и получателю. Один из таких часто применяемых генераторов — линейный конгруэнтный ГПСЧ (ГСПЧ это генератор псевдослучайных чисел). Мы, конечно, догадываемся, что это плохо, но что же именно плохо в этом подходе? Проблема в том, что довольно трудно генерировать параметры для самого генератора. Программно подобрать хорошие параметры для линейного конгруэнтного ГПСЧ, чтобы последовательность была длинная и невырожденая, довольно трудно. По этому поводу можно почитать в 3.2.1 в книге Д.Кнута «Искусство программирования». Поэтому зачастую эти параметры вколачивают в код как константы и, как следствие, потенциальный взломщик получает множество сообщений зашифрованых с одним ключом, что значительно упрощает его работу.

А что если использовать сами данные для генерации этой псевдослучайной последовательности?

Эта идея осенила меня лет 20 назад, когда я «помогал» писать диплом одной моей знакомой студентке. На первый взгляд кажется, что это невозможно, ведь нам нужен генератор, который выдавал бы одинаковую последовательность и при шифровке, и при расшифровке. Как ни странно, именно этот «убийственный» тезис и даёт нам путь к созданию такого генератора. Да, нам нужен алгоритм, который меняет значения своих внутренних переменных одинаково, если ему дать исходный байт (или что там у нас является атомарной единицей кодирования) и зашифрованый байт. Как этого достичь? Всё гениальное просто — для вычисления следующего значения ключа можно задействовать коммутативные операции для пар исходных-шифрованых байт. Так как результат операции не зависит от порядка операндов в паре, то очевидно, что такой алгоритм будет менять свои переменные при расшифровке точно так же как и при шифровке, но последовательность ключей для других входных данных будет другой.

Пример генератора ключей, зависящего от входных данных

Чтоб было понятней, рассмотрим простенький пример такого алгоритма.
Пусть xn — это очередной код в исходных данных, kn — текущий ключ, kn+1 — следующее значение ключа, yn — зашифрованый код xn.
Q(a,b) — некая коммутативная функция, т.е. такая, что q(a,b)==q(b,a).
F(a,b,c) — некая целочисленная функция.
Toгда итерацию по (де)кодированию можно описать так:
yn := xn xor kn;
kn+1 := F( kn, Q( xn, yn ), n );
Если для функции F() понятно, что её имплементация в общем-то ограничена лишь нашей фантазией и здравым смыслом, то про Q(), вероятно, вам хочется увидеть подробностей, а именно, каким таким условиям она должна соответствовать, чтобы быть коммутативной. Самый простой способ этого достичь — использовать аргументы только парами в коммутативных операциях, например xor, сложение, умножение. Примеры:
Q(a,b) = a xor b. (Исправлено: пожалуй я тут погорячился, ведь при наложении исходного и зашифрованного кода получается ключ, что нежелательно. Я лично использую немного более сложные функции).
Q(a,b) = ((a xor b) or 1) * (( a + b ) xor 1).
Как видите, придумать свою супер-пупер функцию Q() совсем не сложно. Другое дело, нужно ли её делать сложной? Думаю, что особого смысла в её переусложнении нет.

Ну а теперь-то что плохо?

Да, не зная кода функции кодирования, прочитать что-либо будет весьма затруднительно. Но какие зацепки всё-таки остаются? Если входные параметры для скремблера будут одинаковыми, то
  1. Если два сообщения начинаются с одних и тех же данных, то и начало зашифрованых данных будет абсолютно одинаковым;
  2. Ключ для первого кода одинаков;
  3. Длина зашифрованного сообщения точно совпадает с длиной исходного сообщения.

Как с этим бороться, но не положить свою молодую жизнь? Конечно, способов борьбы может быть много, но хочется дёшево и сердито, есть ли такие? У меня есть несколько идей на этот счёт.
Чтобы побороть первые два пункта, есть очень простой, но эффективный приём. При шифровании перед каждым сообщением вставляйте случайные данные. Достаточно даже одного байта(кода). Так как следующий ключ зависит от данных, то даже для одинаковых сообщений мы получим разные последовательности ключей. Получателю нужно просто отбрасывать этот префикс после расшифровки сообщения.
Для борьбы с третьим пунктом можно добавлять случайные данные до и/или после сообщения.

А ещё идеи есть?

А то! У меня всегда есть идеи!
Допустим вы передаёте данные в сжатом виде. Или данные уже частично зашифрованы. Или каждое сообщение/блок достаточно длинные и состоят из двоичных данных с примерно равномерным распределением кодов. В этом случае любое вмешательство в порядок кодов в сообщении может существенно усложнить жизнь потенциальному взломщику. Уверен, что вы можете и сами придумать некий примитивный перемешиватель байтов в блоке данных, но я ведь обещал интересные и красивые идеи.

Перемешиватель данных (shuffler)

Обычно для решения этой задачи используют некий ГСПЧ для получения пар индексов кодов в блоке данных, которые меняют местами. Неприятность этого метода в том, что трудно гарантировать, что какая-то часть данных не останется на том же месте. Также не совсем понятно, сколько же перестановок нужно сделать, чтобы достичь приемлемого результата, хотя для надёжности можно просто пройтись по всем кодам сообщения и обменять каждый со случайным. Но есть ещё одна неприятность — если генератор имеет плохое распределение по квадрату (а линейный конгруэнтный именно такой болезнью и болеет, и причём безнадёжно), то при определённых размерах блока можно нарваться на зацикливание выдаваемых значений. Я довольно долго шёл к идее быстрого псевдослучайного перемешивателя данных (shuffler) и считаю, что она заслуживает вашего внимания не только как алгоритм для скремблирования.

Немного теории. В пункте 3.2.1.2 книги Д.Кнута «Искусство программирования» можно найти критерии для выбора множителя для линейного конгруэнтного генератора, чтобы длина генерируемой последовательности равнялась модулю. Что это означает? Это значит, что для генератора с модулем m каждое значение от 0 до m-1 будет выдано ровно один раз. Зачем это нам? Вспомним, что для нашего перетасовщика было бы желательно гарантировать, что все байты(коды) сообщения поменяли своё место. То есть, если длина данного блока данных равна этому самому m, то нам будет достаточно просто записывать очередной входной байт(код) сообщения в выходной буффер по индексу, равному очередному значению из генератора. Простота этого алгоритма настолько сооблазнительна, что я не мог пройти мимо.

Но, как всегда случается с чем-то сооблазнительным, не обошлось без проблем. Во-первых, не все m одинаково полезны хороши. Из той же главы той же книги мы видим, что если m является произведением простых чисел в первой степени, то полного перебора элементов мы достичь не можем в принципе (не считая перебора подряд, что нам, конечно, не интересно). Получается, что получить нужный нам генератор с заданной длиной последовательности нельзя, и, следовательно, если у нас сообщения произвольной длины, то мы не всегда можем найти такой генератор. Тупик? А действительно ли нам нужны генераторы произвольной длины? Вспомним о том, что для потенциального взломщика знание длины сообщения очень даже небесполезно. Тогда мы уже знаем и способ борьбы, который мы успешно применяли для генератора, зависящего от входных данных. Правильно, надо подбросить случайный мусор, и лучше всего перед полезными данными. Правда, есть проблема в том, что в каждом блоке нужно как-то указывать количество полезной информации в нём. Если же в вашем случае длина всех сообщений/блоков данных фиксирована, то вы вы можете зафиксировать и m — выбрать первое удобное для вас значение, которое больше длины входного блока и удовлетворяет критерию из теоремы A из 3.2.1.3 из книги.

Теперь о самом критерии для параметров генератора xn+1=(a*xn+c) mod m:
  1. c и m взаимно просты;
  2. a — 1 кратно p для всех простых делителей p числа m;
  3. a — 1 должно быть кратно 4, если m кратно 4.

Как бы этого достичь малой кровью? Я предлагаю такой вариант:
m = 2n, где n>3;
с = p, p — простое число & p>2;
a = 4*k+1.
Как легко заметить, все три условия выполняются и такие значения довольно легко подобрать.

Ещё идеи?

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

Думаю, что на сегодня хватит.

Исправления: Исправил замеченную отчепятку и зачеркнул неудачный пример.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 37

    +4
    Статья интересная, но мне было бы проще применить SSL даже там, где оно того не требует. Просто потому, что это пара строчек готового кода с готовыми примерами и готовыми решениями. А здесь все это надо тестить/отлаживать, разрабатывать. Да и шифрование вполне нормальное получится:)
      –1
      Иногда применить SSL не проще. SSL предполагает наличие сокета, точнее, он сам является сокетом. И он уж явно более затратный по ресурсам. Даже если забыть о том, что эти простенькие алгоритмы можно использовать вообще для чего-то несетевого, то всё равно даже и для сети можно найти применения, например, подумайте о том, как сделать нечто такое для UDP.
        +2
        я так думаю человек имел в виду openssl, в функции которого на вход подаем исходную строку (буфер), и на выходе получаем зашифрованную строку (буфер)
          +3
          Я всё равно настаиваю, что использовать SSL может быть не проще в каких-то ситуациях. Случаи бывают разные. Допустим, у вас микропроцессор с ограниченным объёмом ROM и RAM, и openssl там нет. Обычно в таких случаях полагаются либо на hardware решения на регистрах сдвига, но если нужно именно простое программное решение? Я соглашусь, что при наличии соответствующих библиотек может быть проще написать и отладить с openssl (или каком-то другом алгоритме), но будет ли это быстрее работать? Не верю, за исключением, может быть случаев, когда имеется hardware поддержка.
            +1
            В таком случае — да, однако во введении вы обозначили область применения как «простая защита там, где без защиты стремно, а серьезно защищать нечего». Поэтому я вам и отвечаю, что при наличие готовых библиотек — проще, быстрей и дешевле сделать готовое, чем городить этот колхоз.

            Хотя на контроллерах да, ваше решение может быть полезно.
          0
          >подумайте о том, как сделать нечто такое для UDP
          преимущества использования UDP испаряются, если обратить внимание на то, что для такого шифрования необходимо получить предыдущий блок для расшифровки текущего.
            0
            О преимуществах UDP никто и не заикался… А также и том, что конкретная реализация с использование этих идей будет именно поточная. Обратите внимание, что описанная вами проблема касается в основном передачи потоков через непотоко-ориентированные каналы, т.е. это скорее затронет поточные шифры, да и то зависит от того, как их использовать. Если сделать шифрование блока/сообщения самодостаточным, то такой проблемы нет.
        0
        И никакого сравнения с существующими поточными шифрами ни по скорости, ни по криптостойкости. Совершенно не обоснованная статья. Не верю, что лучше уже проверенных временем поточных шифров.
          0
          Нормальная статья. То что здесь описано — это скремблирование, и оно имеет отличную от шифрования область применения. Область применения шифрования — это когда можно обеспечить секретность ключа. Когда же ключ, данные и алгоритм неизбежно доступны злоумышленнику, то единственный выход — скремблирование, а его нужно делать своим собственным, уникальным алгоритмом, и всячески защищать его от реверс-инженеринга. Известный алгоритм легко идентифицировать в коде и выковырять к нему ключ, неизвестный же придется долго и упорно реверсить, да еще его можно сделать специально неудобным для злоумышленника.
            0
            > Когда же ключ, данные и алгоритм неизбежно доступны злоумышленнику, то единственный выход — скремблирование.
            В этом случае злоумышленнику нужно просто подставить ключ и данные в алгоритм и получить исходное сообщение :)

            >То что здесь описано — это скремблирование, и оно имеет отличную от шифрования область применения.
            И в этой области применения вполне достаточно простого смешивания с спевдослучайной последовательностью.
              0
              > В этом случае злоумышленнику нужно просто подставить ключ и данные в алгоритм и получить исходное сообщение :)
              Но сначала нужно найти ключ и алгоритм, а это может быть не так просто. И реализация нужного алгоритма может плохо ложиться на платформу, на которой злоумышленник хочет расшифровывать данные. Например скремблируется сетевой трафик, причем скремблируется так, что чтобы получить хоть часть данных надо расшифровать их полностью. И алгоритм скремблирования содержит много операций и никак не упрощается. Злоумышленнику придется потратить много денег на покупку оборудования, ресерс-инженеринг алгоритмов и программирование дешифрации, чтобы читать такой трафик.

              > И в этой области применения вполне достаточно простого смешивания с спевдослучайной последовательностью.
              В этой области нет, и не может быть универсальных рецептов. Каждый случай индивидуален, и под него можно придумать оптимальный алгоритм.

                0
                Намного полезнее будет подумать в сторону криптостойкого генератора псевдослучайных чисел. А если не нужна криптостойкость, то и не городить ничего, а использовать линейный конгруэнтный.
                  0
                  Намного полезнее будет подумать головой. А что использовать — зависит от задачи. Глупо давать конкретные советы не зная где и как это используется.
                    0
                    дайте пример области применения, где не подойдет то, что я предлагаю и подойдет то, что написано в этой статье.
                      0
                      Пример номер раз: мы делаем защиту софта от реверс-инженеринга и нам нужно заскремблировать код, чтобы усложнить его анализ хакером. Алгоритм должен быть как можно сложнее и запутаннее, и желательно меняться при каждой компиляции. Тогда будет сложно сделать автоматический распаковщик.

                      Пример номер два: мы делаем некий протокол, который провайдеры очень хотели бы заблокировать (p2p, Skype, e.t.c.). Нам нужно как можно сильнее усложнить им жизнь и увеличить их расходы. Для этого скремблирование стоит сделать двойным: алгоритм первого слоя зависит от данных и помимо расшифровки выдает на выходе ключ для второго слоя. В итоге чтобы отличить данные от случайных придется как минимум расшифровывать весь первый слой целиком и часть второго. Реализация будет сложной и потребует много ресурсов, и чтобы фильтровать трафик пользователей никаких денег не хватит.
                0
                Для скремблирования много где найдется применение. Что первым приходит в голову — это неблокируемый провайдерами файлообмен. Для этого достаточно придумать такой алгоритм, реалтаймовое дешифрование которого для многих гигабит трафика стоило бы провайдеру слишком больших денег. И чтобы не было никаких особенностей трафика, позволяющих это заблокировать средствами циски.
                  –1
                  Берите любой VPN и не изобретайте колесо.
                    0
                    Во-первых VPN не подходит для задачи, предполагается что мы делаем приложение со своим протоколом. Во-вторых протокол не дизайнившийся для неблокируемости будет заблокирован, способ найдется.
            0
            Во-первых, тут не излагается конкретный алгоритм, а даются оригинальные идеи (по-крайней мере две).
            Во-вторых, эти идея не обязательно использовать для потоков, более того, идея шафлера вообще может быть использована для чего-то далёкого от шифрования.
            В-третьих, сравнивать скорости имеет смысл только для конкретных реализаций в конкретных условиях. Хотя у меня есть большие сомнения, что можно обогнать такую простую арифметику, как здесь.
            В-четвёртых, сравнивать криптостойкость… А это сильно важно надо для тех применеий для которых оно рассчитано? Она очевидно лучше, чем у часто применяемого XOR с фиксированым ключом и использующих его это почему-то не сильно волнует, причем этот алгоритм ненамного сложнее в реализации.
              +2
              Вот алго попроще:
              1) Генерим keysize рэндомных байт
              2) Шифруем данные любым понравившимся поточным алгоритмосом
              3) Пишем в начало мессаджа key, потом данные
              При получении считываем key, потом расшифровываем данные
              4) ?????
              5) PROFIT!
              Единственный минус который можно придумать — длинна данных вырастает на keysize байт.
                0
                Проще чего? Куда уж проще-то? Сложность "любого понравившегося поточного алгоритма" вы учитываете в общей сложности своего алгоритма?

                Кстати, применение поточного алгоритма в лоб с одим ключом к одинаковым данным даёт одинаковый результат, что уже само по себе недостаток с точки зрения криптографии. В статье указано, как с этим просто забороться. Хотя идея добавления мусора перед данными не нова, но в своё время я этот велосипед изобрёл сам (интернета тогда, можно сказать, не было).

                Собственно, в статье даются идеи, изложенные на пальцах. Уверен, что кому-то эти идеи будут полезны.
                  0
                  >Проще чего? Куда уж проще-то?

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

                  >Кстати, применение поточного алгоритма в лоб с одим ключом к одинаковым данным даёт одинаковый результат, что уже само по себе недостаток с точки зрения криптографии.

                  см п. 1.

                  Притензий к идеям в статье, кстати, не имею, просто указываю на более простой в реализации вариант.
                    0
                    Придумывать уже не надо — я же не зря надрывался, когда статью писал. Так что этот пункт уже отпадает. (это я нашутил)

                    В конце концов все эти поточные шифры кто-то когда-то изобрёл, и сделали это люди (скорее всего) как мы. Развелось их (шифров) уже столько, что время, потраченное на выбор алгоритма, уже сопоставимо со временем написания своего. Да, я осознаю, что защита слабаная на коленке и основанная на закрытости кода скорее всего устоит лишь до первой действительно серьёзной попытки взлома. Но тут такой задачи и не ставилось, да и не уверен я, что он так просто сдастся… Хотя у меня и есть некие идеи по взлому этого кода, но математически эта задача непростая, а идеи изложенные тут очень generic, так что при необходимости его можно легко отмасштабировать для увеличения стойкости, например, увеличить битность параметров генератора ключей.
                      0
                      И все таки, у этих алгоритмов против данной статьи есть один неоспоримый плюс — их долгое время на уязвимости и скорость проверяли мозги совокупным объемом с камаз ) К тому же уже есть 100500 готовых реализаций которые можно всандалить копипастом.
                        +2
                        Когда-то какие-то пессимисты тоже ругали эти алгоритмы. А может какая-то из идей приглянётся очередному камазу мозгов и будет использована в неком новом алгоритме? Как знать…
                  0
                  Зато очень легко взламывается ) для защиты об блокировки провайдерами слабовато будет )
                    0
                    Не сложнее, чем предложенный в статье. Суть та же: не знаешь алго — куришь в сторонке.
                    Ведь суть скремблирования (обфускации), чтобы внешне поток данных был не отличим от случайных. Удачи провайдерам в попытках разбора данных на нестандартных портах — перебирать все алгоритмы и возможные способы обфускации для их оборудования — непозволительная роскошь.
                    Хотите большего? Пользуйте нормальное шифрование
                  +1
                  Сейчас читаю в перерывах на работе книгу «Практическая криптография» Нильса Фергюсона.
                  Так вот, один из основных тезисов криптографии — это «При́нцип Керкго́ффса», согласно которому в секрете должны держаться только ключи. Все остальное должно быть известно публично (на это следуюет опираться).

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

                  Хотя тоже моменты спорны :) вот тут habrahabr.ru/blogs/crypto/116481/ — как раз проблема ФБР, что они не знают «функции» кодирования
                    0
                    Я уже в комментах писал про это. Конечно да, основная сложность во взломе первой идеи — это добыть сам алгоритм, и это явно больше чем полдела. Но, допустим, ключи (в данном случае параметры генератора) не присутствуют в коде — это я оставил на усмотрение программиста. Математическая задача нахождения этих параметров довольно нетривиальна и она сильно зависит от функций. Если приоритетом была скорость, то битность параметров скорее всего определяется битностью платформы, но я специально не оговаривал то, что делается в F() и Q(), а там этих параметров может быть сколько угодно. Подбирать брутфорсом можно, тем более к счастью-несчастью алгоритм быстрый, но какой будет критерий подбора, если в начале идёт мусор? Да, доказать криптостойкость даже для какой-то конкретной реализации будет проблематично, а оно вам действительно важно для этих применений? Вон радиообмен военных лётчиков НАТО слушают и картинку с предаторов без проблем смотрят, а вы говорите… Кстати, для предаторов этого шифра было бы достаточно — доступ к его коду получить непросто, для этого сначала нужно его сбить или выкрасть.
                      0
                      Ничего не спорные моменты, ФБР не знает ни ключ, ни алгоритм. У них только зашифрованный текст есть. Ну и конечно же предположение, что алгоритм должен быть простой и не криптостойкий, ведь человек мог в уме шифровать.
                        0
                        На самом деле можно существенно усложнить взлом, используя только скремблирование.
                        В том числе подменять алгоритм в случае, если по вторичным признакам мы обнаруживаем, что нас отлаживают. В этом случае взломщику придется копать, почему в отладчике все путем, а без него все падает. В итоге для взлома требуется более высокая квалификация, следовательно, вероятность падает.
                          0
                          P.S. Это для защиты от взлома при доступности двоичного кода.
                        0
                        Вообще, я довольно давно присматриваюсь к подобных алгоритмам (а лучше — реализациям) скрэмблеров.
                        Не то чтобы очень интенсивно ищу, но время от времени у меня возникает необходимость иметь какой-то алгоритм, если не полноценного шифрования, то хотя бы, вот, скрэмблирования, который нормально работал бы как минимум на Java, GWT, PHP и Javascript.
                        А то, как обычно, — то мега библиотеки подключаем (Java),
                        то они не работают в GWT (клиентская часть),
                        то «simple» Javascript что-то по-своему делает,
                        то в PHP md5 у данных изменяется (версия PHP что-ли?!)…

                        Вот если бы такое что-то найти. Забрал бы себе :-)
                          0
                          Ну, собственно, я лично именно для таких нужд чаще всего и использую эти свои алгоритмы. Именно так — бывает нужно связывать delphi/FPC, Java, JavaScript, Perl. В случае Delphi/FPC у меня имплементации на ассемблерах x86 и x64, а в оригинале (20 лет назад в дипломе девочки) это был Ассемблер IBM 370.
                          0
                          Мы с Димой Скляровым как-то обсуждали создание такого вот сверхлегкого, но относительно стойкого шифра для работы «на лету» и пришли к выводу, что в общем-то достаточно старой доброй связки ADD + XOR, особенно в 64-битном варианте. Если криптосхема реализована правильно, то обратить эту функцию, не зная ключа, уже очень и очень трудно. Для данных, уязвимых к статистическому анализу, можно добавить циклический сдвиг на переменное количество бит.
                          Управляемый ГПСЧ добавить можно, но вот насколько оно добавит криптостойкости — вопрос сложный. Самое уязвимое здесь место — передача сеансового ключа шифрования: если злоумышленник сможет его перехватить, то все остальное уже неважно.
                            0
                            >Самое уязвимое здесь место — передача сеансового ключа шифрования: если злоумышленник сможет его перехватить, то все остальное уже неважно.
                            Что мешает использовать шифрование с открытым ключем для передачи сеансового ключа для скремблирования?
                              0
                              Ну так в первой идеи именно это и сказано, только обобщено и формализовано, а также устранены некоторые типичные недостатки.

                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                            Самое читаемое