在Ubuntu 18.04上分析自然人憑證client端程式

前言

  • 經過申請自然人憑證如何在Ubuntu 18.04上面使用自然人憑證?等系列文章之後,相信各位讀者對自然人憑證在Ubuntu使用上不會很陌生。
  • 本篇文章,是要更進一步分析,「/path/to/HiPKILocalSignServerApp/HiPKILocalSignServer」這個目錄底下的一些程式,以及本地的客戶端程式所做的行為與機制。

前置環境

  • 已經有一台Ubuntu 18.04的主機
  • 已經學會申請與在Ubuntu 18.04上使用自然人憑證
  • 自然人憑證環境已經架設好

客戶端程式

  • 首先,我們先切換到「HiPKILocalSignServerApp」這個目錄底下,裡面有這些本文章重要的相關的檔案,如下截圖:

  • 「Readme.txt」
    • 一個用英文寫的說明文件,裡面簡單的講述該如何操作這個「HiPKILocalSignServer」。
  • 「selfTest.desktop」
    • 一個啟動檔,裡面執行之後會透過呼叫網頁瀏覽器並瀏覽「http://localhost:61161/selfTest.htm」位址。
  • 「start.desktop」
    • 一個啟動檔,裡面描述啟動「start.sh」shell script
  • 「startInvisible.desktop」
    • 一個啟動檔,裡面同樣是描述啟動「start.sh」shell script並不透過終端機視窗執行
  • 「stop.desktop」
    • 一個啟動檔並停止本地端的「HiPKILocalSignServer」,停止的方式就是利用kill指令砍到正在運行的「node」程式。
  • 「update.desktop」
    • 一個啟動檔,會執行「update.sh」shell script去更新本地端的cleint端程式

接著切換到「HiPKILocalSignServer」目錄底下,裡面幾個重要的檔案如下:

  • 「popupForm.htm」,這是在做簽章簽章的時候會跳出來的小視窗,裡面以純JavaScript開發而成的,裡面會監聽「message」事件來判斷目前卡片的狀態。
    • 事件的狀態有:
      • MakeSignature 簽章中
      • umakeSig 簽章中
      • GetUserCert 憑證讀取中
      • DecryptData 解密中
      • writecert 寫憑證中
      • CheckEnvir 資料讀取中
      • changeUserPINCode 密碼變更中
      • makeCsr 製作憑證請求檔中
  • selfTest.htm」,一個自我測試的網頁,主要也是在Linux作業系統中對自然人憑證用來自我測試所使用。
  • 「hipkiLocalServer.js」,一個執行Hipki LocalServer的Node.js程式,這個會搭配「start.sh」shell script程式,裡面有記載所有的route path,可以存取的網址(path),可以搭配「hipkiFuncs.js」來看,可以找到對應請求的route path時候會執行的function。
  • 「errorcode.js」,裡面會紀錄所有簽章所發生的狀態碼,並把狀態碼對應成錯誤的狀態訊息。
  • 「hipkiFuncs.js」,裡面收錄許多外部呼叫對應的函式,透過這個對幾個外部執行檔做外部呼叫,進而達到功能相關的功能,下面有各個Linux執行檔對應與可能的功能。
  • 「hipkiFuncs.js.bak」,迷之JS備份檔?
  • 「hipkilog.js」,debug的log,會寫相關的log檔案在本地端的目錄
  • 「Module_HiPKILocalSignServer.txt」,紀錄此「Module_HiPKILocalSignServer」的版本號為多少,目前版本相關資訊如下:
    • {“version”:”1.3.4.3″,”description”:”HiPKILocalSignServer”}
  • 「node」,Node.js的執行檔,此收錄版本為:「v5.6.0」
  • 「node_modules」,Node.js的相依套件,裡面有「winston」的套件,用來方便紀錄log檔案所用的套件
  • HiPKIDecrypt.exe,HiPKISign.exe,HiPKIWriteCert.exe,ListInfo.exe
    • 上述這四個檔案皆為Linux底下的編譯過得執行檔,四個檔案皆為動態連結(dynamic linked)的方式進行編譯而成的。
    • 從檔案名稱可以看出,這四個執行檔分別為:自然人憑證解密,自然人憑證簽章,自然人憑證寫入簽章以及列出自然人憑證相關資訊等四個執行檔。
  • 上述這四個執行檔更進一步的資訊為:
  • HiPKIDecrypt.exe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=d9eb593062fa782e031b5bff135ec365bd84819a, not stripped
  • HiPKISign.exe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=33849756a55af45fe09b53fb2fb5ea0039b55f57, not stripped
  • HiPKIWriteCert.exe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=f5a6dcc1e4edec3733fa9dda974afa79186e5c5b, not stripped
  • ListInfo.exe: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=329a0739f48787e4a7874026a878852d103d4cc6, not stripped

上述這些執行檔都在本地端動作

  • 「libHicos_p11v1.so」,一個在Linux底下的靜態連結函式庫,動態連結函式庫的檔案資訊如下:
    • libHicos_p11v1.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=076b4160b06720e85339811680e782a31a006fa2, not stripped
  • 「GRCA2.crt」信任的憑證檔案,用於「update.sh」shell script檢查是否有新版的客戶端程式與下載此客戶端程式壓縮檔所使用。因為有可能網址會阻擋憑證,所以就把HTTPS憑證放在壓縮檔裡面,在使用「update.sh」的shell script裡面的「wget」指令的時候順便指定此憑證以利通過憑證的檢查。相關找到有使用此憑證的地方,如下截圖:

