需求
稍微正規點的公司,都要為自己開發的軟體做程式碼簽名,如下圖所示
程式碼簽名的主要目的是為了確保軟體的來源(這個軟體是由誰生產的)和軟體的內容不被篡改
一個軟體公司可能有很多團隊,很多開發者,開發不同的軟體,但用於簽名的證照就那麼一套
由於擔心開發者用這個證照去簽名惡意的軟體,損壞公司的聲譽,
所以這套證照一般不會直接給開發者使用的
那麼怎麼辦呢?
公司往往會開發一個服務,
軟體開發好後,開發者把軟體上傳到這個服務上,由這個服務給軟體簽名,簽完名後,開發者再下載簽名後的檔案,再分發給使用者
方案
如果公司提供的簽名服務是標準的CI簽名服務,那麼開發者只要為electron-builder設定CSC_LINK和CSC_KEY_PASSWORD環境變數即可
但往往公司提供的就是一個簡單的http上傳下載服務,
這就需要通過自定義electron-builder的簽名回撥來完成相應的工作了
下面是這個配置項在整個electron-builder配置項中的位置(此文簽名只與windows環境有關):
let options = { config: { win: { sign: async (config) => { } }, }, } builder.build(options);
在electron-builder為應用打包時,
至少會產出4個可執行檔案(windows平臺下為exe檔案)
- 你的應用程式.exe
- 你的應用程式的安裝檔案.exe
- 你的應用程式的解除安裝檔案.exe
- elevate.exe(這個檔案用於以管理員的身份啟動程式)
上面提到的sign函式會相應的執行8次(每個exe檔案產生時,會執行兩次sign函式)
如果你有其他的可執行程式要打包到你的應用中,
相應的sign函式也會被呼叫(同樣也是每個exe檔案,會執行兩次sign函式)
sign函式被呼叫時,electron-builder會為其輸入一個config引數
這個引數的值如下(兩個物件分別對應兩次呼叫):
{ path: 'D:\\project\\***\\*** 1.3.0.exe', name: 'HikLink', site: null, options: { icon: '../resource/unrelease/icon.ico', target: [ [Object] ], sign: [AsyncFunction: sign] }, hash: 'sha1', isNest: false, computeSignToolArgs: [Function: computeSignToolArgs] } { path: 'D:\\project\\***\\*** 1.3.0.exe', name: 'HikLink', site: null, options: { icon: '../resource/unrelease/icon.ico', target: [ [Object] ], sign: [AsyncFunction: sign] }, hash: 'sha256', isNest: true, computeSignToolArgs: [Function: computeSignToolArgs] }
不同點是:hash和isNest兩個屬性
(有兩種簽名型別,一種是sha1,一種是sha256,sha1由於不安全,基本已經廢棄了,所以我們選擇sha256)
最終的sign函式的邏輯為:
child_process.spawnSync("curl.exe", [ "-F", "auth_id=******", "-F", "username=******", "-F", "fd=sha256", "-F", "file=@" + config.path, //生成的exe檔案的絕對路徑 "-F", "cert_type=SHA256", "http://******/sign.php", //簽名服務 "-k", "-f", "-o", config.path //簽名完之後就下載,下載之後就覆蓋 ], { cwd: path.dirname(config.path), stdio: "inherit" //上傳下載過程同步到當前控制檯 })
我們是使用著名的curl.exe完成這個工作的
當然可以自己寫程式碼模擬表單提交過程
PS
如果公司需要把所有的exe和dll都簽名,那麼就需要另外想辦法了
我曾經把electron-builder裡的程式碼改寫了,就為了滿足簽名的要求,真是一把辛酸淚