2010-12-20 113 views
35

我注意到,無論何時base64編碼一個字符串,結尾都會加上「=」。我可以刪除這個角色,然後通過加回來可靠地解碼它,或者這是危險的嗎?換句話說,是否附加了「=」總是,或者僅在某些情況下?當base64編碼時去除尾隨「=」

我希望我的編碼字符串儘可能短,這就是爲什麼我想知道我是否總是可以刪除「=」字符並在解碼之前將其添加回來。

感謝

+1

讓我們定義'的base64 sensible'爲'base64'-不補,漂亮嗎?這些等同字符是完全多餘的,因此完全沒有意義。如果您編寫base64解碼器,請考慮不要拒絕沒有填充的輸入。 – 2013-12-03 17:09:54

回答

48

=是填充。

Wikipedia

一個附加的填充字符是 分配可被用於迫使 編碼輸出到一個整數 數倍的4個字符(或 等效地當未編碼的二進制 文本不是3個字節的倍數);然後 這些填充字符必須是 進行解碼時被丟棄,但仍 允許有效 長度未編碼的文本中,計算時,其 輸入二進制長度將不會是一個 倍數的3個字節(最後一個非墊 字符通常被編碼爲使得它表示的 的最後6位塊將在其最少的 有效位上被填零,最多兩個填充 字符可能發生在 編碼流的末尾)。

如果您控制另一端,則可以在傳輸時將其刪除,然後在解碼之前重新插入它(通過檢查字符串長度)。
請注意,數據在傳輸中不會有效。

+0

看起來這可能實際上並不奏效,因爲在解碼結束時,我們需要知道編碼端是否刪除了「=」。我無法包含該信息。 – 2010-12-20 18:48:20

+39

@Steve:如果長度不是4個字符的倍數,則直接加上'='字符。在.Net中,'if(str.Length%4!= 0)str + = new string('=',4 - str.Length%4)' – SLaks 2010-12-20 18:50:46

+10

請注意,在PHP中'base64_decode'將接受字符串* ,因此如果您稍後以PHP將其刪除,則無需將其添加回去。 – Mahn 2014-10-16 16:33:13

5

=用於填充。 base64字符串的長度應該是4的倍數,因此根據需要添加1或2個=

閱讀:不,你不應該刪除它。

+0

一個有用的答案。 – Exception 2016-01-22 12:33:51

+0

所以告訴我。爲什麼在編碼Base64 URL安全時不會發生這種情況? – 2016-09-20 07:31:24

+0

@NoFuchsGiven。如果你使用的圖書館(而不是語言)RTFM(提示:谷歌給了我這個鏈接https://people.eecs.berkeley.edu/~jonah/bc/org/bouncycastle/util/encoders/UrlBase64 .html),你試着想一下在URL中提供了什麼字符保留爲分隔符(提示:「=」),並且你將所有這一切與規範中不需要填充的事實結合起來(同樣,TFM救援https://tools.ietf.org/html/rfc4648#section-3.2)答案應該是明顯的。 – 2016-09-20 13:44:06

21

我寫了Apache的commons-codec-1.4.jar Base64解碼器的一部分,並且在那個邏輯中我們沒有填充字符。文件結束和數據流結束等同於Base64消息完成的任何數量的'='字符!

我們在commons-codec-1.4中引入的URL安全變體省略了填充字符,目的是爲了使事物變小!

http://commons.apache.org/codec/apidocs/src-html/org/apache/commons/codec/binary/Base64.html#line.478

我想一個更安全的答案是,「取決於你的解碼器實施方案」,但在邏輯上它並不難寫,並不需要填充的解碼器。

+1

有趣的是,感謝這個角度。我想知道這個填充是爲了優化硬件實現。 – 2011-01-26 15:00:13

+0

用戶應該注意,如果您編碼爲URL安全,然後另一個程序使用Apache以外的其他程序進行解碼,則它將無法正確解碼。 – smcg 2013-07-25 18:21:01

+0

網址安全也做額外的轉換,: encodeUrlSafe(解碼( 「d8vb15jT4MYKb7RpvtJq +/EH8K1h5XH14Oi + 3NtrLcM」))= = 「d8vb15jT4MYKb7RpvtJq-_EH8K1h5XH14Oi-3NtrLcM」 在這裏,您可以看到,它與減+替換和/帶_ – stokito 2016-03-16 08:40:17

15

在JavaScript中,你可以做這樣的事情:

// if this is your Base64 encoded string 
var str = 'VGhpcyBpcyBhbiBhd2Vzb21lIHNjcmlwdA=='; 

// make URL friendly: 
str = str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, ''); 

// reverse to original encoding 
if (str.length % 4 != 0) 
    str += ('===').slice(0, 4 - (str.length % 4)); 
str = str.replace(/-/g, '+').replace(/_/g, '/'); 

參見本小提琴:http://jsfiddle.net/7bjaT/66/

3

在Android上我用這:

全球

String CHARSET_NAME ="UTF-8"; 

編碼

String base64 = new String(
      Base64.encode(byteArray, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_CLOSE | Base64.NO_WRAP), 
      CHARSET_NAME); 
return base64.trim(); 

解碼

byte[] bytes = Base64.decode(base64String, 
      Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_CLOSE | Base64.NO_WRAP); 

等於該上的Java:

編碼

private static String base64UrlEncode(byte[] input) 
{ 
    Base64 encoder = new Base64(true); 
    byte[] encodedBytes = encoder.encode(input); 
    return StringUtils.newStringUtf8(encodedBytes).trim(); 
} 

解碼

private static byte[] base64UrlDecode(String input) { 
    byte[] originalValue = StringUtils.getBytesUtf8(input); 
    Base64 decoder = new Base64(true); 
    return decoder.decode(originalValue); 
} 

我從來沒有尾隨 「=」 的問題,我使用BouncyCastle的以及