На очередной паре по «Информационной безопасности» преподаватель дал нам задание придумать собственный метод шифрования. В голову сразу пришла идея о довольном необычном (а может и нет) методе. Что из этого вышло, читайте под катом.



За основу был взят шифр «Цезаря», суть которого заключалась в замене букв путём сдвига в алфавите на определённое число. Число это также является ключом, его вводит пользователь при шифровании.

Что же нам нужно? Был составлен массив ассоциаций букв и символов emoji. Для этого были написаны скрипт для парсинга всех emoji из Вконтакте и программа на Delphi для создания ассоциации путем случайного перемешивания смайликов, а также для дополнения их ссылками на изображения. На выходе получилось что-то подобное:

Массив ассоциаций
а "✨","http://vk.com/images/emoji/2728.png"

б "❄","http://vk.com/images/emoji/2744.png"

в "🀄","http://vk.com/images/emoji/D83CDC04.png"

г "🃏","http://vk.com/images/emoji/D83CDCCF.png"

д "🆘","http://vk.com/images/emoji/D83CDD98.png"

е "🌂","http://vk.com/images/emoji/D83CDF02.png"

ё "🌍","http://vk.com/images/emoji/D83CDF0D.png"

ж "🌛","http://vk.com/images/emoji/D83CDF1B.png"

з "🌝","http://vk.com/images/emoji/D83CDF1D.png"

и "🌞","http://vk.com/images/emoji/D83CDF1E.png"

й "🌟","http://vk.com/images/emoji/D83CDF1F.png"

к "🌰","http://vk.com/images/emoji/D83CDF30.png"

л "🌱","http://vk.com/images/emoji/D83CDF31.png"

м "🌲","http://vk.com/images/emoji/D83CDF32.png"

н "🌳","http://vk.com/images/emoji/D83CDF33.png"

о "🌴","http://vk.com/images/emoji/D83CDF34.png"

п "🌵","http://vk.com/images/emoji/D83CDF35.png"

р "🌷","http://vk.com/images/emoji/D83CDF37.png"

с "🌸","http://vk.com/images/emoji/D83CDF38.png"

т "🌹","http://vk.com/images/emoji/D83CDF39.png"

у "🌺","http://vk.com/images/emoji/D83CDF3A.png"

ф "🌻","http://vk.com/images/emoji/D83CDF3B.png"

х "🌼","http://vk.com/images/emoji/D83CDF3C.png"

ц "🌽","http://vk.com/images/emoji/D83CDF3D.png"

ч "🌾","http://vk.com/images/emoji/D83CDF3E.png"

ш "🌿","http://vk.com/images/emoji/D83CDF3F.png"

щ "🍀","http://vk.com/images/emoji/D83CDF40.png"

ъ "🍁","http://vk.com/images/emoji/D83CDF41.png"

ы "🍂","http://vk.com/images/emoji/D83CDF42.png"

ь "🍃","http://vk.com/images/emoji/D83CDF43.png"

э "🍄","http://vk.com/images/emoji/D83CDF44.png"

ю "🍅","http://vk.com/images/emoji/D83CDF45.png"

я "🍆","http://vk.com/images/emoji/D83CDF46.png"

a "🍇","http://vk.com/images/emoji/D83CDF47.png"

b "🍈","http://vk.com/images/emoji/D83CDF48.png"

c "🍉","http://vk.com/images/emoji/D83CDF49.png"

d "🍊","http://vk.com/images/emoji/D83CDF4A.png"

e "🍋","http://vk.com/images/emoji/D83CDF4B.png"

f "🍌","http://vk.com/images/emoji/D83CDF4C.png"

g "🍍","http://vk.com/images/emoji/D83CDF4D.png"

h "🍎","http://vk.com/images/emoji/D83CDF4E.png"

i "🍏","http://vk.com/images/emoji/D83CDF4F.png"

j "🍐","http://vk.com/images/emoji/D83CDF50.png"

k "🍑","http://vk.com/images/emoji/D83CDF51.png"

l "🍒","http://vk.com/images/emoji/D83CDF52.png"

m "🍓","http://vk.com/images/emoji/D83CDF53.png"

n "🍔","http://vk.com/images/emoji/D83CDF54.png"

o "🍕","http://vk.com/images/emoji/D83CDF55.png"

p "🍖","http://vk.com/images/emoji/D83CDF56.png"

q "🍗","http://vk.com/images/emoji/D83CDF57.png"

r "🍚","http://vk.com/images/emoji/D83CDF5A.png"

s "🍛","http://vk.com/images/emoji/D83CDF5B.png"

t "🍜","http://vk.com/images/emoji/D83CDF5C.png"

