2020年7月20日

Javascript 字串加密解密範例研究

Javascript 字串加密解密範例研究

Wayne Fu 0 A+
最近需要用 JS 保存一些,不想被很容易就判讀出來的資料,因此研究了一下 JS 如何對字串進行加密及解密。

結果搜尋發現網路上這方面的實用工具不多,原因大致是:

  • JS 是攤在陽光下的語言,加密解密流程會被看到
  • 因此很少純前端進行加密與解密,大多是配合後端進行運算,一邊加密另一邊解密

不過只要加密用的金鑰(key)不被知道,就算純前端也是能有一些應用,本篇會提供一些前端的 JS 字串加密解密範例。

(圖片出處: pixabay.com)


一、Base64 編碼


1. 瀏覽器編碼 API

瀏覽器自帶了 Base64 編碼 API,不用任何外掛非常方便:

  • btoa():將字串轉換為 Base64 編碼
  • atob():將 Base64 編碼還原回字串

這是最簡便的加密編碼方式,不容易看出編碼如何產生,可用於不重要的資料、瞞過不懂語法的人。


2. 範例程式碼

var str = "WFU BLOG", // 原始字串
encodeStr = encode(str), // 編碼後的字串
decodeStr = decode(encodeStr); // 將編碼還原

console.log(encodeStr); // 加密後的字串 "V0ZVIEJMT0c="
console.log(decodeStr); // 解密後的字串 "WFU BLOG"

function encode(str) {
return btoa(str);
}

function decode(str) {
return atob(str);
}


3. 處理中文字串

瀏覽器 base64 編碼 API 的缺點為,無法處理中文字串,因此需先將 UNICODE 字串進行編碼,再進行 base64 編碼,例如使用 escape():

btoa(escape("這裡是中文字串"))

解碼的時候也要記得使用 unescape() 還原,例如:

unescape(atob("JXU5MDE5JXU4OEUxJXU2NjJGJXU0RTJEJXU2NTg3JXU1QjU3JXU0RTMy"))


二、AES 加密


1. 介紹及 CDN

Advanced Encryption Standard(AES) 是一個主流的加密演算法,也可以說是本篇最正規的加密演算法,因此外掛的體積相當龐大,壓縮後也有 13k 之多。如果不是非常重要的資訊,殺雞並不需要用此牛刀。

此演算法非常知名,所以找到 CDN 連結不難,使用以下外連即可:

https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js

2. 加密方式

AES 有兩種加密的操作方式方式,詳細說明可參考這篇「兩種JavaScript的AES加密方式」:
  • 使用「金鑰」+「金鑰偏移量」:加密效果更佳,越難破解
  • 單純使用「金鑰」:操作上比較簡便

以下提供的範例程式碼使用比較簡便的「金鑰」加密方式。


3. 範例

<script src='https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js'></script>
<script>
var str = "Blogger 調校資料庫", // 原始字串
key = "wfublog", // 加密金鑰
encodeStr = encode(str), // 編碼後的字串
decodeStr = decode(encodeStr); // 將編碼還原

console.log(encodeStr); // 加密後的字串 "U2FsdGVkX1+0+TBcZVnH29Wy8Qmk26FKtIWMQAsD0cWiJcfL5Cw+1UdUNYkyDvdu"
console.log(decodeStr); // 解密後的字串 "Blogger 調校資料庫"

function encode(str) {
return CryptoJS.AES.encrypt(str, key).toString();
}

function decode(str) {
return CryptoJS.AES.decrypt(str, key).toString(CryptoJS.enc.Utf8);
}
</script>

可自行修改「原始字串」及「加密金鑰」的值。



三、簡易加密演算法


正規加密演算法的檔案很大,而且還需要花費 http 外連。接下來介紹的都不是正規演算法,但檔案很小,且還能使用加密金鑰,也算是相當安全。

1. 演算法出處

此演算法出自這個網頁「一個完美的 JavaScript 字符串 加密 和 解密」:

  • 原始碼經壓縮後不到 2k
  • 原程式還需引用 js 外連,我修改後的版本不需外連,直接複製程式碼即可使用


2. 範例程式碼

var str = "Blogger 調校資料庫", // 原始字串
key = "wfublog", // 加密金鑰
encodeStr = encode(str, key), // 編碼後的字串
decodeStr = decode(encodeStr, key); // 將編碼還原

console.log(encodeStr); // 加密後的字串 "b6443a79b4a1f1ba09eaa5999ae8824de1aa389300c5e3236e00f86e47f15bf581c059d56a5aed5d408398a704d338fda08497a82044ea6e04962174"
console.log(decodeStr); // 解密後的字串 "Blogger 調校資料庫"

