使用Unicode爲私密文本添加數字水印

若是你以爲能夠,請多點贊,鼓勵我寫出更精彩的文章🙏。
若是你感受有問題,也歡迎在評論區評論,三人行,必有我師焉
javascript

TL;DR

  • 前言
  • 思路解析
  • 相關知識點介紹
  • 代碼解析

前言

隨着數字時代的到來,能夠說一切的生活,都是基於網絡的。而在有些特定的場景中,涉及到私密信息的時候,老是會有心懷鬼胎的人去捏造事實和進行造謠,變成三人成虎的一個尷尬的局面。java

因此就須要一種技術去識別私密文本的發佈者。從而找出真兇網絡

思路解析

咱們是針對文本,來追本溯源找到始做俑者,而文本在頁面中是瞬息萬變的一種存在。因此咱們須要將可以辨識複製文本的操做人的信息冗餘到文本中,可是不能顯示的展示出來。ide

換句話說,咱們須要將表明操做人的信息悄無聲息的和待複製文本結合到一塊兒。ui

首先,有一點須要明確:在計算機中,不管是何種開發語言定義何種變量,最終在內存中都是基於二進制形式存貯。同時,二進制中的01都是存儲必定的信息的佔位符。也就是咱們還須要將二進制中的信息用特定的語言方式進行替換並顯示隱藏加密

因此咱們能夠將水印過程設計思路大體歸爲以下spa

新增水印設計

  • 用戶信息二進制化
  • 二進制信息顯示隱藏
  • 用戶信息與文本信息冗餘

解碼水印code

  • 獲取水印信息
  • 轉二進制化
  • 解析加密信息

相關知識點介紹

Unicode

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零寬空格和零寬鏈接符、零寬非鏈接符

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('')
);
複製代碼

tips

雖然咱們所說的零寬空格也好仍是零寬鏈接符也好,它這是表面上的不顯示,可是若是用代碼來查詢字符串的長度,他的長度爲0 '\u200A'.length ===1 //true

相關文章
相關標籤/搜索