Осторожнее с копипастом: фингерпринтинг текста непечатаемыми символами

https://medium.com/@umpox/be-careful-what-you-copy-invisibly-inserting-usernames-into-text-with-zero-width-characters-18b4e6f17b66
  • Перевод
Не хотите читать? Посмотрите демо.

Символы нулевой ширины — это непечатаемые управляющие символы, которые не отображаются большинством приложений. Н​апример, в э​то пред​ложение я вст​авил де​сять про​​белов н​улевой ширины, вы эт​о замет​или? (Подсказка: вставьте предложение в Diff Checker, чтобы увидеть местоположение символов!). Эти символы можно использовать как уникальные «отпечатки» текста для идентификации пользователей.


Безусловно, он может здесь быть. И вы никогда не догадаетесь

Зачем?


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

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

После недавнего поста Зака Айсана стало понятно, что людям интересна тема непечатаемых символов. Так что я решил опубликовать этот метод здесь вместе с интерактивной демонстрацией для всех. Примеры кода обновлены для современного JavaScript, но общая логика одинакова.

Как?


Точные шаги и логика описаны ниже, но если в двух словах: строка имени пользователя преобразуется в двоичную форму, затем двоичный файл преобразуется в серию непечатаемых символов, представляющих каждый бит. Потом непечатаемая строка незаметно вставляется в текст. Если текст опубликован на другом сайте, строку непечатаемых символов можно извлечь и провести обратный процесс, чтобы выяснить имя пользователя, который сделал копипаст!

Фингерпринтинг текста


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

Здесь мы просто преобразуем каждую букву имени пользователя в двоичный эквивалент.

const zeroPad = num => ‘00000000’.slice(String(num).length) + num;
const textToBinary = username => (
  username.split('').map(char =>
    zeroPad(char.charCodeAt(0).toString(2))).join(' ')
);

2. Взять имя пользователя в бинарном формате и преобразовать его в непечатаемые символы

Следующий скрипт перебирает двоичную строку и преобразует каждый бит 1 в непечатаемый пробел, каждый 0 — в непечатаемый символ запрета лигатур (non-joiner). После преобразования каждой буквы вставляем непечатаемый символ разрешения лигатур (joiner) — и переходим к следующей.

const binaryToZeroWidth = binary => (
  binary.split('').map((binaryNum) => {
    const num = parseInt(binaryNum, 10);
    if (num === 1) {
      return '​'; // zero-width space
    } else if (num === 0) {
      return '‌'; // zero-width non-joiner
    }
    return '‍'; // zero-width joiner
  }).join('') // zero-width no-break space
);

3. Вставка «имени пользователя» в непечатаемый конфиденциальный текст

Здесь просто вставляем блок непечатаемых символов в конфиденциальный текст.

Извлечение имени пользователя из помеченного текста


Те же действия в обратном порядке.

1. Извлечь непечатаемое «имя пользователя» из конфиденциального текста

Удалить конфиденциальный текст из строки, оставив только непечатаемые символы.

2. Преобразовать непечатаемое «имя пользователя» обратно в двоичный файл

Здесь мы разбиваем строку на фрагменты, с учётом добавленных межбуквенных разделителей. Это даёт эквивалент в управляющих символах для каждой буквы имени пользователя! Перебираем символы и возвращаем 1 или 0, чтобы воссоздать двоичную строку. Если не находим соответствующий 1 или 0, то значит попали на межбуквенный разделитель (символ разрешения лигатур) и, таким образом, завершиили двоичное преобразование для символа: можно добавить к строке один пробел и переходить к следующему символу.

const zeroWidthToBinary = string => (
  string.split('').map((char) => { // zero-width no-break space
    if (char === '​') { // zero-width space
      return '1';
    } else if (char === '‌') {  // zero-width non-joiner
      return '0';
    }
    return ' '; // add single space
  }).join('')
);

3. Преобразование имени пользователя из двоичного формата обратно в текст

В конце концов, анализируем двоичную строку и преобразуем каждую серию 1 и 0 в соответствующий символ.

