利用"零宽字符"隐藏你的小秘密

Posted bisal(Chen Liu)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用"零宽字符"隐藏你的小秘密相关的知识,希望对你有一定的参考价值。

什么是"零宽空格"?》文章中提到零宽空格可以"传递隐密信息",有朋友提出不太理解这是怎么做到的,检索了些资料,还是很涨姿势的。

参考原文:https://zhuanlan.zhihu.com/p/75992161

零宽字符

零宽字符是一种在浏览器中不打印的字符,大致相当于 display: none ,在许多文本应用中也不显示,例如邮箱、QQ、微信、文本编辑器等。

这里有三种零宽字符 -- 零宽空格、零宽连字、零宽不连字,

零宽字符在浏览器中对应的转义字符

零宽空格    --- ​  
零宽不连字  --- ‌
零宽连字    --- ‍

摩斯电码

摩斯电码采用长短两种符号进行文本加密,通过字典进行加密和解码,摩斯电码字典如下图所示,

我们使用/作为分隔符将 morse 这个单词转换为摩斯电码就是,

morse  ->   --/---/.-./.../.

现在我们再将 / 替换为零宽空格; - 替换问零宽连字;. 替换为零宽不连字,

/   -->    ​
.   -->    ‌
-   -->    ‍

那么就能将morse这个单词转换为如下零宽字符,

‍‍​‍‍‍​‌‍‌​‌‌‌​‌

将这段零宽字符粘贴进一个html文件当中,

<p>前</p>
<div>&#8205;&#8205;&#8203;&#8205;&#8205;&#8205;&#8203;&#8204;&#8205;&#8204;&#8203;&#8204;&#8204;&#8204;&#8203;&#8204;</div>
<p>后</p>

在浏览器中打开这个HTML文件,你只能看到 "前后" 两个字。

密码字典

我们要建立两个字典,一个加密字典,一个解密字典。

建两个数组分别存储 a-z 和 0-9 对应的莫斯码,

const morseWords = ['.-','-...','-.-.','-..','.','..-.','--.','....','..','.---','-.-','.-..','--','-.','---','.--.','--.-','.-.','...','-','..-','...-','.--','-..-','-.--','--..']

const morseNumber = ['-----','.----','..---','...--','....-','.....','-....','--...','---..','----.']

使用索引对象来做字典,for循环生成对应加解密字典,

let wordsToMorse = ;
let morseToWords = ;
let morseToNum = ;

//a-z数组
let words = [];
for (let i = 10; i < 36; i++) 
  let j = i.toString(36);
  words.push(j);


//数字加密字典
let numToMorse = morseNumber;

//数字解密字典
for (let i in morseNumber)
    morseToNum[morseNumber[i]]=i;


//字母加密字典
for (let i in words) 
    wordsToMorse[words[i]] = morseWords[i];

//字母解密字典
for (let i in wordsToMorse) 
    morseToWords[wordsToMorse[i]] = i;

//合并解密字典
let decodeWords = Object.assign(morseToWords, morseToNum);

导出字典,这样就可以通过索引来查询字典,

/* morse.js */
export  wordsToMorse, morseToWords, morseToNum, numToMorse, decodeWords ;

/* encrypt.js */
import  wordsToMorse, morseToWords, morseToNum, numToMorse, decodeWords  form 'morse.js'

console.log(wordsToMorse['z'])      //--..
console.log(decodeWords['--..'])    //z

加密函数

主要两步,先转换摩斯电码,再使用零宽字符替换摩斯电码。

循环输入字符串,判断每个字符是字母还是数字,分别调用不同的数字/字母加密字典,将转换后的摩斯字符串使用 &#8205; 、 &#8204; 、 &#8203; 进行替换,

