Удалить трейлинг "=" при кодировании base64 - PullRequest
41 голосов
/ 20 декабря 2010

Я замечаю, что всякий раз, когда я кодирую строку в base64, в конце добавляется символ "=". Могу ли я удалить этот символ, а затем надежно расшифровать его, добавив обратно, или это опасно? Другими словами, "=" всегда добавляется или только в определенных случаях?

Я хочу, чтобы моя закодированная строка была как можно короче, поэтому я хочу знать, всегда ли я могу удалить символ "=" и просто добавить его обратно перед декодированием.

Ответы [ 8 ]

59 голосов
/ 20 декабря 2010

= - отступ.

Википедия говорит

Выделен дополнительный символ пэда, который может использоваться для принудительного преобразования закодированного вывода в целое число, кратное 4 символам (или эквивалентно, когдане закодированный двоичный текст не кратен 3 байтам);эти символы дополнения должны затем быть отброшены при декодировании, но все же позволяют вычислять эффективную длину незакодированного текста, когда его входная двоичная длина не будет кратна 3 байтам (последний символ без отступа обычно кодируется так, чтобы последний6-битный блок, который он представляет, будет дополнен нулями его младших значащих битов, в конце закодированного потока может быть не более двух символов дополнения).

Если вы управляете другим концом, вы можете удалить его во время транспортировки, а затем повторно вставить его (проверив длину строки) перед декодированием.
Обратите внимание, что данные не будут действительнымиBase64 в транспорте.

22 голосов
/ 21 августа 2011

В 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/

22 голосов
/ 25 января 2011

Я написал часть декодера Apache commons-codec-1.4.jar Base64, и в этой логике у нас все хорошо без дополняющих символов. Конец файла и Конец потока являются такими же хорошими показателями того, что сообщение Base64 завершено, как любое количество символов «=»!

Вариант URL-Safe, который мы представили в commons-codec-1.4, пропускает символы заполнения, чтобы уменьшить размер!

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

Полагаю, более безопасный ответ: «зависит от реализации вашего декодера», но логически не сложно написать декодер, который не нуждается в заполнении.

8 голосов
/ 20 декабря 2010

= добавлено для заполнения. Длина строки base64 должна быть кратна 4, поэтому при необходимости добавляются 1 или 2 =.

Читайте: нет, вы не должны удалять его.

3 голосов
/ 06 октября 2016

На 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

1 голос
/ 21 мая 2019

Если вы кодируете байты (с фиксированной длиной битов), то заполнение является избыточным.Это относится к большинству людей.

Base64 потребляет 6 битов за раз и создает байт из 8 битов, который использует только комбинации из шести битов.

Если ваша строка равна 1 байту (8 бит), вы получите 12 бит, как наименьшее число, кратное 6, в которое поместится 8, с дополнительными 4 битами.Если ваша строка составляет 2 байта, вы должны вывести 18 битов, с дополнительными двумя битами.Для кратных шести против кратных 8 вы можете иметь остаток 0, 2 или 4 бита.

Заполнение говорит, что игнорировать эти дополнительные четыре (==) или два (=) бита.Заполнение здесь сообщает декодеру о вашем заполнении.

Заполнение действительно не нужно, когда вы кодируете байты.Кодер base64 может просто игнорировать оставшиеся биты, которые составляют менее 8 бит.В этом случае лучше удалить его.

Заполнение может быть полезно для потоковой передачи и битовых последовательностей произвольной длины, если они кратны двум.Это также может быть использовано для случаев, когда люди хотят отправлять только последние 4 бита, когда осталось больше битов, если все оставшиеся биты равны нулю.Некоторые люди могут захотеть использовать его для обнаружения неполных последовательностей, хотя вряд ли это надежно для этого.Я никогда не видел эту оптимизацию на практике.Люди редко сталкиваются с такими ситуациями, большинство людей используют base64 для дискретных байтовых последовательностей.

Если вы видите ответы, предлагающие оставить его включенным, это не очень хорошее поощрение, если вы просто кодируете байты, это включает функцию длямножество обстоятельств у вас нет.Единственная причина, по которой он должен быть включен в этом случае, может заключаться в добавлении допуска к декодерам, которые не работают без заполнения.Если вы контролируете оба конца, это не проблема.

1 голос
/ 30 октября 2018

Если вы используете PHP, следующая функция вернет вырезанную строку в исходный формат с правильным заполнением:

<?php

$str = 'base64 encoded string without equal signs stripped';
$str = str_pad($str, strlen($str) + (4 - ((strlen($str) % 4) ?: 4)), '=');

echo $str, "\n";
0 голосов
/ 01 мая 2019

Используя Python, вы можете удалить заполнение base64 и добавить его обратно так:

from math import ceil

stripped = original.rstrip('=')

original = stripped.ljust(ceil(len(stripped) / 4) * 4, '=')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...