const binaryToText = string => (
  string.split(' ').map(num =>
    String.fromCharCode(parseInt(num, 2))).join('')
);

Заключение


Компании как никогда много внимания уделяют утечкам информации и поиску инсайдеров. Этот лишь один из многих трюков, которые можно использовать. В зависимости от направления вашей работы, может быть жизненно важно понимать риски, связанные с копированием текста. Очень немногие приложения отображают непечатаемые символы. Например, вы можете предположить, что ваш терминал попытается их отобразить (мой нет!).

Если вернуться к секретной доске объявлений, то план сработал как надо. Вскоре после внедрения скрипта вышло новое объявление. В течение нескольких часов текст распространили в другом месте с прикрепленной непечатаемой строкой. Имя пользователя виновника успешно идентифицировали, и его забанили: хэппи-энд!

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

Чтобы поиграться со скриптом, запускайте демо или смотрите исходный код.
Поделиться публикацией
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 107
    –31
    «Фингерпринтинг» звучит как брейнфакинг
      +1
      Пальцеотпечаток из кук хабра сотрите.
    +11
    Шикарная история. Ещё одной параноей по слежке прибавилось. И ещё добавлю что от этих скрытых символов сложно избавиться, как, например, от форматирования. Если вставить в блокнот, потом снова скопировать, то символы сохранятся, а форматирование нет.
      0
      Вариант для чужого офисного компьютера: вставлять в word с включённым отображением всех знаков
        +1
        Вариант, работающий на 146%: перенабрать текст вручную (или использовать OCR).
          0
          Либо использовать стандартный блокнот. При сохранении текста с кодировкой ANSI он выдаст предупреждение, что используются Unicode символы, и все скрытые непечатаемые символы улетают в трубу.
            +2
            Подменять иногда рус на лат символы с одинаковым начертанием. Фиг кто заметит при беглом просмотре.
              0
              Word выделяет такие слова как ошибочные.
                0
                Об этом не подумал. Но блокнот, вроде не проверяет. Хотя ворд периодически выделяет и правильные, слишком большое количество может быть подозрительным. Для больших текстов можно иногда добавлять второй пробел. Собственно в случае с большими текстами можно придумать массу синтаксически корректных замен, которые не спалить. Автоматически их делать для пары десятков вариантов тоже не проблема. Собственно идея давать различный текст подозреваемым была придумана не одну сотню лет назад.
                  0
                  <nerd>Только это был не текст, а словесная информация.</nerd>
                    0
                    Что есть «словесная» информация? Речь была об кусках теста с сайта (причём много их, как я понял), т.е. вполне подходит.
                    Формально — любая читаемая информация — текст. Даже числа и любые знаки. В т.ч. даже невидимые, как, собственно, в самой статье.
                    0
                    Для больших текстов можно иногда добавлять второй пробел.
                    Лишний пробел довольно легко заметить в тексте, даже не читая его, просто при беглом просмотре. Если только он не попадает на конец строки.
                      +1
                      Даже если так — кто его заподозрит? И тем более будет исправлять. Обычно такие тексты копируют по принципу «синтаксис и пунктуация автора сохранены», сиреч — не глядя. Опечатки тоже обычно не правят. Собственно тексты без ошибок (особенно для внутреннего пользования) сейчас не редкость, и мало кто обращает на это внимание. Или вместо обычных использовать неразрывные.
                      Добавить пару пробелов в уникальной для юзера комбинации и всё. А для длинных текстов и небольшого количества клиентов — даже одного. Даже если кто придерётся, что текст кривой — всегда можно сослаться на залипший пробел (кстати при перекосе пробела на старой клаве такое случается, как и при слишком задранной скорости автоповтора).
                  0

                  Вообще-то суть не в том, чтобы показать, что текст скопировали. А именно уличить того, кто его копирует. Смысл просто менять букву или пробел добавлять?

                    0
                    Вообще-то пробел можно добавлять в разные места, в уникальной для юзера комбинации. Потом просто по его положению можно узнать, какая из версий ушла. То, что текст скопирован известно уже по условию.
                      0
                      Дополнительная программа будет вставлять пробелы в случайные места, чтобы подставить кого-то другого?
                        0
                        Каким образом?
                        Чтобы подставить кого-то другого нужно как минимум:
                        1. Знать о том, что эта система вообще существует (т.е. это должен быть кто-то из очень своих)
                        2. Знать о том, какая комбинация кому соответствует (т.е. это должен быть кто-то из админов)
                        Собственно в любой случае тут уже не сработает никакой из вариантов предложенных в статье или комментариях.
                        0
                        Вобще-то пользователей может быть больше, чем комбинаций.
                          0
                          Прикинем приблизительно. Текст 100 слов (очень короткий):
                          один пробел: 100 вариантов.
                          2 пробела: ~10000
                          Опечатка (например довольно типичная — замена 2х соседних букв местами): ~300..400
                          Опечатка (замена символа): ~6000..7000
                          Подсчёты крайне приблизительные, но порядок прикинуть позволяют.
                          И 100 слов — это очень мало. В этом комментарии их примерно 40.
                            0
                            один пробел: 100 вариантов.
                            2 пробела: ~10000
                            Два пробела — примерно в два раза меньше, т.к. перестановка (обмен местами) двух пробелов ничего не меняет.

                            А идею с дополнительными пробелами (в т.ч. кодируемыми разными символами) я одобряю.
                              +1
                              Так я и написал, что приблизительно. Оценивал только порядок величин. Если уж придираться, то между 100 словами всего 99 пробелов :)
                            0
                            Если принять одинарный пробел за 0 а двойной за 1, то из 100 слов (то есть 100 пробелов) количество разных комбинаций получится 2^100, а это приблизительно 10^34. Ну ок, 2^99 (10^33).
                            При такой ёмкости можно даже применить избыточное кодирование с восстановлением.
                    0
                    Не. При желании можно, например, делать рандомные ошибки в словах. Потом по анализу можно поймать.
                      +1
                      Можно использовать разные типы кавычек, разные виды тире / дефисов / дефисоминусов / разделителей в телефонном номере / etc. Это ещё незаметнее.

                      И можно даже пойти ещё дальше и заменять слова на синонимы.
                        0
                        Самое надежное — сообщать каждому пользователю разную, взаимосключающую информацию! :)
                      0
                      Вариант, работающий на 146%: перенабрать текст вручную (или использовать OCR).


                      Я кстати думал, как можно было бы бороться с этим. От OCR можно защититься опечатками, небольшими изменениями пунктуации (дефис вместо тире, запятая вместо точки с запятой, знаки сноски, арабские/римские цифры в списках, кавычки).

                      С перенабором вручную уже сложнее — для фингерпринта понадобится тоже ручная работа. Можно фингерпринтить синонимами и парафразами. Выделить достаточное количество участков в тексте и задать для них варианты замены. Потом кодировать уникальный ID с помощью комбинации замен.
                      +1
                      На самом деле тут можно предложить и менее палевный вариант. Например подменять символы на подобные по начертанию, но из других кодовых страниц (можно спалить шрифтом, у которого начертания отличаются) или псевдорандомно вставлять обычный/неразрывный пробел (при некоторой внимательности можно заметить). Оба варинта вполне пройдут через блокнот и ворд (вроде неразрывные он не отличает от обычных при показе)
                        0
                        в ворде неразрывный пробел отличается от обычного, при включении непечатаемых символов сразу заметен.
                        Если текст направлен ограниченному количеству человек, можно вставить в середине предложение, в котором будут меняться синонимы слов в зависимости от пользователя. Затем по синонимам вычислять id пользователя. Еще лучше пораскидать таких слов по всему тексту в «случайном» порядке.
                          0
                          Ну как вариант я подобное и предлагал. Синонимы — муторно и требует ручной работы. Да и работает только для ну очень ограниченного количества. Проще заменить какие-либо часто встречающиеся обороты или слова. Это можно делать и автоматически. Ну и чем больше их в тексте — тем, очевидно, больше возможных комбинаций.
                            0
                            Работает только для ну очень ограниченного количества
                            Не знаю, что за ограниченное количество, но 40 синонимов хватит на 1 трлн человек. Ну либо 1 млрд + 8 бит на подпись.
                              0
                              1. 40 синонимов сходу подобрать не так просто.
                              2. Нам не нужны синонимы «от балды». Нужны синонимы именно для слов из текста, т.е. обязательно придётся использовать определённый набор слов.
                              3. Их нужно согласовывать с остальным текстом, что немного муторно делать автоматически.
                              Т.е. в целом использовать можно, но слишком сложно (imho)
                                0
                                Так не для одного же слова 40 синонимов. Для любых (по одному синониму на слово). Под синонимами можно подразумевать даже перестановку слов или частей предложения. Думаю, 40 наберётся очень быстро (зависит от размера текста).

                                А теперь для эксперимента подберём синонимы для этого комментария:
                                (Так|ну)(ведь)? не для одного (и того же|же|) слова (40|сорок) синонимов(. а для|. Для) любых (слов)? (по одному синониму на (одно)? слово). Под синонимами (можно подразумевать ←→ даже) перестановку (слов ← или → частей предложения). Думаю, (40|сорок) (, в зависимости от (размера|длины) текста, наберётся (достаточно|очень) быстро|СТАРЫЙ_ВАРИАНТ)

                                Итог: без проблем подобрал 13.58 синонимов даже к такому небольшому тексту. Этого хватит, чтобы найти одного пользователя из 12 тысяч. Это как-то плохо сочетается с «Работает только для ну очень ограниченного количества».
                                  0
                                  1. Это исключительно ручная работа под конкретный текст (о чём я и писал). Т.е. не автоматизируется. А теперь то же самое в 12 тысячах вариантов. Это же касается и перестановок.

                                  2. Как разрешать подобные варианты?
                                  любых (слов)? (по одному синониму на (одно)? слово).
                                  И это всего одно предложение. В длинном тексте это уже станет изрядной проблемой.
                                    0
                                    Очевидно, что я указываю только 13 синонимов, а все 12 тыс вариантов генерируются программой (на основе указанные мной синонимов). Поиск 13 синонимов да, не автоматизируется. Но составить 1 трлн вариантов программой — без проблем.

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

                                    2. Как разрешать подобные варианты?
                                    А что здесь не так? Все фразы корректны. Ничего разрешать не нужно. Примеры:

                                    • Так не для одного же слова 40 синонимов. Для любых (по одному синониму на слово).
                                    • Так не для одного же слова 40 синонимов. Для любых (по одному синониму на одно слово).
                                    • Так не для одного же слова 40 синонимов. Для любых слов (по одному синониму на слово).
                                    • Так не для одного же слова 40 синонимов. Для любых слов (по одному синониму на одно слово).

                                    На то они и синонимы, что не влияют на остальные части текста. Т. е. синонимы нужно подбирать так, чтобы они не могли ничего сломать. В моём случае так и подобрано.
                                      0
                                      2. Этот вариант — по сути конкретный набор под конкретный текст. Причём требует не только подбора вариантов, но и ручной разметки текста. Ибо нельзя просто взять и удалить или добавить «слово» в произвольном месте. Я совсем не это понимал под автоматизацией.

                                      1. Если у нас просто набор синонимов, который автоматически подставляется при подходящем случае — то возникает
                                      * проблема использования таких слов там, где замена не предполагается
                                      * проблема наличия в любом языке слов, имеющих больше одного смысла (решается очень внимательным подбором синонимов)
                                      * проблема словоформ. в англицком она ещё решаема, но в русском всё может быть очень сложно.
                                        0
                                        Ну так про ручную работу я ничего и не говорил :) Я говорил про утверждение «для ну очень ограниченного количества».

                                        А вообще предполагается, что найти синонимы придётся 1 раз, так и вычислить крысу. Если 40 — много, то 4 текста по 10 синонимов.

                                        Если же это защита интеллектуального произведения, то найти 40 синонимов значительно легче, чем написать статью/книгу. Здесь уже можно и каждый раз подбирать.
                                          0
                                          Так я уже давно согласился, что это вполне реально. Просто сложно. Ну и проблема наличия даже 40 штук никак не отметает проблем, указанных выше.

                                          В случае же книги (да и для любых реально больших текстов) как раз более простые и автоматические методы более эффективны (imho). Вероятность там что-то заметить сильно меньше, а места для сокрытия — больше.
                        0
                        Firefox тоже подчёркивает. Плюс прямо на странице он разрывает слово, если нужно перенести, поэтому я подвох заметил сразу.
                        0
                        Я уже давно думал, что для отслеживания эл.книг можно использовать лишние / опциональные знаки препинания, например, заменять точку запятой, или запятую на точку с запятой. Если выделить десятка два-три таких мест (а лучше сотню, для дублирования), то можно каждой продаваемой книжке присваивать свой индивидуальный код, а дальше смотреть, кто из покупателей выложил книгу на флибусту. Чтобы найти все такие места потребуется не один экземпляр купить.
                        +7
                        Схожие методы использовались на «околохакерских» форумах для идентификации каналов утечки информации.
                          +1

                          Это вы ещё не вспомнили 'вариант омега' про радиоигру разведок: помните точку в конце предложения?

                            +2
                            Это, если не ошибаюсь, история о том, как британцы, судя по всему, не без помощи инсайдера, спалили кучу своих агентов в европе супротив германской разведки. Агенты должны были помечать точкой(или отсутствием), что раскрыты, и они это делали, но руководство проигнорило, и на них полагались как на надежных. В итоге в «надежную» точку досылали людей на погибель…
                          +3
                          Например, вы можете предположить, что ваш терминал попытается их отобразить (мой нет!).

                          Н<200b>апример, в э<200b>то пред<200b>ложение я вст<200b>авил де<200b>сять про<200b><200b>белов н<200b>улевой ширины, вы эт<200b>о замет<200b>или?
                          Для тех кому интересно(Vim).
                            +11

                            Еще вот так их можно найти (если знать что они там есть!):


                            Двойной клик выделяет кусок текста, ограниченный пробелами.

                              0
                              Хмм firefox выделяет все слово…
                                0
                                firefox при попытке поиска «в это» говорит, что ничего не нашел
                                +1
                                Вчера как здесь читал про дополнение для Chrome, которое находит такие символы в тексте. Называется «Replace zero-width characters with emojis».
                                image. Похоже, статья перекликается с этим переводом.
                                  +1
                                  Чтобы избавится от этого недостатка, достаточно вставлять их до/после пробелов. Правда, текст для этого должен быть достаточно длинным.
                                    0
                                    у меня просто теги отображаются <200b> :|
                                  0

                                  Стандартный маковский тоже вполне справляется:


                                  Скрытый текст
                                    –1
                                    Edge прекрасно показывает все «пробелы».

                                    image
                                      +1
                                      Это не Edge пробелы так показывает, это они в комментарии так записаны были…
                                    +1
                                    Радует то, что в мессенджерах пересылка таких копипастов не работает.

                                    Например, вот так выглядит «скрытая» информация в Telegram:
                                    image

                                    Эффект блокнота :)
                                      0
                                      Зато в веб-версии Телеграма все прекрасно работает:
                                      image
                                        0
                                        Desktop, Linux:
                                        Telegram Desktop, Linux
                                          0
                                          Telegram Windows 8.1 работает:
                                          Скрин
                                          Yes
                                          0
                                          Боже, зачем так сложно-то?
                                          Во-первых любой нормальный rich-edit это покажет, во-вторых (вытекающее из первого) — ненадежно — символы могут быть потеряны при копировании или очистке и т.д.

                                          Кодирование есть куда проще — знаками пунктуации. Тире и дефисов в юникоде штук 5, замена точек на точку с запятой и т.д.

                                          Имея 5 вариантов — это уже 5 бит — 2^5 пользователей.

                                          Никто на это не обратит внимание, как на похожие по начертанию символы или что-то еще. Все привыкли, что типографика всегда страдает.
                                            +5
                                            Имея 5 вариантов — это уже 5 бит — 2^5 пользователей.

                                            Ух ты! Целых 32 пользователя!:)
                                              0
                                              Это на одних только тире и дефисах уже целых 32 пользователя, а если добавить многоточий, кавычек, апострофов…
                                              +1
                                              Не понял вашу комбинаторику.

                                              Если у тире пять вариантов, то одно тире в предложении даёт возможность идентифицировать 5 пользователей, два — 25 и так далее.

                                              Но если тире в тексте больше одного, то их подозрительное различие будет визуально заметно. То же с пробелами разной ширины.
                                                +1
                                                Имелось ввиду, что использовать символы там, где они и должны быть использованы. Даже в небольшом тексте практически всегда есть тире — вот их и использовать, только код символа использовать один из пяти.

                                                Кроме того, можно составить текст так, чтобы там были по смыслу определенная типографика, а дальше — играться.
                                              0
                                              Так удалось вычислить инсайдера или нет?
                                                +5
                                                Так удалось вычислить инсайдера или нет?

                                                Если дочитать статью до конца, то вопрос отпадет.
                                                  0
                                                  Почему-то не заметил то предложение. Спасибо!
                                                    0
                                                    Чего уж там, я тоже не дочитал до конца :)
                                                      0
                                                      Тоже фингерпринтинг… вычисляем тех, кто не дочитал статью :)
                                                      0

                                                      Концовка мягковато описана. С учётом "любви к нему" и усилий по вычислению, я прямо ждал ту картинку "он не сделал бекап и дропнул базу", ну или хотя бы что-то более суровое ("нашли его с группой товарищей и заставили вслух читать число пи до 1000 знака!"), чем просто забанили.

                                                  0
                                                  Н? апример, в э? то пред? ложение я вст? авил де? сять про?? белов н? улевой ширины, вы эт? о замет? или?
                                                  стандартный Windows cmd.exe
                                                    +5
                                                    Много лет назад, когда писатели-фантасты были гораздо ближе к фэндому, они давали свои первые версии романов своим знакомым (распространяя через фидо и затем интернет).
                                                    Однако для того, чтобы обезопаситься от утечек, многие из них каждому адресату отправляли тексты романов с некоторыми уникальными изменениями — лишний пробел между словами, запятая сдвинутая вправо, использование буквы «ё» там, где у других буква «е», и всё такое прочее. Не сказать, что утечки были массовой проблемой, но возможно в т.ч. потому, что получатели знали о возможном «фингерпринтстве», а инсайдеры более одного раза не могли предать чужое доверие.
                                                      0
                                                      С текстами на русском вообще легко. Найдите пять отличий: aceo (латиница) асео (кирилица). Правда, спеллчекер отметит И если это распечатать, а потом OCRить, то потеряется.
                                                      0

                                                      deleted

                                                        +1
                                                        SPOON SPOON SPOON
                                                          +5
                                                          Сделать скриншот и публиковать его, а не копипасту. Можно ещё немного размыть или снизить разрешение, чтобы что-то невидимое для глаз исказилось.
                                                          Так многие и делают, особенно на мобилах, бо скриншот — одно нажатие кнопок, а копипаста — та ещё затея.
                                                            +1
                                                            Кстати, стоило бы делать так:

                                                            const zeroWidthSpace = '​';
                                                            const zeroWidthNonJoiner = '‌';
                                                            const zeroWidthJoiner = '‍';
                                                            const zeroWidthNoBreakSpace = '';
                                                            
                                                            const binaryToZeroWidth = binary => (
                                                              binary.split('').map((binaryNum) => {
                                                                const num = parseInt(binaryNum, 10);
                                                                if (num === 1) {
                                                                  return zeroWidthSpace;
                                                                } else if (num === 0) {
                                                                  return zeroWidthNonJoiner;
                                                                }
                                                                return zeroWidthJoiner;
                                                              }).join(zeroWidthNoBreakSpace);
                                                            );
                                                            
                                                              +5
                                                              А ещё лучше:
                                                              const zeroWidthSpace = '\u200B';
                                                              const zeroWidthNonJoiner = '\u200C';
                                                              const zeroWidthJoiner = '\u200D';
                                                              const zeroWidthNoBreakSpace = '\uFEFF';
                                                              
                                                              0
                                                              Мне для отображения символов в строке нравится qaz.wtf.

                                                              По идее, таких сервисов в вебе должно быть навалом, но я почему-то нашёл только этот.

                                                              Если кто-то знает лучший инструмент (веб- или командной строки Линукс) — буду рад услышать.
                                                                +1
                                                                Попробуйте в демке стереть скопированный текст. Ничего не заметили?
                                                                  0
                                                                  На сколько я помню этих символов нулевой длинны немного больше чем 2…
                                                                  Плюс, как уже заметили выше есть еще одинаковые символы в разных языках.
                                                                  Т.е. даже если применять преобразование бинарного в… то гораздо оптимальнее преобразовывать в 4-, 8-, 16-ричный код (используя больше символов). Так меньше символов на тот же объем информации потребуется.
                                                                    0
                                                                    Вставил в консоль:
                                                                      0
                                                                      Заметил раньше, чем первое предложение начал читать.

                                                                      Подумал, что косяк переводчика, но нет, на хромиумовских браузерах таки пробела не видно.
                                                                        –1
                                                                        Мораль: если копипастишь, вставляй вначале в Notepad!
                                                                          +3
                                                                          Ожидал после такой эпичной завязки игры шпионов продолжения в том же стиле, а не достаточно скучным и простым баном в качестве очень быстрой развязки после кульминации, когда шпиона вычислили.
                                                                          Нашел инсайдера, который сливает данные? Просто прекрасно, теперь можно управлять сливаемыми данными! Т.е. тупо отправлять дезу, периодически проверяя, что на других сайтах именно деза с правильным отпечатком имени. И теперь начинается настоящая шпионская игра! Особенно для того, чтобы инсайдер не заметил изменения отношения и «все осталось как есть» (с доступом к архиву правильных записей, как вариант).
                                                                            0
                                                                            Объясните по подробнее пожалуйста.
                                                                            Вот это условие на первый взгляд вообще лишено смысла

                                                                             if (char === '​') {
                                                                                  return '1';
                                                                             } else if (char === '‌') {  
                                                                                  return '0';
                                                                              }
                                                                            
                                                                              0
                                                                              Там символы в кавычках разные, что очевидно.
                                                                              0
                                                                              Я действительно удивился тому, что введенной мной значение было отображено. Почему-то мне казалось, что в браузере Google Chrome данная проблема уже давно исправлена (хотя что-то мне подсказывает, что я что-то путаю).
                                                                                0
                                                                                Регулярные выражения спасут копипаст ;).
                                                                                <!DOCTYPE html>
                                                                                <html lang="ru">
                                                                                <head>
                                                                                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                                                                                <meta name="Keywords" content="refining" /><meta name="abstract" content="refining" /><meta name="description" content="refining" /><meta name="viewport" content="width=device-width, initial-scale=1"/>
                                                                                <title>Чистильщик</title>
                                                                                </head>
                                                                                <body style="text-align:center;margin:0;">
                                                                                <div>
                                                                                <textarea id='trash' type="text" style="width:90%;height:400px; text-align:center;"></textarea>
                                                                                </div>
                                                                                <button style="width:180px;height:60px;font: bold 20px/1.5 cursive; text-align:center;" id="_button">старт</button>
                                                                                <br/><br/>
                                                                                <div id="resultation"></div>
                                                                                <script>
                                                                                function refining(){
                                                                                	rG1='';
                                                                                	trash=String(document.getElementById('trash').value);
                                                                                	var sG1=new Array();
                                                                                	for(i=0;i<trash.length;i++){sG1[i]=trash[i].replace(/[^а-яА-яa-zA-Z_0-9-—!"№%?*()\[\]+=@#$%^&*{}:;"'?><.,|\ \\\/\n\	]/g, '\█');};		
                                                                                	for(i=0;i<sG1.length;i++){rG1+=sG1[i];};
                                                                                	document.getElementById('resultation').innerHTML=rG1;
                                                                                };
                                                                                document.getElementById('_button').onclick=refining;
                                                                                </script>
                                                                                </body>
                                                                                </html>
                                                                                
                                                                                  0
                                                                                  Такие пробелы нулевого размера и другие скрытые символы можна обнаружить еще на стадии копирования, с помощью обычной консоли браузера.
                                                                                    +2
                                                                                    У этого метода есть значительный минус. При использовании программ экранного доступа, которыми пользуются незрячие, эти символы видны, их можно удалить или изменить при копировании.
                                                                                    Также такой текст очень неудобно слушать. Вот прочитайте написанный в посте текст вслух: так он и читается скринридером:
                                                                                    «Н апример, в э то пред ложение я вст авил де сять про белов н улевой ширины, вы эт о замет или?»

                                                                                    P. S. Сам символ озвучивается при посимвольном чтении, как «Пробел нулевой ширины».
                                                                                      0
                                                                                      А дать ограниченному кругу пользователей вообще разный текст — не рассматриваем? Зачем мудрить со скрытыми символами? Задача в том, чтобы найти подлеца, а не в написании кучи скриптов…
                                                                                        0
                                                                                        Занятная вещица, особенно учитывая если работаешь под TOR сетью, толку от TOR сети нет если ник светится.
                                                                                        Получается надо текст писать картинкой и тогда есть хоть какой то вариант не спалится, хотя и с картинкой можно опростоволоситься.
                                                                                          0
                                                                                          Было бы не плохо вставить ссылку в конце статьи на add-on для chrome, которое предупреждает о наличии таких символов.
                                                                                            0
                                                                                            эээ… приложение выпустили сотрудники литреса? ))
                                                                                          0
                                                                                          Н​апример, в э​то пред​ложение я вст​авил де​сять про​​белов н​улевой ширины, вы эт​о замет​или?
                                                                                          ©Opera 12.16
                                                                                            0
                                                                                            Нужно зайти в Оперу, чтобы понять смысл этого комментария. Выше я выложил принтскрин.
                                                                                              0
                                                                                              Ступил. Пользоваться предпросмотром из-под того же браузера — это новое определение оптимизма)
                                                                                            0
                                                                                            image
                                                                                              –1
                                                                                              Попробовал повторить на Vivaldi, не получилось:
                                                                                              Yes
                                                                                                0
                                                                                                Оу, понял свою ошибку, прошу прощения. Неверно понял сообщение выше, не обратил внимания на правую часть…
                                                                                              0
                                                                                              А как же с использованием чисто ASCII?
                                                                                              При копировании я всегда снимаю оформление и выполняю подмену UTF-8 на ASCII.
                                                                                              Мне кажется что игра с пробелами (1 или 2), замена сходных букв кириллицы на латиницу, а также передача не чисто имени, а уникального ID даст больше эффекта и скрытности.
                                                                                                –1

                                                                                                Я не понял, так нашли того, кто сливал инфу или нет?

                                                                                                  0
                                                                                                  Взгляд с другой стороны. А сделал уже кто-нибудь онлайн сервис для быстрой проверки текста на наличие скрытых встроенных символов?
                                                                                                  0
                                                                                                  echo "Н​апример, в э​то пред​ложение я вст​авил де​сять про​​белов н​улевой ширины, вы эт​о замет​или?" | iconv -c -t cp1251 | iconv -f cp1251
                                                                                                  


                                                                                                  Все не 8-битные символы идут в сад.

                                                                                                  Можно пойти дальше. рандомно подставлять похожие символы из других кодовых таблиц, добавлять-убирать пробелы перед знаками пунктуации…
                                                                                                    0
                                                                                                    Та в нашем мире паранойя — это норма
                                                                                                      0
                                                                                                      Я таким образом, правда проще (обычными табами и пробелами), подписывал исходный код скриптов которые продавал, было это лет 10 назад.

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

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