function incode(str) 
    if(typeOf str != 'string')
        return ;
    
    let res = [];
    let l = "&#8205;";
    let s = "&#8204;";
    let q = "&#8203;";
    for (let i in str) 
        let val = str[i];
        if (!!parseInt(val) || parseInt(val) == 0) 
          res.push(numToMorse[str[i]]);
         else 
          res.push(wordsToMorse[str[i]]);
        
    
    let encrypt = res.join("/");
    encrypt = encrypt.replace(/\\//g, q)
    encrypt = encrypt.replace(/\\./g, s)
    encrypt = encrypt.replace(/\\-/g, l)
    return encrypt;

解密函数

首先从待解密字符串中匹配零宽字符, 零宽字符在Unicode中的编码为 \\u200B \\u200C \\u200D|,在HTML中有两种显示,

HTML

&#8203;
&#8204;   -->  &zwnj
&#8205;   -->  &zwj
  1. 匹配出文本中的零宽字符

  2. 转换零宽字符为摩斯字符串

  3. 调用解密字典把摩斯码转换普通文本

function decode(text) 
    if(typeOf str != 'string')
        return ;
    
    let decode = [];
    //匹配文本中的零宽字符,并转换为摩斯码
    text.match(/(\\&\\#8203\\;|\\&\\#8204\\;|\\&\\#8205\\;|\\u200B|\\u200C|\\u200D|\\&zwnj\\;|\\&zwj\\;)+/g).map(temp => 
        temp = temp.replace(/\\&\\#8203\\;|\\u200B/g, "/");
        temp = temp.replace(/\\&\\#8204\\;|\\u200C|\\&zwnj\\;/g, ".");
        temp = temp.replace(/\\&\\#8205\\;|\\u200D|\\&zwj\\;/g, "-");
        let arr = temp.split("/");

        //调用解密字典转码
        for (let i in arr) 
            decode.push(decodeWords[arr[i]]);
        
    )
    return decode;

中文支持

我们已经实现对普通字符串的加密了,但是只支持英文和数字。

要实现中文加解密,主要思路是先对文本进行正则匹配,将其中的中文进行Unicode转码,转码后整段文本就变成了字母、数字、'\\' 的组合,我们在加解密字典中加上对 \\ 的支持,在 morse.js 文件中加上,

/* morse.js */
/* 附件字符 */
decodeWords['-...-'] = ' ';  //顺便把空格也加进字典
decodeWords[".--.-"] = "\\\\";
wordsToMorse["\\\\"] = ".--.-";

另外几点事项,

(1)pc版QQ不支持零宽字符,会显示空格,但手机版不会。

(2)中文转码长度大约是相同长度英文字符的6倍。

(3)零宽字符虽然看不见但是,但也是一个个字符,所以删除含有零宽字符的文本时,删到零宽字符时会删不动要把零宽字符全部删完才能接着往下删。

作者有个github,https://github.com/rover95/morse-encrypt,做的就是隐藏字符加密的操作,原理就是利用零宽字符对加密文本进行转码,嵌入到普通文本当中,从而隐藏加密内容。表面看起来是一段普通文本,复制粘贴不会丢。

例如我们要隐藏加密一个比特币钱包,将它写到"前"和"后"两个字中间,显示的时候,只看到"前后",

但其实它隐藏到了这两个字中间,通过解密,就可以得到真正隐藏的信息,

原图视频链接,https://raw.githubusercontent.com/rover95/morse-encrypt/master/src/assets/morse-b.gif

可以将密码、比特币钱包、重要信息、不可告人的秘密加密到文本然后存储到记事本,这个视频是个实际的使用场景,有些读者朋友可能开始蠢蠢欲动了,

如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,

近期更新的文章:

什么是"零宽空格"?

国产数据库应用调查统计

重罚15分,揭秘尤文图斯的财务迷云

MySQL定制化执行计划的功能

IPXX指的是什么?

近期的热文:

推荐一篇Oracle RAC Cache Fusion的经典论文

"红警"游戏开源代码带给我们的震撼

文章分类和索引:

公众号1100篇文章分类和索引

以上是关于利用"零宽字符"隐藏你的小秘密的主要内容,如果未能解决你的问题,请参考以下文章

什么是"零宽空格"?

什么是"零宽空格"?

让你的网页"抖起来"?!?

同态加密实现数据隐私计算,能让你的小秘密更加秘密

ie图标怎么隐藏

js控制div显示与隐藏,js利用"hover"属性