unicode 零宽字符
unicode 官网:https://home.unicode.org/
unicode 各种类型详细介绍:https://www.compart.com/en/unicode/category/Cf
对零宽度字符完全没有头绪的可以先玩下这个Demo
在綫解密:https://330k.github.io/misc_tools/unicode_steganography.html
什么是零宽度字符?
零宽字符是一种特殊的 Unicode 字符,正如字面意思,它的宽度为零,也就是在文本中不占用任何显示空间。
它们存在于页面中主要用于调整字符的显示格式,下面就是一些常见的零宽度字符及它们的unicode码和原本用途:
零宽度空格 (zero-width space, ZWSP)
U+200B
: 用于较长单词的换行分隔- 就是一个显示宽度为零的空格,但是会强制换行或分隔单词
零宽度非断空格符 (zero width no-break space,BOM)
U+FEFF
: 用于阻止特定位置的换行分隔- 就是一个显示宽度为零的空格,但是不可以换行
零宽度断字符 (zero-width non-joiner,ZWNJ)
U+200C
: 用于阿拉伯文,德文,印度语系等文字中,阻止会发生连字的字符间的连字效果- 例如在德语中,字母组合“ff”应该被视为两个单独的字母,而不是一个单独的字符。
零宽度连字符 (zero-width joiner,ZWJ)
U+200D
: 用于阿拉伯文与印度语系等文字中,使不会发生连字的字符间产生连字效果- 它通常用于控制文本的排版和显示。常见的复杂Emoji表情即用到了该字符,用于表示多字符关系从而合成复杂新字符
零宽度字符能做什么?
1. 传递隐密信息
利用零宽度字符不可见的特性,我们可以用零宽度字符在任何未对零宽度字符做过滤的网页内插入不可见的隐形文本。下面是一个简单的利用零宽度字符对文本进行加密
与解密
的JavaScript
例子:
加密
1 |
|
// 接着上面的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 |
|
// 利用零宽度字符来分隔敏感词
const censored = ‘敏感词’;
let censor = censored.replace(/敏感词/g, ‘’); // ‘’
// 使用零宽度空格符对字符串进行分隔
const uncensored = Array.from(censored).join(‘’);
censor = uncensored.replace(/敏感词/g, ‘’); // ‘敏感词’
#### 应用
1. 逃脱敏感词过滤
通过零宽度字符我们可以轻松逃脱敏感词过滤。敏感词自动过滤是维持互联网社区秩序的一项重要工具,只需倒入敏感词库和匹配相应敏感词,即可将大量的非法词汇拒之门外。使用谐音与拼音来`逃脱敏感词过滤`会让语言传递信息的效率降低,而使用零宽度字符可以在`逃脱敏感词过滤`的同时将词义原封不动地传达给接受者,大大提高信息传播者与接受者之间交流的效率。