两三个星期前,看到篇文章讲用零宽字符隐藏信息来抓那些xjb复制的人
Be careful what you copy: Invisibly inserting usernames into text with Zero-Width Characters
挤点时间出来记录一下,以免过目就忘
首先讲下零宽字符,零宽字符是一种不可打印的Unicode字符,包括零宽连字、零宽不连字、零宽空格。不显示的前提貌似是在浏览器上,我试了复制到qq和复制到编辑器里都是会格式错误,一眼就发现文本中藏了私货。然后讲如何编码与解码。
首先要将编码前的文本转为8位二进制的形式。
1
2
3
4
5
| const zeroPad = num => ‘00000000’.slice(String(num).length) + num;
const textToBinary = username => (
username.split('').map(char =>
zeroPad(char.charCodeAt(0).toString(2))).join(' ')
);
|
例如a
,将a
的ASCII码转为2进制形式,不足8位的在前面用0填充,每个8位间用空格隔开。
其次将其中的空格、0、1分别用对应的零宽字符替换
1
2
3
4
5
6
7
8
9
10
11
| const binaryToZeroWidth = binary => (
binary.split('').map((binaryNum) => {
const num = parseInt(binaryNum, 10);
if (num === 1) {
return ''; // zero-width space \u200b
} else if (num === 0) {
return ''; // zero-width non-joiner \u200c
}
return ''; // zero-width joiner \u200d
}).join('') // zero-width no-break space
);
|
这里将1用零宽空格\u200b
,0用零宽不连字\u200c
,空格用零宽连字\u200d
替换
这样就编码好了一段另类的二进制,将这段零宽字符插到文本中,就可以充当一种指纹,当别人无脑复制盗你的文章的时候,将他文章中的零宽字符解码后甩他脸上。他就无话可说了。
然后再讲下如何解码
首先是要将零宽字符还原成二进制
1
2
3
4
5
6
7
8
9
10
| const zeroWidthToBinary = string => (
string.split('').map((char) => { // zero-width no-break space
if (char === '') { // zero-width space \u200b
return '1';
} else if (char === '') { // zero-width non-joiner \u200c
return '0';
}
return ' '; // add single space
}).join('')
);
|
如果是\u200b
就替换成1,是\u200c
就替换成0,如果都不是就替换成空格,这样就还原了编码第一步后的二进制组了
然后就是还原二进制为ASCII码了
1
2
3
4
| const binaryToText = string => (
string.split(' ').map(num =>
String.fromCharCode(parseInt(num, 2))).join('')
);
|
挺有趣的一个技巧,在我搜索资料的过程中,我发现了有老哥用零宽来缩短代码显示和隐藏代码hhhhh
js 奇葩技巧之隐藏代码
“短”化你的代码