使用「Google 試算表做為資料庫」後,除了需要瞭解「資料庫防駭技巧」,為了安全性著想,一些需要加密的運算不可在前端執行(Javascript會被看光)。
舉例來說,前端發送修改資料的請求時,後端必須先驗證這個請求的身份、權限,也就是檢查前端附上的 token 通行金鑰。這個金鑰當然不可由前端產生,否則 JS 演算邏輯被看到,就可任意偽造通行金鑰。
那麼 Google 試算表的後端語言 Google Apps Script(簡稱 GAS),是否有足夠安全的加密演算法、是否需要安裝外掛?請見本篇的說明
(圖片出處: pexels.com)
一、GAS 內建工具
前端向後端發送請求時,反應速度是非常重要的,如果 GAS 在後端進行加密時還要讀取外掛,導致伺服器回應請求的時間過長,那麼前端的使用者體驗一定不佳,訪客遲早跑光光。 值得慶幸的是找了很久,終於發現 GAS 官方提供了內建的各種知名加密演算法,並提供了範例說明,請參考這個頁面有詳細列表: 1. 工具介紹 從官網頁面的函數列表,我們看到 GAS 提供了這些工具:- base64:將字串轉換為 64 位元編碼,只使用英數符號。如果使用了英數以外的字串例如特殊符號、中文,最好先經 base64 編碼處理
- Digest 演算法:包含了 MD5、SHA 等雜湊演算法
- Mac 演算法:一樣使用 MD5、SHA 等雜湊演算法,但需要提供加密金鑰
- RSA 演算法:RSA 是一種非對稱加密演算法,需要公鑰與私鑰
二、MD5、SHA 操作
官方說明書大概是寫給工程師看的,沒有一定的基礎知識八成看不懂這些函數要如何運作。 MD5、SHA 函數及使用參數如下:computeDigest(algorithm, value, charset)
- algorithm 填入演算法名稱,參照官網「DigestAlgorithm」
- value 填入原始字串
- charset 為編碼方式,參照官網「Charset」
var sourceStr = "Blogger 調校資料庫", // 原始字串 含 UTF8 中文字串
SHA_256_hash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256,
sourceStr), // SHA_256 雜湊值 非 UTF8 編碼
SHA_256_hash_utf8 = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256,
sourceStr, Utilities.Charset.UTF_8), // SHA_256 雜湊值 UTF8 編碼
base64_SHA_256_hash = Utilities.base64Encode(SHA_256_hash), // SHA_256 雜湊值 非 UTF8 編碼 經 base64 編碼轉為英數字串
base64_SHA_256_hash_utf8 = Utilities.base64Encode(SHA_256_hash_utf8); // SHA_256 雜湊值 UTF8 編碼 經 base64 編碼轉為英數字串
console.log(SHA_256_hash); // [ -70, 36, 121, -47, -80, -76, -98, -14, 97, 106, 15, -57, 44, -122, -69, 58, -1, -128, -126, 39, -27, 17, 86, 42, 16, 23, -34, 92, 64, 43, -11, -10 ]
console.log(SHA_256_hash_utf8); // [ -66, -35, 9, -38, 15, -43, 107, 103, -87, 17, 54, -104, -117, -29, 76, -27, 42, -108, -60, 9, -61, -14, 55, -80, 6, 0, 46, 16, 18, -74, 6, -86 ]
console.log(base64_SHA_256_hash); // uiR50bC0nvJhag/HLIa7Ov+AgiflEVYqEBfeXEAr9fY=
console.log(base64_SHA_256_hash_utf8); // vt0J2g/Va2epETaYi+NM5SqUxAnD8jewBgAuEBK2Bqo=
三、MAC 操作
使用 MAC 演算法產生雜湊值的 MD5、SHA 函數及使用參數如下:computeHmacSignature(algorithm, value, key, charset)
- algorithm 填入演算法名稱,參照官網「MacAlgorithm
- value 填入原始字串
- key 填入加密私鑰
- charset 為編碼方式
var sourceStr = "Blogger 調校資料庫", // 原始字串 含 UTF8 中文字串
key = "WFU BLOG", // 私鑰
HMAC_SHA_384_hash_utf8 = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_384, sourceStr, key, Utilities.Charset.US_ASCII), // SHA_384 雜湊值 UTF8 編碼
base64_SHA_384_hash_utf8 = Utilities.base64Encode(HMAC_SHA_384_hash_utf8); // SHA_256 雜湊值 UTF8 編碼 經 base64 編碼轉為英數字串
console.log(HMAC_SHA_384_hash_utf8); // [ 4, -36, -68, 59, 82, -127, -13, 111, -28, -52, 65, 7, -72, 109, -38, 107, -83, -36, -39, -60, 72, 80, 68, -37, -12, 62, -45, -45, 33, -89, -9, 67, 63, -57, -29, -128, 53, 42, 94, -26, -21, 111, 72, -66, 112, -20, 27, 69 ]
console.log(base64_SHA_384_hash_utf8); // BNy8O1KB82/kzEEHuG3aa63c2cRIUETb9D7T0yGn90M/x+OANSpe5utvSL5w7BtF
四、RSA 操作
GAS 提供的 RSA 加密函數研究一陣子才發現沒有用處,無法生成公鑰、私鑰(要自己想辦法取得),只能產生雜湊值,不能加密也無法解密。 仔細想了一下,難怪函數名稱幾乎都有 "Signature",原來 GAS 本篇提供的工具作用就是製作 "簽名"。既是如此的話,不如直接使用前兩個方案就好,不需特別操作更複雜的 RSA 方案。不過既然都花時間了,還是把研究結果貼一下。computeRsaSha256Signature(value, key)
- value 填入原始字串
- key 填入私鑰,且私鑰需符合格式,請參考官網computeRsaSha256Signature
- 私鑰可從線上工具產生,例如 Online RSA Encryption, Decryption And Key Generator Tool,按「Generate RSA Key Pair」後,複製 Private Key 的字串
var sourceStr = "Blogger 調校資料庫", // 原始字串
privateKey = "MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAxiiQ5NEDMH3RRd1+gp5yDnT1r1cnVTQumaC1n6uK9JcHrDlfMASbMPO0adz1kMBN3jcMY3dRRcT4SoEkNxW1oQIDAQABAkBRNtcLsM5J1YcrxzfOePnuCumWz3WDajufI0rNAhWVYIbtSfgNQj0eZtMa2xshapGu7F7ov4UFb2YOlRhGl9xxAiEA/vnwYUZu4WmDbsemHTcxnpn6ivVs6bnzVDLx2rR1lZMCIQDG9Dr82jMAQ3SHCake6WGrU1oScP27BxtM9fFaGNTIewIhALnuLJnisIxzUsJ/l+SKEQbkpcya91bgoE3v8GlZWr09AiBIJQZC7Ijz/oIB+dHXAMBHFTmjWE/aA1C2DrVPe5OlgwIhALPUSYLt194IO89G79FCzCu+Cn3IxL0Xmxq7kzaCFERd", // 私鑰 從線上工具產生
privateKeyStr = "-----BEGIN PRIVATE KEY-----\n" + privateKey + "\n-----END PRIVATE KEY-----\n", // 完整私鑰字串
RsaSha256_hash = Utilities.computeRsaSha256Signature(sourceStr, privateKeyStr), // Rsa Sha256 雜湊值
base64_RsaSha256_hash = Utilities.base64Encode(RsaSha256_hash); // Rsa Sha256 雜湊值 經 base64 編碼轉為英數字串
console.log(base64_RsaSha256_hash); // MGnoHZQu2ZZFPACoMZMwMEC3dwUsc//EINixWsTjasydxc12nCIiDmkRpoF0G3O3ZRik69wSIgRurwjjjhNJ1A==
五、AES 加密、解密
AES 為知名的「對稱加密」演算法,介紹說明可參考維基「進階加密標準」。如果在 GAS 有加密、解密需求的話,因官方未提供內建工具,可參考以下的作法。 1. AES 工具 這個網頁「CryptoJS libraries for Google Apps Script」將知名的 CryptoJS 函式庫搬到 GAS 使用,此頁面有操作說明,同時完整的程式碼放在這個頁面: 進入上面這個 GAS 頁面後,將「AES.gs」的所有程式碼複製到自己的 GAS,就可以進行操作了。 2. 範例程式碼 以下的範例請自行修改原始字串、加密金鑰,就能進行加密與解密了:var sourceStr = "Blogger 調校資料庫", // 原始字串 使用 UTF8 編碼
Key = "WFU BLOG", // 加密金鑰
encodeStr = CryptoJS.AES.encrypt (sourceStr, Key).toString(), // 加密字串
decodeStr = CryptoJS.AES.decrypt (encodeStr, Key).toString(CryptoJS.enc.Utf8); // 解密字串 還原 UTF8 編碼
console.log(encodeStr); // U2FsdGVkX186XFuduXNEWWWUY02bhb+2IVKYyGcOoSg7dtmXxugjfTlGQ4TKC8qJ
console.log(decodeStr); // Blogger 調校資料庫
六、補充說明
本篇使用到 GAS 官方提供的 base64 編碼工具,效果等同於前端 JS 的 btoa() 函數。然而官方提供的 base64 解碼工具跟 atob() 截然不同,解出來的不是字串,而是一個陣列,很難想像這是什麼東西,詳情可參考官網說明文件「base64Decode」:"Decodes a base-64 encoded string into a UTF-8 byte array"。 要還原 base64Encode() 字串的話不可直接用 base64Decode(),務必參照官方提供的範例程式碼,先解碼成陣列再製作出一個 blob 物件,再轉成字串才能成功:Utilities.newBlob(Utilities.base64Decode("這裡是 base64 編碼字串")).getDataAsString()
更多 Google Apps Script 相關技巧:
沒有留言:
張貼留言注意事項:
◎ 勾選「通知我」可收到後續回覆的mail!
◎ 請在相關文章留言,與文章無關的主題可至「Blogger 社團」提問。
◎ 請避免使用 Safari 瀏覽器,否則無法登入 Google 帳號留言(只能匿名留言)!
◎ 提問若無法提供足夠的資訊供判斷,可能會被無視。建議先參考這篇「Blogger 提問技巧及注意事項」。
◎ CSS 相關問題非免費諮詢,建議使用「Chrome 開發人員工具」尋找答案。
◎ 手機版相關問題請參考「Blogger 行動版範本的特質」→「三、行動版範本不一定能執行網頁版工具」;或參考「Blogger 行動版範本修改技巧 」,或本站 Blogger 行動版標籤相關文章。
◎ 非官方範本問題、或貴站為商業網站,請參考「Blogger 免費諮詢 + 付費諮詢」
◎ 若是使用官方 RWD 範本,請參考「Blogger 推出全新自適應 RWD 官方範本及佈景主題」→ 不建議對範本進行修改!
◎ 若留言要輸入語法,"<"、">"這兩個符號請用其他符號代替,否則語法會消失!
◎ 為了過濾垃圾留言,所有留言不會即時發佈,請稍待片刻。
◎ 本站「已關閉自刪留言功能」。