零寬度字符:和諧?屏蔽?不存在的

對零寬度字符徹底沒有頭緒的能夠先玩下這個Demogit

什麼是零寬度字符?

零寬度字符是一些不可見的,不可打印的字符。它們存在於頁面中主要用於調整字符的顯示格式,下面就是一些常見的零寬度字符及它們的unicode碼和本來用途:github

  1. 零寬度空格符 (zero-width space) U+200B : 用於較長單詞的換行分隔
  2. 零寬度非斷空格符 (zero width no-break space) U+FEFF : 用於阻止特定位置的換行分隔
  3. 零寬度連字符 (zero-width joiner) U+200D : 用於阿拉伯文與印度語系等文字中,使不會發生連字的字符間產生連字效果
  4. 零寬度斷字符 (zero-width non-joiner) U+200C : 用於阿拉伯文,德文,印度語系等文字中,阻止會發生連字的字符間的連字效果
  5. 左至右符 (left-to-right mark) U+200E : 用於在混合文字方向的多種語言文本中(例:混合左至右書寫的英語與右至左書寫的希伯來語),規定排版文字書寫方向爲左至右
  6. 右至左符 (right-to-left mark) U+200F : 用於在混合文字方向的多種語言文本中,規定排版文字書寫方向爲右至左

零寬度字符能作什麼?

1. 傳遞隱密信息

利用零寬度字符不可見的特性,咱們能夠用零寬度字符在任何未對零寬度字符作過濾的網頁內插入不可見的隱形文本。下面是一個簡單的利用零寬度字符對文本進行加密解密JavaScript例子:web

加密
// 爲了代碼的簡潔與易讀性,如下代碼會忽略性能方面考量

const text = '123😀';

// Array.from 能讓咱們正確讀取寬度爲2的Unicode字符,例:😀
const textArray = Array.from(text);

// 用codePointAt讀取全部字符的十進制Unicode碼
// 用toString將十進制Unicode碼轉化成二進制(除了二進制,咱們也可使用更大的進制來縮短加密後的信息長度,以此提高效率)
const binarify = textArray.map(c => c.codePointAt(0).toString(2));

// 此時binarify中的值是 ["110001", "110010", "110011", "11111011000000000"],下一步咱們須要將"1","0"和分隔符映射到響應的零寬度字符上去

// 咱們用零寬度連字符來表明1,零寬度斷字符來表明0,零寬度空格符來表明分隔符
// 下面的''看上去像是空字符串,但其實都是長度爲1,包含零寬度字符的字符串
const encoded = binarify.map(c => Array.from(c).map(b => b === '1' ? '‍' : '‌').join('')).join('​');

// 此時encoded中包含的就是一串不可見的加密文本了

複製代碼

注:在使用零寬度字符進行加密時,請儘可能避免將加密後的隱形文本插入在明文的開頭或者結尾處,以此來避免隱形文本在複製時被遺漏數組

解密
// 接着上面的encoded
// 用分隔符(零寬度空格符)提取加密文本中的字符
const split = encoded.split('​');

// 將文本轉回成二進制數組
const binary = split.map(c => Array.from(c).map(z => z === '‍' ? '1' : '0').join(''));

// 此時binary中的值再次回到開始的 ["110001", "110010", "110011", "11111011000000000"]

// 最後一部只須要將二進制文本轉回十進制,再使用 String.fromCodePoint 就能夠獲得原文本了
const decoded = binary.map(b => String.fromCodePoint(parseInt(b, 2))).join('');

// 此時decoded中的值便是 "123😀"

複製代碼
應用
  1. 隱形水印瀏覽器

    經過零寬度字符咱們能夠對內部文件添加隱形水印。在瀏覽者登陸頁面對內部文件進行瀏覽時,咱們能夠在文件的各處插入使用零寬度字符加密的瀏覽者信息,若是瀏覽者又剛好使用複製粘貼的方式在公共媒體上匿名分享了這個文件,咱們就能經過嵌入在文件中的隱形水印輕鬆找到分享者了。工具

  2. 加密信息分享性能

    經過零寬度字符咱們能夠在任何網站上分享任何信息。敏感信息的審覈與過濾在當今的互聯網社區中扮演着相當重要的角色,可是零寬度字符卻能如入無人之境通常輕鬆地穿透這兩層信息分享的屏障。對比明文哈希表加密信息的方式,零寬度字符加密在網上的隱蔽性能夠說是達到了一個新的高度。僅僅須要一個簡單的識別/解密零寬度字符的瀏覽器插件,任何網站均可以成爲信息分享的遊樂場。網站

2. 逃脫詞匹配

// 利用零寬度字符來分隔敏感詞
const censored = '敏感詞';

let censor = censored.replace(/敏感詞/g, ''); // ''

// 使用零寬度空格符對字符串進行分隔
const uncensored  = Array.from(censored).join('​');

censor = uncensored.replace(/敏感詞/g, ''); // '敏​感​詞'

複製代碼
應用
  1. 逃脫敏感詞過濾ui

    經過零寬度字符咱們能夠輕鬆逃脫敏感詞過濾。敏感詞自動過濾是維持互聯網社區秩序的一項重要工具,只需倒入敏感詞庫和匹配相應敏感詞,便可將大量的非法詞彙拒之門外。使用諧音與拼音來逃脫敏感詞過濾會讓語言傳遞信息的效率下降,而使用零寬度字符能夠在逃脫敏感詞過濾的同時將詞義原封不動地傳達給接受者,大大提升信息傳播者與接受者之間交流的效率。加密

示例與小結

爲了更好地理解與使用零寬度字符,我爲你們提供了一個Demo工具庫,庫中提供了一些應用零寬度字符的常見方法(加密解密逃脫匹配...)。零寬度字符在頁面中的存在多是一個好事,但也多是一個壞事,一切都取決於你如何去使用零寬度字符。若是你不想在你的頁面中看到這些零寬度字符,你能夠選擇徹底過濾這些字符,可是這樣會形成一些特殊語言的排版問題。因此,請酌情謹慎處理這些隱形的字符。

最後給各位留一個小彩蛋

「I‏‍‏‌‏‎‍​‏‏‌‏‌‏​‏‌‌‌‍‎‍​‏‏‏‎‎​‏‏‌‏‌‏​‌‎‏‏‍‍​‏‏‎‎‎‍​‌‎‌​‏‍​‏‍​‌‏‎​‌‏‎​‌‎​‏​‌‎‌t’s not who I am underneath, but what I do that defines me.」 -Bruce Wayne

reference

Be careful what you copy: Invisibly inserting usernames into text with Zero-Width Characters by umpox

相關文章
相關標籤/搜索