隐藏字符加密(写给女孩的隐秘情书)

隐藏字符加密(写给女孩的隐秘情书)

你是否曾经有许多话想对那个她说,却因为没有勇气而迟迟没有说出口,从而错过了一个又一个她
那么何不把你想说的话转换为隐藏字符发给她,这样在你错过下一个她的时候你就可以安慰自己 -- 不是我没说,只是她没发现

原理

1.零宽字符

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

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

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

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

2.摩斯电码

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


我们使用/作为分隔符将 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

加密函数

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

  1. 循环输入字符串,判断每个字符是字母还是数字,分别调用不同的数字/字母加密字典
  2. 将转换后的摩斯字符串使用 &#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. 零宽字符虽然看不见但是,但也是一个个字符,所以删除含有零宽字符的文本时,删到零宽字符时会删不动要把零宽字符全部删完才能接着往下删

在线地址 http://morse.rovelast.com

ok,现在就可以把你想说的话悄悄告诉她了

明明什么都对她说了,但她却一辈子也发现不了。。。简直浪漫


存储重要信息

也可以把你的密码、比特币钱包、重要信息、不可告人的秘密加密到文本然后存储到记事本,简直万无一失;
和当年的图种颇有几分相似

在你的代码埋下彩蛋

完整代码见
项目地址 github.com/rover95/mors

进去点个star

有人问我你究竟是哪里好
这么多年我还忘不了
春风再美也比不上你的笑
没见过你的人不会明了
发布于 2019-07-31