轉義、編碼和加密

轉義、編碼和加密是開發(fā)中很常見也很基礎的概念。對于初學開發(fā)的開發(fā)者,可能有時會無法準確的區(qū)分著幾個詞。我們將通過這篇文章來了解一下“轉義、編碼和加密”這幾個詞的關聯(lián)和區(qū)別。
## 轉義
### 第一種轉義場景
絕大多數(shù)的開發(fā)者都曾經(jīng)在自己學習第一個編程語言時,就遇到了這個概念。以經(jīng)典的C語言中字符串中的字符轉義為例。
如果在一個字符串中存在一個`"`,那么就需要在`"`前添加`\`才能夠正常的表示,比如下面這樣。
```c
char* universal_law = "月老板說:\"世界上本也不存在'銀彈'。一套框架解決不了所有問題。\""
```
之所以需要這樣,是因為對于字符串來說,`"`本身就是表示一個字符串的起止符號。如果不進行轉義,那么編譯器將無法正確的識別其中的`"`哪些是分隔符,哪些是字符串內(nèi)部的`"`。
所以,第一種需要轉義的場景就是:**如果不進行轉義就可能與語法規(guī)定的某些內(nèi)容產(chǎn)生混淆,所以這些內(nèi)容都被設計為需要轉義。**
基于這種場景,可以在很多的編程語言和概念中找到這種場景的體現(xiàn):
- java
? ? ```java
? ? String honor = "月老板-\"賽博坦首席技術官\"";
? ? ```
? ? 對`"`進行轉義
- C#
? ? ```csharp
? ? var proverbs = "月老板:\"這里不要寫死,下次需求必改\"";
? ? ```
? ? 對`"`進行轉義
- XML
? ? ```xml
? ? <nb>月老板的襯衫價格>99磅6便士</nb>
? ? ```
? ? `>`是對`>`的轉義,`>`是XML的邊界符
- 正則表達式
? ? ```jsregexp
? ? \d+\\\.\d+
? ? ```
? ? `\.`表示一個`.`,因為在正則表達式中`.`表示匹配除`\n`和`\r`之外的任何單個字符。
? ? `\\`表示一個`\`,轉義字符的轉義表示。
> **可發(fā)帖可群聊的技術交流方式已經(jīng)上線,歡迎通過鏈接,加入我們一起討論。 <https://www.newbe.pro/links/>**
### 第二種轉義場景
當然,另外還有一種場景,同樣還是以C語言為例,看一下下面這個例子:
```c
char* hammurabi_no1 = "月落大佬:\"業(yè)務復雜度不會因為系統(tǒng)設計變化而減少,\r\n它只是從一個地方轉移到了另外的地方。\""
```
其中的`\r`和`\n`也是一種轉義場景的使用。他們分別表示一個回車符和換行符。之所以要轉義,是因為正常情況下,這樣的字符是不可見的,對于這種字符,不過不采用轉義的形式進行表達,那么會比較困難,因為語言設計者設計了這種轉義的方式來表達不容易表達的字符。
因此,可以總結出第二種需要轉義的場景:**轉義可以使得表達內(nèi)容的方式更加容易,更加容易理解,所以設計了這類轉義規(guī)則。**
基于這種場景,也可以在很多編程語言和概念中找到對應的體現(xiàn):
- C#
? ? ```csharp
? ? var colorOfYueluoShirt = 0xFFFFFF;
? ? ```
? ? `0xFFFFFF`表示一個十六進制數(shù),對應的十進制數(shù)是16777215。`0xFFFFFF`的表達形式更容易閱讀。
- HTML
? ? ```html
? ? <nb>月老板的襯衫價格>966¥</nb>
? ? ```
? ? `¥`是對`¥`的轉義,因為在期初的HTML中,只能用ASCII表中的字符進行表達,所以當時設計了這種方式。
除了在IT領域,在其他領域其實也存在類似第二場景的應用。例如在中國的航空領域,對于數(shù)字的念法有特殊的處理:7讀作拐,0讀作洞,1讀作幺,2讀作兩。經(jīng)過這樣的“轉義”處理,可以避免誤聽而造成的困擾。
### 轉義的總結
總結來說,轉義規(guī)則的設計,主要解決了兩種場景下對代碼的表達問題:
1. 如果不進行轉義就可能與語法規(guī)定的某些內(nèi)容產(chǎn)生混淆,所以這些內(nèi)容都被設計為需要轉義。
2. 轉義可以使得表達內(nèi)容的方式更加容易,更加容易理解,所以設計了這類轉義規(guī)則。
值得一提的是,很多名稱中包含有`escape`或者`unescape`的函數(shù)或者方法都表明了它們與轉義有關。
## 編碼
編碼也是一個非常常見的概念。比如經(jīng)常會聽到UTF8編碼、GBK編碼、Base64編碼、URL編碼、HTML編碼、摩斯電碼等等一些和編碼有關的概念。
### 生活化地理解編碼
在了解編碼之前,首先通過一個生活化的例子來了解一下“什么是信息,什么是信息的載體”。
全世界,對于“我愛你”這樣一句話的表達方式千差萬別??陬^表達,書面表達,肢體表達,普通話表達,英語表達,音樂表達,繪畫表達。甚至有生之年我們可以腦電波表達。但不論表達方式是如何的,其中包含的信息可以是一致的。都是為了傳達“我愛你”這樣的一個核心價值。
在以上這段表述中,可以將“我愛你”這樣的概念理解為“信息”。而各種表達方式理解為這個信息的各種載體。
那么,回到編程的世界中來。計算機中的信息主要的載體是以電磁信號的物理載體存在于計算機世界中。那么如果要將現(xiàn)實世界復雜的內(nèi)容都依靠這種載體來表達,就需要進行轉化,我們可以將這種轉化理解為編碼。結合前文生活化的例子,使用普通話來表達“我愛你”這個信息,就可以理解為使用普通話來編碼這個信息。
因此,**編碼,其可以理解為,采用一種新的載體來表示前一個載體所表達的信息。**
可以套用類似這樣一個公式來理解:**XX編碼,將A編碼為B,以實現(xiàn)通過B進行存儲或傳輸傳輸?shù)哪康摹?*
### 技術相關的編碼
那么,采用這樣的概念,我們來理解一下以往見到的各種技術概念:
- 文本文件編碼,將“文本數(shù)據(jù)”編碼為“二進制數(shù)據(jù)”,以實現(xiàn)通過“二進制數(shù)據(jù)”進行存儲或者傳輸?shù)哪康?/p>
? ? 文本文件在計算機中,最終的載體是二進制文件的形式存在。早起,由于計算機誕生在美國,文本內(nèi)容也只包含有英文內(nèi)容。因此當時只要使用ASCII進行編碼就可以了。但是后來隨著計算機的普及,需要表達的信息越來越多了。因此誕生了Unicode、GB2312等等編碼形式。但不論如何,這些編碼其實都是對文本信息的編碼形式。
- Base64編碼,將“二進制數(shù)據(jù)”編碼為“64個可打印字符的組合”,以實現(xiàn)通過“可打印字符的形式”進行存儲或者傳輸?shù)哪康?/p>
? ? 在Web場景中,在有些地方限制了數(shù)據(jù)傳輸?shù)姆绞健@?,在URL,只能傳遞文本。因此,如果想要傳輸一組二進制數(shù)據(jù)。那么可以選用Base64編碼,將二進制數(shù)據(jù)編碼為可打印的字符串。這樣才能完成URL上二進制數(shù)據(jù)的傳輸。
- URL編碼,將“非數(shù)字字母字符”編碼為“十六進制轉義序列”,以實現(xiàn)通過“十六進制轉義序列”進行傳輸?shù)哪康?/p>
? ? 如果需要在URL中傳遞中文作為參數(shù),或者需要在URL中傳遞空格、`&`、`?`、`=`等等特殊符號。這個時候就需要進行URL編碼。例如`月老板`會被編碼為`%E6%9C%88%E8%80%81%E6%9D%BF`。編碼的目的HTTP協(xié)議的內(nèi)在要求,通過這種形式,可以瀏覽器表單數(shù)據(jù)的打包。
總的來說,通過編碼,可以轉化信息表達的載體。這樣就可以利用新載體帶來的好處。這里也有一些生活化的例子:
- 摩斯電碼,將“文本數(shù)據(jù)”編碼為“點橫組成的電信號”,以實現(xiàn)通過“電報”進行傳輸?shù)哪康摹?/p>
? ? 例如:
? ? ```
? ? -·-- ··- · ·-·· ··- ---? ?·· ···? ?- ···· ·? ?-- --- ··· -? ?··-· ·- -- --- ··- ···? ?-·· ·- ·-·· ·- ---
? ? ```
- 社會主義核心價值觀編碼,將“文本數(shù)據(jù)”編碼為“社會主義核心價值觀組成的字符”,以實現(xiàn)通過“社會主義核心價值觀”進行傳輸?shù)哪康摹?/p>
? ? 例如:
? ? ```
? ? 誠信自由公正敬業(yè)友善公正愛國愛國友善愛國愛國愛國富強愛國民主友善愛國公正敬業(yè)誠信和諧誠信民主友善敬業(yè)友善愛國公正誠信民主富強誠信民主愛國友善愛國愛國誠信民主友善敬業(yè)敬業(yè)誠信文明友善愛國公正敬業(yè)愛國誠信富強誠信平等誠信自由公正敬業(yè)誠信文明愛國富強誠信自由平等誠信民主友善公正誠信民主友善自由誠信自由法治敬業(yè)友善自由愛國自由
? ? ```
? ? > 社會主義核心價值觀編碼工具:<http://www.atoolbox.net/Tool.php?Id=850>
值得一提的是,很多名稱中包含有`encode`或者`decode`的函數(shù)或者方法都表明了它們與編碼有關。
### 什么是亂碼
根據(jù)上文提到的公式,編碼是完成`A->B`的載體轉化過程。那么同樣可以定義`A->B`的逆過程`B->A`為“解碼”。
一般,如果解碼之后無法正確還原原來A所表達的信息,我們會說出現(xiàn)了亂碼。例如,使用GB2312的方式去解碼一個UTF8編碼的文件,那么就會出現(xiàn)亂碼。
當然,更加常見的情況是,當開發(fā)者,特別是初入的新晉工程師,看到自己無法理解的文本,就說:“這是亂碼?!?/p>
總的來說,亂碼通常來說只是因為選用的解碼方式和編碼方式不同,而導致信息失真的情況。**選用正確的編碼就能夠解讀出正確的信息。**
## 加密
加密很好理解,在日常生活中也不乏加密的使用場景。特別是在以前的戰(zhàn)爭中的無線電技術應用歷史中,確保己方軍事信息不被敵方破解,采用優(yōu)秀的加密算法是極為重要的軍事內(nèi)容。
加密,可以這樣概括:**按照一定的算法,將需要表達的信息進行處理,以達到除了信息的發(fā)送者和接收者之外,其他人無法識別信息真實內(nèi)容的目的。**
技術上,有需要使用加密的場景:
- HTTPS,安全的HTTP通信通道,通過加密算法來確保瀏覽器接收到的數(shù)據(jù)沒有被篡改,未被泄露
- SSH,為建立在應用層基礎上的安全協(xié)議。SSH 是較可靠,專為遠程登錄會話和其他網(wǎng)絡服務提供安全性的協(xié)議。利用 SSH 協(xié)議可以有效防止遠程管理過程中的信息泄露問題。
- ~~SSR。SSR是各種集換式卡牌游戲中,卡牌稀有度級別分類的一種。(大霧)~~
這里需要特別說的是編碼和加密的區(qū)別和聯(lián)系:
- 編碼的目的是為了轉換信息的載體,使得轉換后的載體更好傳輸或者存儲。但是加密是為了安全,防止被識別。
- 加密需要一個或者一份密鑰進行加密和解密處理。安全是加密算法,在沒有密鑰的情況下,幾乎不可能被破解。但是編碼并不需要密鑰。
所以要簡單區(qū)分是編碼還是加密,可以簡單套用這個理解:**在算法完全公開的情況下,如果還需要密鑰,那么是加密。如果不需要密鑰,只能算是編碼。**
結合生活例子理解一下加密和編碼的區(qū)別:存在這樣一段字符串`Мистер Мун, Навсегда Бог.`這并不是加密,因為這是一段正常的俄語。不能因為看不懂就說他是加密,因為如果懂俄語,會用俄語解碼這段信息,就能知道他表達的意思是:“月先生,永遠的神”。
值得一提的是,很多名稱中包含有`encrypt`或者`decrypt`的函數(shù)或者方法都表明了它們與加密有關。
> **可發(fā)帖可群聊的技術交流方式已經(jīng)上線,歡迎通過鏈接,加入我們一起討論。 <https://www.newbe.pro/links/>**
## 下飯小測
以下是關于本文章的一些概念的測試題,以便讀者更好的理解。
不必擔心這些語言你沒有學過,因為概念其實和語言關系不大。
所有的問題都只有三個選項:
1. 轉義
2. 編碼
3. 加密
### 小測1
在很多編程語言中都存在“字符串內(nèi)插”的語法,例如:C#、ES6、Powershell。
以C#為例,以下就是一個示例:
```csharp
var dalao = "月落大佬";
var hammurabi_no1 = $@"{dalao}:
""業(yè)務復雜度不會因為系統(tǒng)設計變化而減少,
它只是從一個地方轉移到了另外的地方。""
";
Console.WriteLine(hammurabi_no1);
```
那么,以上代碼中`""`輸出時只表示一個`"`,這是(A)處理。
如果需要在`$@`開頭的“多行字符串內(nèi)插”字符串中,輸出一個`}`,那么需要使用`}}`來進行(B)處理。
A:轉義
B:轉義
### 小測2
在Powershell中如果要定義一個多行字符串變量,那么需要采用下面這樣的寫法:
```powershell
$template = @"
## [version]
[content]
"@
```
那么,如果需要在這個字符串中插入一個`@`或者`"`,可以直接寫進去,因為powershell是使用`@"`和`"@`,作為多行字符串的起止符,而且要求起止符需要單行。因此中間出現(xiàn)的`@`和`#`都不需要進行(A)處理。
A:轉義
### 小測3
在javascript中有一個函數(shù)名稱為`escape`。按照[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/escape)的解釋,該函數(shù)已經(jīng)被標記為棄用了。建議使用[encodeURI](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)和[encodeURIComponent](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)代替。從相應的函數(shù)解釋上也可以看出,原來的`escape`是進行表達的意思是進行(A)處理?;蛟S就是大佬們意識到這個名字其實不對,所以換了函數(shù)?新函數(shù)看名字直接理解應該是對URI進行(B)處理,似乎更加準確喲。
A:轉義
B:編碼
### 小測4
曾經(jīng)有的網(wǎng)站使用 base64 的方式,處理登錄票據(jù),并且保存在 Cookie 中。盡管這似乎比明文保存要高明一點,但這是不安全的,因為 base64 只是一種(A)算法,不能夠安全的防止信息被篡改??梢赃x用例如 DES 這樣的(B)算法,來確保信息不被篡改。
A:編碼
B:加密
## 總結
轉義、編碼和加密都是在開發(fā)過程中常常遇到的概念。注意區(qū)分學習,進行正確的表達能夠更好溝通。
**感謝您的閱讀,如果您覺得本文有用,請點贊、關注和轉發(fā)。**
> **可發(fā)帖可群聊的技術交流方式已經(jīng)上線,歡迎通過鏈接,加入我們一起討論。 <https://www.newbe.pro/links/>**
- 本文作者: [newbe36524](https://www.newbe.pro)
- 本文鏈接: [https://www.newbe.pro/Others/0x01C-escape-encoding-and-encryption/](https://www.newbe.pro/Others/0x01C-escape-encoding-and-encryption/)
- 版權聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協(xié)議。轉載請注明出處!