若是你以为能够,请多点赞,鼓励我写出更精彩的文章🙏。
若是你感受有问题,也欢迎在评论区评论,三人行,必有我师焉javascript
随着数字时代的到来,能够说一切的生活,都是基于网络的。而在有些特定的场景中,涉及到私密信息的时候,老是会有心怀鬼胎的人去捏造事实和进行造谣,变成三人成虎的一个尴尬的局面。java
因此就须要一种技术去识别私密文本的发布者。从而找出真凶。网络
咱们是针对文本,来追本溯源找到始做俑者,而文本在页面中是瞬息万变的一种存在。因此咱们须要将可以辨识复制文本的操做人的信息冗余到文本中,可是不能显示的展示出来。ide
换句话说,咱们须要将表明操做人的信息悄无声息的和待复制文本结合到一块儿。ui
首先,有一点须要明确:在计算机中,不管是何种开发语言定义何种变量,最终在内存中都是基于二进制形式存贮。同时,二进制中的0
和1
都是存储必定的信息的占位符。也就是咱们还须要将二进制中的信息用特定的语言方式进行替换并显示隐藏。加密
因此咱们能够将水印过程设计思路大体归为以下spa
新增水印设计
- 用户信息二进制化
- 二进制信息显示隐藏
- 用户信息与文本信息冗余
解码水印code
- 获取水印信息
- 转二进制化
- 解析加密信息
What is Unicode
Unicode provides a unique number for every character, no matter what the platform, no matter what the program, no matter what the language.orm
Unicode中存在一些数码是没法在页面显示,可是他们用于特定场景。 例如咱们日常指定文本换行用的\n
用Unicode来表示就是U+000A
。
而零宽空格和零宽链接符、零宽非链接符也是相似的,都没法在页面中显示,可是存在实际意义
const zeroPad = num => '00000000'.slice(String(num).length) + num;
const textToBinary = username => (
username.split('').map(char =>
zeroPad(char.charCodeAt(0).toString(2))).join(' ')
);
复制代码
这里有几点须要解释: 上文中咱们说到,只须要将用户信息进行二进制处理就行。按正常思路只须要将文本进行char.charCodeAt(0).toString(2)
便可。
可是在字符进行二进制换行的时候,若是二进制是以0
开头的,会自动将冗余的0进行剔除。因此,咱们须要在将文本转为二进制以后,须要将缺失的0
进行补全 const zeroPad = num => '00000000'.slice(String(num).length) + num;
例如a
的二进制为1100001
是不够8位的。因此,须要将其补成01100001
,方便后面解码用。
const binaryToZeroWidth = binary => (
binary.split('').map((binaryNum) => {
const num = parseInt(binaryNum, 10);
if (num === 1) {
return '\u200b'; // 零宽空格
} else if (num === 0) {
return '\u200C'; // 零宽非链接符
}
return '\u200D'; // 零宽链接符
}).join('\uFEFF') // 零宽度非换行空格
);
复制代码
let encryptionText = '我是一个萌萌哒的汉子'+ binaryToZeroWidth('北宸南蓁')
复制代码
const zeroWidthChar = [
'\u200B', //零宽空格
'\u200C', //零宽非链接符
'\u200D', //零宽链接符
'\uFEFF', //零宽度非换行空格
]
const charArr = string.match(zeroWidthCharReg);
const binaryArr = charArr.join('').split(zeroWidthChar[2]);//加密信息是由零宽链接符所分割
const mark = binaryArr.map(binary => {
const binaryString = binary.split('').map(b => zeroWidthChar.indexOf(b)).join('');
const utf16 = parseInt(binaryString, 2);
return String.fromCharCode(utf16)
}).join('')
复制代码
const zeroWidthToBinary = string => (
string.split('\uFEFF').map((char) => { // 零宽度非换行空格
if (char === '\u200b') { // 零宽空格
return '1';
} else if (char === '\u200C') { //零宽非链接符
return '0';
}
return ' '; // 加密信息本身的文本分割
}).join('')
);
复制代码
该操做能够认为是加密的的逆向操做。
const binaryToText = string => (
string.split(' ').map(num =>
String.fromCharCode(parseInt(num, 2))).join('')
);
复制代码
虽然咱们所说的零宽空格也好仍是零宽链接符也好,它这是表面上的不显示,可是若是用代码来查询字符串的长度,他的长度为0 '\u200A'.length ===1 //true