在使用 PKI 時經常會在網路上傳送簽章或加密後的資料,進行安全且私密的資料交換,但是要如何將二進位簽章或加密資料放入 HTML 這類的文字資料中呢?常見的做法是將二進位資料編碼成可列印(printable)的資料,而最普遍的編碼方式為 Hex 和 Base64 編碼。
2021 年將全面換發新式數位身分證(New eID),而在新式數位身分證的應用介面(API)裡有許多資料,像是自然人憑證中的 PKI 簽章與加密資料都需運用到 Base64 編碼進行交換與傳遞,現在就來了解一下什麼是 Hex 和 Base64 編碼。
Hex 是以兩個 16 進位符號(0~9、A、B、C、D、E、F)來表示每個 byte 資料,如此就可表示所有二進位資料。然而 Hex 編碼的缺點在於資料長度會變成原來的兩倍,如果將大量資料用 Hex 編碼則在網路傳輸上會需要更多的時間,所以資料量大時建議使用 Base64 編碼。
Base64 則是用 64 個字元符號來表示資料,處理邏輯如下:
- 先將資料每 3 個 byte 分成一組,最後資料不足 3 個 byte 則以 0 補足。
- 每組資料再分成 4 段,每段 6 個 bit。26=64 正好對應 64 個字元符號來編碼。3 個 byte 可分成 4 段,所以編碼後的資料長度會比原資料長度略長,為原資料的 4/3。字元符號的對應編碼如下表:
數值 字元 0 A 1 B 2 C 3 D 4 E 5 F 6 G 7 H 8 I 9 J 10 K 11 L 12 M 13 N 14 O 15 P 數值 字元 16 Q 17 R 18 S 19 T 20 U 21 V 22 W 23 X 24 Y 25 Z 26 a 27 b 28 c 29 d 30 e 31 f 數值 字元 32 g 33 h 34 i 35 j 36 k 37 l 38 m 39 n 40 o 41 p 42 q 43 r 44 s 45 t 46 u 47 v 數值 字元 48 w 49 x 50 y 51 z 52 0 53 1 54 2 55 3 56 4 57 5 58 6 59 7 60 8 61 9 62 + 63 / - 將所有資料依表編碼。
- 最後在資料後面補 0 的部分,編碼則以 = 表示。
現在就把 ARES 用 Base64 表示看看:
A | R | E | |||||||||||||||||||||
0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 |
Q | V | J | F |
S | |||||||||||||||||||||||
0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
U | w | = | = |
所以 ARES 經 Base64 編碼後就是「QVJFUw==」。
看到這裡或許有點一個頭兩個大了,不過不用擔心,多數的程式語言都有提供 Base64 的函式庫可以使用,例如:dotnet 的 Convert.
類別或是 Java 的 java.util.Base64
類別都提供 Base64 編碼(encode)和解碼(decode)方法。
最後要提醒的是,由於 Base64 會用到+和=兩個符號,若放在 URL 裡傳輸會發生衝突,因為 URL 編碼器會把標準 Base64 中的 / 和 + 字元變形,如:%XX 的形式(URL 編碼)。因此使用時要將 Base64 資料經 URL 編碼用 post 方式傳送並指定 Content-Type: application/x-www-form-urlencoded
,就可避免兩者的衝突。