字符ascii码值转换_没想到 Unicode 字符还能这样玩?
? 腳本之家
你與百萬(wàn)開(kāi)發(fā)者在一起
來(lái)源 | 程序通事(ID:US_stocks)
如若轉(zhuǎn)載請(qǐng)聯(lián)系原公眾號(hào)
上周的時(shí)候,朋友圈的直升飛機(jī)不知道為什么就火了,很多朋友開(kāi)著各種花式飛機(jī)帶著起飛。
圖片來(lái)自網(wǎng)絡(luò)還沒(méi)來(lái)得及了解咋回事來(lái)著,這個(gè)直升飛機(jī)就?到的微博熱搜。
圖片來(lái)自網(wǎng)絡(luò)后面越來(lái)越多人開(kāi)來(lái)他們的直升飛機(jī),盤旋在朋友圈上方。于是很多朋友開(kāi)來(lái)他們的坦克,專打直升飛機(jī),一轟一個(gè)準(zhǔn)。
圖片來(lái)自網(wǎng)絡(luò)好了,說(shuō)回正題!
程序員朋友應(yīng)該都很熟悉 Unicode (萬(wàn)國(guó)碼),它幾乎包含世界上所有符號(hào),比如組成直升飛機(jī)這幾個(gè)特殊符號(hào)對(duì)應(yīng)的 Unicode 碼分別為:
ps:推薦一個(gè)網(wǎng)站,可以根據(jù)符號(hào)搜對(duì)應(yīng)的 Unicode 碼:https://unicode.yunser.com/unicode
除了這些正常字符以外,Unicode 還包含著各種各樣的奇葩字符。
奇葩字符
除了正常的我們熟知的文字以外,Unicode 中還有一些奇怪的文字,比如下面這些文字
這咋讀?某少?世代?恩?超出認(rèn)知范圍除了這些奇怪文字以外,Unicode 還有一些奇葩的的符號(hào)。
例如下面一整套麻將牌:
三缺一?一整套的撲克牌:
對(duì)三?要不起!一整套國(guó)際象棋:
不會(huì)玩--!除了這些,通過(guò)組合符合,我們還可以造出各種各樣的顏文字(??????)??、
另外 Unicode 還收錄著我們常用的 Emoji 。
除了這些之外,Unicode 中還有一些特殊字符的,利用這些字符,我們還可以玩出很多有趣的騷操作。
組合字符
Unicode 有一類字符稱為組合字符,它可以附加在前一個(gè)非組合字符上,從而使整體看起來(lái)像是一個(gè)字符。
組合字符原來(lái)目的是為了解決一些地區(qū)語(yǔ)言、文字特殊的需要,比如說(shuō)泰文聲調(diào)符號(hào)與母音符號(hào)。
正常使用的情況下,這些組合字符數(shù)量都會(huì)有一些限制。但是在 Unicode 組合字符設(shè)計(jì)上,并沒(méi)有加這種限制,這樣使我們可以無(wú)限加這類組合字符。
利用這個(gè)特性,可以達(dá)到一些惡搞效果,比如「擊穿天花板」與「鑿穿地板」的效果。
上面實(shí)現(xiàn)原理其是利用以下兩個(gè)組合字符:
上翻字符下翻字符只要復(fù)制這兩個(gè)字符相應(yīng)的 HTML 代碼,跟在正常的字符后面,就可以使這兩個(gè)字符附加在普通字符上,比如下面實(shí)現(xiàn)效果為
黑??Unicode 碼值通常使用 U+N(16 進(jìn)制N 代表碼值),比如 A 的碼值為 U+0041。
在 HTML 中 Unicode 可以使用 N;(十進(jìn)制,N 代表碼值)表示
在 JS 中 Unicode 中需要使用] \uN(16 進(jìn)制N 代表碼值)表示
只要我們?cè)谄胀ㄗ址鄰?fù)制幾個(gè)這類附加字符,就可以形成上述「擊穿」效果。
還記得上面說(shuō)的泰文嗎,曾經(jīng)有一段時(shí)間貼吧,很流行一種噴射文,比如下面的效果。
?
往左噴、往右噴、左右互噴這種噴射文實(shí)際原理就是利用泰文中聲調(diào)符號(hào)附加在其他正常符號(hào)上。
不過(guò)現(xiàn)在這個(gè)效果貌似已經(jīng)沒(méi)辦法再?gòu)?fù)現(xiàn)了,現(xiàn)在我們只能看到這樣的效果:
在一些老版本的系統(tǒng)/瀏覽器可能還能看到這種效果,知道的小伙伴留言區(qū)可以告知一下。
零寬字符
Unicode 中還有一類格式字符,不可見(jiàn),不可打印,主要作用于調(diào)整字符的顯示格式,所以我們將其稱為零寬字符。
零寬字符主要有以下幾類:
零寬度空格符 (zero-width space) U+200B : 用于較長(zhǎng)單詞的換行分隔
零寬度非斷空格符 (zero width no-break space) U+FEFF : 用于阻止特定位置的換行分隔
零寬度連字符 (zero-width joiner) U+200D : 用于阿拉伯文與印度語(yǔ)系等文字中,使不會(huì)發(fā)生連字的字符間產(chǎn)生連字效果
零寬度斷字符 (zero-width non-joiner) U+200C : 用于阿拉伯文,德文,印度語(yǔ)系等文字中,阻止會(huì)發(fā)生連字的字符間的連字效果
左至右符 (left-to-right mark) U+200E : 用于在混合文字方向的多種語(yǔ)言文本中(例:混合左至右書寫的英語(yǔ)與右至左書寫的希伯來(lái)語(yǔ)),規(guī)定排版文字書寫方向?yàn)樽笾劣?/p>
右至左符 (right-to-left mark) U+200F : 用于在混合文字方向的多種語(yǔ)言文本中,規(guī)定排版文字書寫方向?yàn)橛抑磷?/p>
利用零寬字符不不可見(jiàn)的特性,我們也可以玩出一些騷效果。
空白微博
發(fā)布微博的時(shí)候,如果內(nèi)容都是空格,將沒(méi)辦法發(fā)布。
但是如果我們將零寬字符,比如說(shuō)「零寬度空格符 U+200B」復(fù)制到微博,這樣我們就可以發(fā)布空白微博。
我們可以利用 Chrome 瀏覽器的控制臺(tái)復(fù)制零寬字符,操作方式如下:
發(fā)布效果如下:
真的沒(méi)有改 HTML 導(dǎo)致的.jpg隱形水印
對(duì)于一些內(nèi)部論壇或者說(shuō)小說(shuō)網(wǎng)站來(lái)說(shuō),可以通過(guò)零寬字符在帖子或小說(shuō)內(nèi)容嵌入隱形水印。
當(dāng)這些內(nèi)容被一些爬蟲(chóng)復(fù)制到其他網(wǎng)站時(shí),我們就可以通過(guò)隱形水印,輕松查找時(shí)那位用戶泄漏內(nèi)容。
隱形水印主要原理就是將用戶信息比如用戶名,通過(guò)一定算法轉(zhuǎn)成零寬字符,這樣普通用戶瀏覽時(shí)完全看不到這個(gè)水印。
如果內(nèi)容被復(fù)制到其他網(wǎng)站,隱形誰(shuí)贏也被復(fù)制,只要找到這個(gè)水印,將這些零寬字符反轉(zhuǎn)成用戶名即可。
下面展示一種轉(zhuǎn)換方法,JS 代碼主要參考以下 Github 項(xiàng)目:
https://github.com/umpox/zero-width-detection
隱形水印生成方法
第一步我們需要將明文字符串每個(gè)字符都轉(zhuǎn)成二進(jìn)制串。
????//?每個(gè)字符轉(zhuǎn)為二進(jìn)制,用空格分隔????const?textToBinary?=?username?=>?(
??????username
??????.split('')
??????//?charCodeAt?將字符轉(zhuǎn)成相應(yīng)的?Unicode?碼值
??????.map(char?=>?char.charCodeAt(0).toString(2))
??????.join('?')
????);
示例如下:
第二步,將二進(jìn)制串轉(zhuǎn)為零度字符串,轉(zhuǎn)換規(guī)則如下:
- 1 轉(zhuǎn)換為 \u200b 零寬度字符(zero-width space)
- 0 轉(zhuǎn)換為 \u200c 零寬度斷字符(zero-width non-joiner)
- 其他(剩余就是空格) 轉(zhuǎn)換為 \u200d 零寬度連字符 (zero-width joiner)
- 最后使用 \ufeff 零寬度非斷空格符 (zero width no-break space) 作為分隔符
??binary.split('').map((binaryNum)?=>?{
????const?num?=?parseInt(binaryNum,?10);
????if?(num?===?1)?{
??????return?'\u200b';?//?\u200b?零寬度字符(zero-width?space)
????}?else?if(num===0)?{
??????return?'\u200c';?//?\u200c?零寬度斷字符(zero-width?non-joiner)
????}
????return?'\u200d';?//?\u200d?零寬度連字符?(zero-width?joiner)
??}).join('\ufeff')?//?\ufeff?零寬度非斷空格符?(zero?width?no-break?space)
);
最終加密方法如下:
const?encode?=?username?=>?{??const?binaryUsername?=?textToBinary(username);
??const?zeroWidthUsername?=?binaryToZeroWidth(binaryUsername);
??return?zeroWidthUsername;
};
使用加密方法將明文字符串加密之后,加密字符串肉眼是看不到了,但是實(shí)際還是存在的。
實(shí)際上,如果我們將加密之后字符串復(fù)制到 ?BEJSON 網(wǎng)站,就可以看到字符。
另外你還可以把加密字符串復(fù)制到 IDEA 中,可以看到相應(yīng)的 Unicode 編碼值。
解密隱形水印
知道了加密的方式,解密其實(shí)就很簡(jiǎn)單,我們只要按照相反步驟的來(lái)就可以了。
第一步,將隱形水印按照以下規(guī)則轉(zhuǎn)換為二進(jìn)制串。轉(zhuǎn)換規(guī)則如下:
- 使用 \ufeff 分隔字符串
- \u200b 轉(zhuǎn)為 1
- \u200c 轉(zhuǎn)為 0
- 其他字符使用空格
??string.split('\ufeff').map((char)?=>?{?//?\ufeff?零寬度非斷空格符?(zero?width?no-break?space)
????if?(char?===?'\u200b')?{?//?\u200b?零寬度字符(zero-width?space)
??????return?'1';
????}?else?if(char?===?'\u200c')?{?//?\u200c?零寬度斷字符(zero-width?non-joiner)
??????return?'0';
????}
????return?'?';
??}).join('')
);
調(diào)用該方法,隱形水印轉(zhuǎn)成二進(jìn)制串。
第二步,將二進(jìn)制再轉(zhuǎn)為相應(yīng)的字符。
const?binaryToText?=?string?=>?(??//?fromCharCode?二進(jìn)制轉(zhuǎn)化
??string.split('?').map(num?=>?String.fromCharCode(parseInt(num,?2))).join('')
);
最終解密方法如下:
const?decode?=?zeroWidthUsername?=>?{??const?binaryUsername?=?zeroWidthToBinary(zeroWidthUsername);
??const?textUsername?=?binaryToText(binaryUsername);
??return?textUsername;
};
解密示例如下:
短網(wǎng)址
我們常用的短網(wǎng)址,域名后面會(huì)跟上一串隨機(jī)串,從而實(shí)現(xiàn)短網(wǎng)址到長(zhǎng)網(wǎng)址的映射。比如以下網(wǎng)址:
https://sourl.cn/iLyn9S
然而我們可以利用零寬字符也可以實(shí)現(xiàn)短網(wǎng)址的效果,,比如下面這個(gè)網(wǎng)站,就可以生成這類短網(wǎng)址。
https://zws.im/
可以看到這個(gè)短網(wǎng)址后面看不到任何字符,實(shí)際上這后面跟著一串零寬字符。當(dāng)瀏覽器訪問(wèn)該短網(wǎng)址時(shí),后端程序只要反解密的后面零寬字符,拿到相應(yīng)的網(wǎng)址,然后在做跳轉(zhuǎn)就可以到指定的網(wǎng)站。
反解密的原理可以參考上面隱形水印的代碼
小心零寬字符
日常開(kāi)發(fā)過(guò)程中,我們有時(shí)需要從一些文件中讀取文本內(nèi)容,然后做相應(yīng)的處理。
有時(shí)候我們可能會(huì)碰到一些詭異的現(xiàn)象,比如我們之前碰到的例子。
后臺(tái)程序從 Excel 讀取文本內(nèi)容,然后程序中判斷是讀取的文本內(nèi)容是否與指定的字符串相等。
然后當(dāng)我們讀取一份 Excel 內(nèi)容后,返現(xiàn)這段比較邏輯怎么也通過(guò)不了。本來(lái)以為是 Excel 內(nèi)容存在空格什么的,但是打開(kāi) Excel 仔細(xì)一看,跟指定字符串一模一樣,并沒(méi)有什么其他字符。
第一次碰到這種例子,沒(méi)有什么經(jīng)驗(yàn),真的排查了很久,到最后都有點(diǎn)懷疑人生了。最后無(wú)意間將文本內(nèi)容復(fù)制到了 IDEA 中,才發(fā)現(xiàn)整理混雜著零寬字符!
如果各位小伙伴也碰到這類問(wèn)題,不妨將復(fù)制文本內(nèi)容,然后到 IDEA 中查看是否存在某些看不見(jiàn)字符~
參考鏈接
(更多精彩值得期待……)
●??人人都欠微軟一個(gè)正版?
●??積分兌換,來(lái)就“兌”了
●??這 10 行比較字符串相等的代碼給我整懵了,不信你也來(lái)看看
●??Unicode雙向算法(bidi算法)詳解(一)
●?漫畫:什么是字符串匹配算法?
●?漫畫:如何優(yōu)化 “字符串匹配算法”?
總結(jié)
以上是生活随笔為你收集整理的字符ascii码值转换_没想到 Unicode 字符还能这样玩?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java 取pdf 文本域_java –
- 下一篇: java substring截取字符串_