先說結論
不算。Base64 是一種編碼:用六十四個不惹事的字元,把任何資料重新寫一遍,好讓它穿過那些只為純文字修的系統時不散架。它沒有金鑰,沒有秘密,沒有任何一種安全性質。要還原它,只需認出它,別的什麼都不用。人要一眼,計算機要一毫秒。
這個問題仍然值得問,因為這場混淆到處都是,偶爾還很貴。base64 的字串看起來亂:cGFzc3dvcmQ= 對眼睛什麼也不交代。而看著亂的東西,就被歸進了「安全」那個抽屜。真有產品帶著這樣「保護」起來的密碼出過廠。藥方是一次學會的一組區別:編碼是給機器的,加密是給秘密的,雜湊是當指紋的。三件事,三樣工具,護得住東西的只有一樣。
編碼:誰都能還原
編碼改的是資料的寫法,從不改它說了什麼。郵件附件、樣式表裡嵌的圖、網址裡的令牌,處處都有一堆任意位元組要過只認文字的路,base64 就是那身標準行頭:三個位元組進去,四個字元出來,用的是字母、數字加兩個符號,末尾拿 = 補齊。認準末尾這個 =,往後你會發現 base64 無處不在。
定乾坤的性質是這一條:配方是公開的,倒著跑也一模一樣。沒有什麼可知道的,也就沒有什麼可不知道的。網址裡的百分號編碼(空格寫成 %20)、HTML 實體(&)、十六進位、反斜槓轉義,都是同一個主意穿不同的衣服。這裡的 Base64 編解碼工具全都會說,雙向都行,就在你自己的機器上。把撿到的字串解開,和把它讀一遍一樣正當,因為編碼從來就不是鎖。
加密:持鑰匙的人能還原
真護得住內容的是加密。它用一把金鑰變換資料,數學擺的陣勢是:沒有金鑰,逆變換不只是難,是運算能力夠不著;有金鑰,瞬間完成。秘密全住在金鑰裡,不住在方法裡。演算法是公開的,是標準,也正因如此才結實。
視覺上的混淆就咬在這裡,因為加密後的位元組為了上路,照例要過一遍 base64:先讓金鑰攪亂,再穿上趕路的行頭。兩層,兩件事。JSON Web Token 是課本級的例子:三段 base64 用點連著,前兩段誰去試,都能解成能讀的 JSON。天天有人把令牌貼進公開的網頁解碼器,只因為以為整個是封死的。老實的說法是:JWT 是一張帶防偽簽名的明信片,不是信封。
雜湊:誰也還原不了
雜湊只朝一個方向跑。多少資料都行,塞進 SHA-256,出來一個定長的數。同樣的資料,每次同一個數;差一個位元的資料,一個面目全非的數。而從數回到資料的路,誰都沒有,帶不帶鑰匙都沒有。它不是行頭也不是鎖,它是指紋。
正因如此,屬於它的兩件事它做得最對。核對下載的檔案是不是釋出者釋出的那一個:對指紋。這工作雜湊與校驗和工具在你機器上做,還有配套的指南。再有是存密碼:運營得體的服務只存你密碼的雜湊,連它被偷走的資料庫裡也沒有密碼本身。哪家網站能把你忘掉的密碼用郵件發回來,它就等於告訴你,它從來沒做過雜湊。哪份配置把密碼寫成 cGFzc3dvcmQ= 來「保護」,它就等於告訴你,它只做過編碼。
在野外把三個認出來
對著眼前這串字元,有條管用的捷徑:
- 解出來是能讀的東西?那就是編碼。字母數字,或許有
+和/,末尾常有=。丟進解碼器看一眼。 - 解出來是一堆二進位雜訊?那 base64 只是行頭,底下的東西要麼加密了,要麼壓縮了,要麼壓根不是文字。兩種情況,編碼都什麼也告訴不了你。
- 定長、十六進位字元、從來解不開?64 個十六進位字元是 SHA-256 的身形,32 個是 MD5 的。雜湊不解碼,只有對得上和對不上。
每一個的實操教訓各一句:保密的事,永遠別託付給編碼;平臺帶著現成的加密,永遠別自己造;密碼除了雜湊,別用任何形式存。還有一層:你為了驗證而去解碼的那串字元,自己往往就是敏感的部分。除錯中的令牌多半如此。所以這裡的解碼器跑在秘密本來就在的地方,你的機器上;所以往網頁工具裡貼上到底意味著什麼,另有自己的一頁。