技術交流

如何在新式數位身分證進行 PKI 簽章、加密資料的傳遞?

羅祖祈 羅祖祈

在使用 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 個字元符號來表示資料,處理邏輯如下:

  1. 先將資料每 3 個 byte 分成一組,最後資料不足 3 個 byte 則以 0 補足。
  2. 每組資料再分成 4 段,每段 6 個 bit。26=64 正好對應 64 個字元符號來編碼。3 個 byte 可分成 4 段,所以編碼後的資料長度會比原資料長度略長,為原資料的 4/3。字元符號的對應編碼如下表:
    數值字元
    0A
    1B
    2C
    3D
    4E
    5F
    6G
    7H
    8I
    9J
    10K
    11L
    12M
    13N
    14O
    15P
    數值字元
    16Q
    17R
    18S
    19T
    20U
    21V
    22W
    23X
    24Y
    25Z
    26a
    27b
    28c
    29d
    30e
    31f
    數值字元
    32g
    33h
    34i
    35j
    36k
    37l
    38m
    39n
    40o
    41p
    42q
    43r
    44s
    45t
    46u
    47v
    數值字元
    48w
    49x
    50y
    51z
    520
    531
    542
    553
    564
    575
    586
    597
    608
    619
    62+
    63/
  3. 將所有資料依表編碼。
  4. 最後在資料後面補 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,就可避免兩者的衝突。