开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天
了解web隐写术之前,先了解一下什么是零宽字符。下面用到的分别是零宽不连字和零宽连字。
- 零宽不连字,全称Zero Width Non Joiner,是一个不打印字符,放在电子文本的两个字符之间,抑制本来会发生的连字(与‍相反)。在html中的编码(‌)
- 零宽连字,全称Zero Width Joiner,是不打印字符,使两个本不会发生连字的字符产生了连字效果,在html中的编码(‌)
- 零宽空格(zero-width space, ZWSP)是一种不可打印的Unicode字符,用于可能需要换行处。在html中编码(​)
零宽字符串加密原理:
上面三个字符在前端都是不渲染的,我们就利用其中的两个来进行加密,分别是零宽不连字和零宽空格。他们在浏览器中都是不渲染的,但又实际存在,然后利用上面的两个零宽字符分别代表0和1编码。首先我们对目标字符串转换成二进制字符串,然后在分别用两个零宽字符替换掉0和1,并且插入到浏览器的元素中,这样,通过零宽字符串加密的文本就生成了。
1.零宽加密
<div>有内鬼,<span id="badman">是你吗?</span></div>
//加密
const zeroPad = num => '00000000'.slice(String(num).length) + num;
//把字符串转换为二进制字符串
const textToBinary = username => (
username.split('').map(char =>
zeroPad(char.charCodeAt(0).toString(2))).join(' ')
);
//把二进制字符串转换为零宽字符串
const binaryToZeroWidth = binary => (
binary.split('').map((binaryNum) => {
const num = parseInt(binaryNum, 10);
if (num === 1) {
return ''; // 零宽空格
} else if (num === 0) {
return ''; // 零宽不连字
}
return ''; // zero-width joiner
}).join('') // zero-width no-break space
);
let binary=textToBinary("123") //这个'123'就是隐藏起来的实际内容
let zeroWidth=binaryToZeroWidth(binary)
let obj=document.getElementById('badman')
obj.innerText=zeroWidth+obj.textContent
2.如何逆向解码
也比较简单,首先把零宽字符串转换成二进制字符串
const zeroWidthToBinary = string => (
string.split('').map((char) => { // zero-width no-break space
if (char === '') { // 零宽空格
return '1';
} else if (char === '') { // 零宽不连字
return '0';
}
return ' '; // add single space
}).join('')
);
然后再把二进制字符串转换成普通字符串就行
const binaryToText = string => (
string.split(' ').map(num =>
String.fromCharCode(parseInt(num, 2))).join('')
);
3.如何生成unicode编码的零宽字符
上面判断条件里面的就有unicode编码的零宽字符,只是因为当前编辑器没有用unicode解码,所以在一些编辑器只显示了一个红点,或者直接不显示
那么如何生成unicode编码的零宽字符进而用到代码中去的呢?
首先找到比如零宽链接符的ASCII码,点击转换就行了,
转换成功后,右边的结果宽里不会显示,因为浏览器不显示零宽字符,但是确实是存在的,点击右边结果框,ctrl+A 复制就行了,然后添加到代码的条件判断里面。