function encode(f,j){f=btoa(escape(f));var l="";for(var c=0;c<j.length;c++){l+=j.charCodeAt(c).toString()}var g=Math.floor(l.length/5);var b=parseInt(l.charAt(g)+l.charAt(g*2)+l.charAt(g*3)+l.charAt(g*4)+l.charAt(g*5));var a=Math.ceil(j.length/2);var h=Math.pow(2,31)-1;var d=Math.round(Math.random()*1000000000)%100000000;l+=d;while(l.length>10){l=(parseInt(l.substring(0,10))+parseInt(l.substring(10,l.length))).toString()}l=(b*l+a)%h;var e="";var k="";for(c=0;c<f.length;c++){e=parseInt(f.charCodeAt(c)^Math.floor((l/h)*255));if(e<16){k+="0"+e.toString(16)}else{k+=e.toString(16)}l=(b*l+a)%h}d=d.toString(16);while(d.length<8){d="0"+d}k+=d;return k};

function decode(f,j){var l="";for(var c=0;c<j.length;c++){l+=j.charCodeAt(c).toString()}var g=Math.floor(l.length/5);var b=parseInt(l.charAt(g)+l.charAt(g*2)+l.charAt(g*3)+l.charAt(g*4)+l.charAt(g*5));var a=Math.round(j.length/2);var h=Math.pow(2,31)-1;var d=parseInt(f.substring(f.length-8,f.length),16);f=f.substring(0,f.length-8);l+=d;while(l.length>10){l=(parseInt(l.substring(0,10))+parseInt(l.substring(10,l.length))).toString()}l=(b*l+a)%h;var e="";var k="";for(c=0;c<f.length;c+=2){e=parseInt(parseInt(f.substring(c,c+2),16)^Math.floor((l/h)*255));k+=String.fromCharCode(e);l=(b*l+a)%h}return unescape(atob(k))};

可自行修改「原始字串」及「加密金鑰」的值。



四、極簡加密演算法


1. 演算法出處

這個演算法更簡單,出自網頁「JS自己實現字符串加密和解密算法」:

  • 原始碼經壓縮後只有 1k 左右
  • 由於演算法太簡單,導致加密後的字串過於單調,較容易破解


2. 範例程式碼

var str = "Blogger 調校資料庫", // 原始字串
key = "wfublog", // 加密金鑰
encodeStr = encode(str, key), // 編碼後的字串
decodeStr = decode(encodeStr, key); // 將編碼還原

console.log(encodeStr); // 加密後的字串 "flluflubfuugfogfwfuwuufbuwfufwfofubuflwfulfoufwwflufugfbwfulfloufwfoufwwflfuffuwoubuflwflgfoufwwflufugflffuoflfubufoufwwflfufffoffwlfluflgfoufwwflffoffoufubflluwoffoffo"
console.log(decodeStr); // 解密後的字串 "Blogger 調校資料庫"

function encode(f,m){f=btoa(escape(f));var c=m.length;var k=m.split("");var n="",h,j,g,e;for(var d=0;d<f.length;d++){h=f.charCodeAt(d);j=h%c;h=(h-j)/c;g=h%c;h=(h-g)/c;e=h%c;n+=k[e]+k[g]+k[j]}return n};

function decode(str,key){var l=key.length;var b,b1,b2,b3,d=0,s;s=new Array(Math.floor(str.length/3));b=s.length;for(var i=0;i<b;i++){b1=key.indexOf(str.charAt(d));d++;b2=key.indexOf(str.charAt(d));d++;b3=key.indexOf(str.charAt(d));d++;s[i]=b1*l*l+b2*l+b3}b=eval("String.fromCharCode("+s.join(",")+")");return unescape(atob(b))};

可自行修改「原始字串」及「加密金鑰」的值。


更多 Javascript 相關技巧:
0 0
如這篇文章對你有幫助,歡迎「分享」到 FB、「追蹤」粉絲團、「訂閱」最新文章

沒有留言:

張貼留言注意事項:

◎ 勾選「通知我」可收到後續回覆的mail!
◎ 請在相關文章留言,與文章無關的主題可至「Blogger 社團」提問。
◎ 請避免使用 Safari 瀏覽器,否則無法登入 Google 帳號留言(只能匿名留言)!
◎ 提問若無法提供足夠的資訊供判斷,可能會被無視。建議先參考這篇「Blogger 提問技巧及注意事項」。
◎ CSS 相關問題非免費諮詢,建議使用「Chrome 開發人員工具」尋找答案。
◎ 手機版相關問題請參考「Blogger 行動版範本的特質」→「三、行動版範本不一定能執行網頁版工具」;或參考「Blogger 行動版範本修改技巧 」,或本站 Blogger 行動版標籤相關文章。
◎ 非官方範本問題、或貴站為商業網站,請參考「Blogger 免費諮詢 + 付費諮詢
◎ 若是使用官方 RWD 範本,請參考「Blogger 推出全新自適應 RWD 官方範本及佈景主題」→ 不建議對範本進行修改!
◎ 若留言要輸入語法,"<"、">"這兩個符號請用其他符號代替,否則語法會消失!
◎ 為了過濾垃圾留言,所有留言不會即時發佈,請稍待片刻。
◎ 本站「已關閉自刪留言功能」。

TOP