零宽度字符:和谐?屏蔽?不存在的

对零宽度字符彻底没有头绪的能够先玩下这个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

相关文章
相关标签/搜索