執行本地端HiPKILocalSignServer

  • 就在「HiPKILocalSignServerApp」目錄下直接執行「./start.sh」shell script即可,接著就可以打開瀏覽器並輸入「http://127.0.0.1:61161/」,就會看到下面的文字:
    • HiPKI Local Server (version:1.3.4.3) at 127.0.0.1:61161
    • 這就代表執行成功了。
  • 接著瀏覽「http://127.0.0.1:61161/selfTest.htm」的網址,接著可以下面這個頁面:

    • 如果沒有出現上述的頁面的話,代表讀卡機與client端程式有些問題。需要先參考這篇文章先把讀卡機與客戶端程式給安裝與設定好。
  • 接著可以看到「3.已安裝子元件版本」欄位,裡面有幾個上面所提到的Linux上編譯過得可執行檔案的版本資訊:
    • ListInfo.exe:1.0.2
    • HiPKISign.exe:1.0.8
    • HiPKIDecrypt.exe:1.0.2
  • 接著按下F12按鍵打開Web development console,並按下F5將此頁面重整,將會看到這個頁面載入的時候所有會呼叫的本地端網址,可以看到幾個重點:

  • 上面的截圖分別為下面三個網址路徑:
    • http://127.0.0.1:61161/pkcs11info
    • http://127.0.0.1:61161/sign
    • http://127.0.0.1:61161/decrypt
    • 所有請求的網址皆response JSON與使用POST方法進行請求並都使用AJAX進行發送請求
  • 整理成下面的表格:
請求網址HTTP response body對應的cURL指令
http://127.0.0.1:61161/pkcs11inforesponse.jsoncurl -X POST http://127.0.0.1:61161/pkcs11info
http://127.0.0.1:61161/signresponse.jsoncurl 'http://127.0.0.1:61161/sign' --data-binary 'tbsPackage={"tbs":"123","pin":1234}'
http://127.0.0.1:61161/decryptresponse.jsoncurl 'http://127.0.0.1:61161/decrypt' --data-binary 'tbsPackage={"cipher":"123","pin":1234}'
  • 接著,我們把PIN碼輸入,並按下「開始檢測」按鈕。

  • 等一下之後就會看到Web dev console多了幾個新的AJAX請求:
    • http://127.0.0.1:61161/sign,response JSON與使用POST方法進行請求並透過AJAX進行發送請求。
    • http://127.0.0.1:61161/pkcs11info?withcert=true,response JSON與使用GET方法進行請求並透過AJAX發送請求。
  • 整理成下面的表格:
請求網址HTTP response body對應的cURL指令
http://127.0.0.1:61161/signresponse.jsoncurl 'http://127.0.0.1:61161/sign' --data-binary '
tbsPackage={
"tbs":"TBS",
"hashAlgorithm":"SHA256",
"pin":"1234",
"func":"MakeSignature",
"signatureType":"PKCS1",
"slotDescription":"CASTLES EZ100PU 00 00"
}'
http://127.0.0.1:61161/pkcs11info?withcert=trueresponse.jsoncurl 'http://127.0.0.1:61161/pkcs11info?withcert=true'
  • 從上述的表格我們可以知道,response回來的JSON字串不外乎就是憑證與簽章的資訊還有憑證管理中心等相關資訊之外,還有讀卡機的型號等資訊。

分析可執行檔案

上面的章節中,有提到這幾個編譯過得執行檔並由跑在本地端的HiPKILocalSignServer進行外部呼叫。

透過「hipkiFuncs.js」與「hipkiLocalServer.js」這兩個JavaScript程式可以知道,下列這幾個編譯過的可執行檔的下列用法:

  • HiPKIDecrypt.exe
    • 已知的用法:「./HiPKIDecrypt.exe」,查看編譯執行檔版本資訊
      • 輸出結果:{“func”:”decrypt”,”last_error”:0,”ret_code”:1979711500,”version”:”1.0.2″}
    • 已知的用法:「./HiPKIDecrypt.exe ‘{“cipher”:”123″,”pin”:1234}’」,進行解密憑證的動作
      • 輸出結果:{“func”:”decrypt”,”last_error”:0,”ret_code”:1979713944,”version”:”1.0.2″}
  • HiPKISign.exe
    • 已知的用法:「./HiPKISign.exe」,查看編譯執行檔版本資訊
      • 輸出結果:{“func”:”sign”,”last_error”:0,”ret_code”:1979711500,”version”:”1.0.8″}
    • 已知的用法:取得加密與簽章憑證相關資訊,指令用法:

./HiPKISign.exe '{
   "tbs":"TBS",
   "hashAlgorithm":"SHA256",
   "pin":"1234578",
   "func":"MakeSignature",
   "signatureType":"PKCS1",
   "slotDescription":"CASTLES EZ100PU 00 00"
}'

  • HiPKIWriteCert.exe
    • 已知用法:「./HiPKIWriteCert.exe」,查看此執行檔案版本資訊
    • 輸出結果:

{
   "func" : "writecert",
   "last_error" : 0,
   "ret_code" : 1979711500,
   "version" : "1.0.0.9"
}

  • ListInfo.exe
    • 已知用法:「./ListInfo.exe」,查看讀卡機以及卡片等資訊
    • 輸出結果在此連結

客戶端程式系統架構圖

綜合上面分析的結果,可以得到像下面這樣的架構圖:

架構圖的大意就是,大部份都是透過client端上執行起來的「HiPKILocalSignServer」所完成所有的請求,請求是透過外部呼叫並傳遞參數的方式執行並將結果傳遞回去client端。

結語

  • 透過這篇文章的分析,相信大家對自然人憑證client端程式又更進一步的了解了
  • 有些方法並沒有辦法從「selfTest.htm」所發送的請求進行推導,不過這些也夠了,因為我們也看到許多常見的用法

參考文章

  • https://gpkiapi.nat.gov.tw/hisecure/question/list.do?page=1