u "🍝","http://vk.com/images/emoji/D83CDF5D.png"

v "🍞","http://vk.com/images/emoji/D83CDF5E.png"

w "🍟","http://vk.com/images/emoji/D83CDF5F.png"

x "🍠","http://vk.com/images/emoji/D83CDF60.png"

y "🍡","http://vk.com/images/emoji/D83CDF61.png"

z "🍢","http://vk.com/images/emoji/D83CDF62.png"

~ "🍣","http://vk.com/images/emoji/D83CDF63.png"

` "🍤","http://vk.com/images/emoji/D83CDF64.png"

! "🍥","http://vk.com/images/emoji/D83CDF65.png"

@ "🍦","http://vk.com/images/emoji/D83CDF66.png"

# "🍧","http://vk.com/images/emoji/D83CDF67.png"

$ "🍨","http://vk.com/images/emoji/D83CDF68.png"

% "🍩","http://vk.com/images/emoji/D83CDF69.png"

^ "🍪","http://vk.com/images/emoji/D83CDF6A.png"

& "🍫","http://vk.com/images/emoji/D83CDF6B.png"

* "🍬","http://vk.com/images/emoji/D83CDF6C.png"

( "🍭","http://vk.com/images/emoji/D83CDF6D.png"

) "🍮","http://vk.com/images/emoji/D83CDF6E.png"

_ "🍯","http://vk.com/images/emoji/D83CDF6F.png"

+ "🍰","http://vk.com/images/emoji/D83CDF70.png"

" "🍱","http://vk.com/images/emoji/D83CDF71.png"

№ "🍲","http://vk.com/images/emoji/D83CDF72.png"

; "🍳","http://vk.com/images/emoji/D83CDF73.png"

: "🍴","http://vk.com/images/emoji/D83CDF74.png"

? "🍵","http://vk.com/images/emoji/D83CDF75.png"

- "🍶","http://vk.com/images/emoji/D83CDF76.png"

= "🍷","http://vk.com/images/emoji/D83CDF77.png"

/ "🍸","http://vk.com/images/emoji/D83CDF78.png"

\ "🍹","http://vk.com/images/emoji/D83CDF79.png"

0 "🍺","http://vk.com/images/emoji/D83CDF7A.png"

1 "🍻","http://vk.com/images/emoji/D83CDF7B.png"

2 "🍼","http://vk.com/images/emoji/D83CDF7C.png"

3 "🎀","http://vk.com/images/emoji/D83CDF80.png"

4 "🎁","http://vk.com/images/emoji/D83CDF81.png"

5 "🎂","http://vk.com/images/emoji/D83CDF82.png"

6 "🎃","http://vk.com/images/emoji/D83CDF83.png"

7 "🎄","http://vk.com/images/emoji/D83CDF84.png"

8 "🎅","http://vk.com/images/emoji/D83CDF85.png"

9 "🎈","http://vk.com/images/emoji/D83CDF88.png"

"пробел"  "🎉","http://vk.com/images/emoji/D83CDF89.png"


Кроме того был создан ещё один массив «сдвига». Внутри него содержались цифры от 0 до 9, которым также были присвоены уникальные символы. На самом деле можно было добавить больше цифр, это уже дело вкуса. Этот массив выглядит вот так:

Массив сдвига
 0 "🎊","http://vk.com/images/emoji/D83CDF8A.png"

 1 "🎋","http://vk.com/images/emoji/D83CDF8B.png"

 2 "🎌","http://vk.com/images/emoji/D83CDF8C.png"

 3 "🎍","http://vk.com/images/emoji/D83CDF8D.png"

 4 "🎎","http://vk.com/images/emoji/D83CDF8E.png"

 5 "🎏","http://vk.com/images/emoji/D83CDF8F.png"

 6 "🎐","http://vk.com/images/emoji/D83CDF90.png"

 7 "🎒","http://vk.com/images/emoji/D83CDF92.png"

 8 "🎓","http://vk.com/images/emoji/D83CDF93.png"

 9 "🎣","http://vk.com/images/emoji/D83CDFA3.png"


Важное замечание! Возможно, вы заметили, что и в первом, и во втором массивах есть цифры 0-9. Для того чтобы различать их, нужно обязательно присвоить каждой уникальный символ, не встречающийся ранее. Это важное условие для работы всего шифра.


Итак, теперь у нас есть всё для шифрования исходного сообщения. Сначала мы найдём два числа: число «сдвига» (границы 0-9) и число «позиции» (границы 0-«длина исходной строки»). Оба они генерируются случайным образом. Первая цифра будет определять тот самый сдвиг букв как в шифре цезаря, а второе число – это позиция внутри строки, на место которой мы будем вставлять смайлик из массива «сдвига», который соответствует числу «сдвига» (простите за тавтологию).

Стандартно делаем сдвиг в правую сторону, но заменяем их уже не на сдвинутую букву, а на её emoji символ. Во время шифрования, при наборе результирующей строки, следим за моментом, когда нужно будет вставить emoji символ числа «сдвига». На выходе у нас получается строка из одних только смайликов. Здесь нас ждёт самая главная проблема, которая связана скорее с корректным отображением смайликов. Поскольку многие браузеры могут отображать прямоугольники вместо нужных нам символов (хотя распознаванию внутри кода это нисколько не мешает), то мы оборачиваем их в с соответствующими ссылками на изображения. Таким образом, получается довольно красивый внешний вид шифра.

Пример шифрования:

«hello world» => imageimageimageimageimageimageimageimageimageimageimageimage
(отсюда не выходит скопировать шифр)

Сама функция шифрования выглядит вот так:

var str = document.getElementById("text").value;
 var res='';
 var key = getRandomInt(0,9);
 var key_insert = getRandomInt(0,str.length-1) ;
 for (var i=0;i<str.length;i++){
     if (i==key_insert) {res = res+'<img alt="'+numbers[key][1]+'" src="'+numbers[key][2]+'">';}
       for (var j=0;j<cipher.length;j++){
	 if (str[i].toUpperCase()==cipher[j][0].toUpperCase()) {
	  if ((j+key)>cipher.length-1) {
	   res = res+'<img alt="'+cipher[(j+key)-cipher.length][1]+'" src="'+cipher[(j+key)-cipher.length][2]+'">';
	   } else {
	   res = res+'<img alt="'+cipher[(j+key)][1]+'" src="'+cipher[(j+key)][2]+'">';
	   }	   
	 }
	}
 }


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

Пример дешифрования:

imageimageimageimageimageimageimageimageimageimageimageimage => «hello world»
(отсюда не выходит скопировать шифр)

Функция дешифровки:

function decodeEntities(encodedString) {
    var textArea = document.createElement('textarea');
    textArea.innerHTML = encodedString;
    return textArea.value;
}

var str = String(document.getElementById("text").value.toString());
 var res='';
 for (var i=0;i<str.length;i+=2){
   for (var j=0;j<numbers.length;j++){  
    if ( str[i]+str[i+1]==decodeEntities(numbers[j][1])) {var key = j}
   }
 }
 for (var i=0;i<str.length;i+=2){
    for (var j=0;j<cipher.length;j++){
	 if ( str[i]+str[i+1]==decodeEntities(cipher[j][1])) {
	  if ((j-key)<0) {res = res+cipher[cipher.length-(-1*(j-key))][0]} else {res = res+cipher[j-key][0]}
	 }
    }
 }

функция decodeEntities() нужна, чтобы преобразовать код emoji типа "" в символ. Также при сравнении букв мы складываем соседние элементы. Мне кажется причина здесь кроется в размере emoji, потому что только таким образом мы получим символ для сравнения (если попробовать вывести лишь один элемент по индексу, а не их сумму, то мы увидим пустоту).

К плюсам такого шифра можно отнести то, что его невозможно расшифровать методом «относительных частот», а также то, что ключ задает не пользователь, следовательно, сохранность шифра повышается.

Из недостатков – не все сайты «красиво» отображают шифр, если вообще его отображают. Мобильные приложения вообще выводят пустую строку место шифра (точнее сказать, так видит сообщение получатель, у отправителя будет строка из множества obj).

Простейшим улучшением будет являться увеличение массива «сдвига» или же добавления к каждой цифре внутри этого массива ещё одного уникального emoji символа.

Что имеем на данный момент: сайты почти всех социальных сетей адекватно отображают шифр. Мобильные приложения не очень дружат с ним. На андроиде emoji также имеют красивую обёртку. Иногда в процессе шифрования могут пропасть смайлики наподобие «:3», с чем это связано пока не выяснено.

Сам метод вы можете опробовать тут: emojicrypt.xyz
За основу взят шифр «Цезаря»: Wikipedia
Дизайн сайта сделан с помощью Material design lite: getmdl.io

Спасибо, что дочитали статью! Буду рад предложениям и замечаниям как по методу, так и по статье. И И (добра вам).

Комментарии (24)


  1. fsmorygo
    21.10.2015 14:46
    +10

    Все подобные виды шифрования элементарно угадываются методом частотного анализа.


    1. NetherNN
      21.10.2015 15:02
      +25

      Видимо про данную атаку будут рассказывать на следующей паре


      1. EndUser
        21.10.2015 15:26
        +6

        Данная атака была у Дойла в «Пляшущих человечках» ну очень давно. ;-)


        1. PavelMSTU
          21.10.2015 16:03
          +2

          Есть еще «Золотой Жук» Эдгара Аллана По.


          1. JIghtuse
            22.10.2015 16:11
            +1

            Интересно, что в рассказах используются разные подходы к дешифровке. У По как раз частотный анализ, у Дойла — понимание контекста сообщений.


    1. Diatlo
      22.10.2015 15:20

      А если часто встречающиеся символы избыточно добавить в таблицу в случайном порядке и выбирать рандомно?
      Например, дополнительных 10 букв О, 9 букв А и т.д., чтобы вероятность их появления сравнялось с большинством реже используемых букв?


      1. mird
        22.10.2015 16:04

        Это не поможет. Вы все равно не добьетесь semantic security.


      1. maximw
        22.10.2015 18:39

        Если добавить много-много дополнительных букв, то по сути вы получите Книжный шфир, который так же неустойчив к частотному анализу, хотя и гораздо более надежен, чем представленный здесь шифр Цезаря.


  1. maximw
    21.10.2015 15:30
    +3

    А как именно звучало задание вашего преподавателя?


    1. mo3golom
      21.10.2015 16:58
      +1

      Придумать свой способ шифрования. Можно было использовать в качестве основы уже известные методы.


      1. lorc
        21.10.2015 17:14
        +1

        Не интересней было бы например попробовать расширить размер ключа у того же Rijandel (aka AES)?
        Или взять DES и придумать новый метод порождения раундовых ключей? Или попробовать сделать блочный алогоритм основаный на SHA1?


        1. mo3golom
          21.10.2015 17:24

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


          1. maximw
            21.10.2015 20:56
            +3

            Формально вы сделали задание. Странно что преподаватель дал такое без подготовки.
            Про задание я спрашивал как раз к тому, что озвучил lorc. Мне интереснее было бы реализовать что-то более хитрое, любительски-необычное или расковырять и дополнить что-то серьезное. Но шифр заменой 1 к 1 знали люди, которые еще толком считать не умели, только вместо эмодзи были какие-нибудь пиктограммы.

            Кстати, даже эмодзи у вас не настоящие, т.к. это символы Unicode. А у вас png картинки.


            1. symbix
              22.10.2015 02:51
              +1

              > Странно что преподаватель дал такое без подготовки.

              Разумно предположить, что на следующем занятии будут показаны атаки на эти простейшие шифры :)


            1. mo3golom
              22.10.2015 03:49
              +1

              Спасибо за замечание. Уже понял, что шифр весьма прост, в дальнейшем постараюсь сделать что-то более сложное. Насчет символов, они хорошо отображаются если их вставлять, но при простом копировании и вставке получались прямоугольники. Png картинки были сделаны в угоду красивого представления шифра


      1. JustCrazy
        22.10.2015 11:14
        +1

        МГТУ им. Н. Э. Баумана, преподаватель Лебедев А. Н.?


        1. mo3golom
          22.10.2015 12:00

          Нет, СФУ ИМиФИ, преподаватель Кирко И.Н.


          1. JustCrazy
            22.10.2015 12:09

            У нас в прошлом семестре преподаватель такое задание давал. Студенты придумали шифрование на основе числа пи, модифицированный aes (не помню точно что меняли) и использование нескольких алгоритом шифрования. В последнем суть была в использовании некоторого ключа, по которому определялась последовательность использования алгоритмов. Так же из бонусов можно было использовать его или его хэш как часть ключа шифрования, что позволяло усложнить дешифрацию.


  1. istui
    21.10.2015 16:14

    На iOS вроде бы emoji имеют нативную поддержку ОС — мобильные приложения также должны отображать их? Или я не в курсе всех нюансов?


    1. Antti
      21.10.2015 18:31

      А где вообще речь идет об iOS?
      А так вообще да, emoji уже почти везде отображаются.


    1. Finesse
      22.10.2015 06:47

      Эмодзи уже давно часть юникода и поддерживаются на большинстве современных ОС


  1. gto
    21.10.2015 17:40
    +2

    Имхо, на таком же уровне, с квадратом Виженера интереснее получилось бы.


  1. vilgeforce
    21.10.2015 17:47

    «К плюсам такого шифра можно отнести »… Посмотрел на Hello World и явственно вижу что одной букве всегда сопоставляется одна картинка. Так и должно быть и никаких достоинств нет или это у меня крыша съехала?


  1. Xfrid
    21.10.2015 22:21
    +1

    А разве сдвиг усиливает степень шифрования, если вы все равно заменили буквы другими символами?