最近開發過程當中常常會須要Base64編碼,MD5,加密等功能,這些頻繁使用的小工具要常常到網上找,並且還都不太好用,就本身開發了一個, codoolo。在實現Base64的過程,也學到了不少。這篇文件記錄Base64相關的知識,歡迎指正。
Base64早已經被普遍使用了,尤爲是Multipurpose Internet Mail Extensions (MIME)。html
wikipedia中對Base64的定義:安全
Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation.
簡單來講,Base64使用了指定的64個字符對數據編碼,而這64個字符中不包括特殊字符(以避免被一些應用認爲是控制字符,若是ftp,ssh等),這樣通過編碼的數據能夠在網絡中安全的傳輸。網絡
首先須要挑選64個字符。RFC 4648定義了Base64的字符集:ssh
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/工具
下圖顯示如何將字符串「xyz」編碼爲「eH16」的過程編碼
第二步和第三步實際上是一系列位操做,並不須要真的轉換,這裏爲了將編碼過程闡述清楚,加了這兩個步驟。加密
因爲6位正好能夠表示64,因此每3個8位的字符(24bit)能夠編碼爲4個Base64字符(4個6bit=24bit)。但編碼後的每一個字符的存儲仍然須要8位。這意味着Base64編碼後的存儲空間增長了1/3spa
Base64使用6 bits重組數據,但重組後的每一個字符仍然須要8 bit的存儲空間。因此Base64是用較小的字符集表示數據,但存儲空間卻所以增長了,所謂有一利必有一弊。code
在上面的Base64字符集中包括了 '+/' ,而通常的URL和文件名中,不能使用這兩個字符,因此RFC4686提議使用另一個字符集:orm
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
而具體用哪一個字符集,要考慮使用的場景。好比只是在項目內部使用,編解碼均可控,那麼就可使用第二個,甚至可使用一個自定義的字符集。但若是是將數據給第三方,那麼使用第一個字符集更好,由於大部分庫的實現都使用了第一個字符集。
咱們剛剛說了如何將3個字符應用Base64編碼,但若是字符串的長度不是3的倍數怎麼辦?
若是最後還有兩個字符須要編碼:
好比"xy",2個字符有16 bits,那麼前12 bits能夠編碼爲"eH",對於剩下的4 bits,在右側填充2個0,因此第三個字符是"k"。有時,網絡中傳輸的數據長度是未知的,這時爲了肯定知道數據是否截止,則須要將編碼的數據補齊爲4的倍數。對於Base64編碼,使用 = 來補齊,也就是第65個字符。
若是最後只有一個字符,過程相似:
須要注意的是,最後使用了2個 == 來補齊。
請問,若是一個Base64編碼的最後有3個=,即===,這是一個合法的Base64編碼麼?
咱們上面討論編碼的時候,都假設輸入的是ASCII,即字符是0x00-0xFF之間的。那若是輸入的字符是UTF-8呢?好比:
「こんにちは」 或者 「你好」
通常有兩種方式來處理:
因此在實現codoolo時, 若是輸入的是非ASCII碼,會提示選擇一個轉換器:
瞭解了編碼過程,相信解碼就比較簡單了,也就是將上面的過程逆向執行就能夠。
說實話,我一直在使用Base64編碼,到從沒想過一個Base64編碼也要有這麼多須要注意的地方,並且還有問題:
咱們之後接着聊。