# #go #base64
Вопрос:
Как мы знаем, существует два способа декодирования строки base64 в go base64.StdEncoding
или base64.RawStdEncoding
. Как правильно использовать один из них для декодирования одной строки base64? Если вызывается неправильный метод кодирования. Например, если RawStdEncoding
используется для декодирования одной StdEncoding
строки, illegal base64 data at input byte xxx
появится ошибка.
Согласно документу
const (
StdPadding rune = '=' // Standard padding character
NoPadding rune = -1 // No padding
)
RawStdEncoding — это стандартная необработанная кодировка base64 без добавления, как определено в разделе 3.2 RFC 4648. Это то же самое, что и стандартное кодирование, но без символов заполнения.
Должны ли мы различать их, проверяя конец заполнения StdPadding
или нет? фрагмент кода
lastByte := s[len(s)-1:]
if lastByte == string(base64.StdPadding) {
base64.StdEncoding.DecodeString(s)
} else {
base64.RawStdEncoding.DecodeString(s)
}
Это элегантный способ сделать это? Или я чего-то не хватает? Каков элегантный способ декодирования строки base64?
Обновить:
Возможно, один из необработанных способов сделать это с помощью проверки ошибок, как показано ниже
rawByte, err := base64.StdEncoding.DecodeString(s)
if err != nil {
rawByte, err = base64.RawStdEncoding.DecodeString(s)
}
Комментарии:
1. обратите внимание, что стандартная кодировка добавляет дополнение
=
только тогда, когда длина исходного текста не кратна 3. Таким образом, вы не можете основывать это на существовании=
символов. Например. с помощью std encfoo
кодируетZm9v
. Игровая площадка play.golang.org/p/ggPdE9RlCDZ2. Коротко: вы должны знать , какая кодировка использовалась.
3. Также существует более 2 кодировок base64. Смотрите ниже.
Ответ №1:
Как мы знаем, существует два метода декодирования строки base64 в go base64.StdEncoding или base64.RawStdEncoding.
существует также base64.URLEncoding, который использует символы -
и _
в качестве заменителей небезопасных для URL символов base64
и /
.
Должны ли мы различать их, проверяя, является ли конец заполнения StdPadding или нет? фрагмент кода
Это не сработает. Вероятность того, что кодировка base64 не будет иметь видимого заполнения, составляет 1 к 3:
b := []byte("abc123") // len(b) % 3 == 0 - no padding
fmt.Println(base64.StdEncoding.EncodeToString(b)) // YWJjMTIz
fmt.Println(base64.RawStdEncoding.EncodeToString(b)) // YWJjMTIz
https://play.golang.org/p/LMtIHlyXdn7
итак, как вы отличаете их друг от друга и определяете, какая кодировка использовалась?
Да, вы можете — двойное декодирование, как в вашем обновленном вопросе:
rawByte, err := base64.StdEncoding.DecodeString(s)
if err != nil {
rawByte, err = base64.RawStdEncoding.DecodeString(s)
}
Есть несколько приемов, которые вы можете использовать, чтобы сделать несколько обоснованных предположений. Например:
e := base64.StdEncoding.EncodeToString(b) // always produces a mutiple of 4 length
if len(e) % 4 != 0 {
// cannot be base64.StdEncoding - so try base64.RawStdEncoding?
}
Ответ №2:
Если вы получите illegal base64 data at input byte ...
, то:
- вы либо использовали неправильный декодер base64, либо
- после строки base64 есть дополнительные данные, которые необходимо удалить перед вызовом декодера, или
- входные данные не являются base64.
Должны ли мы различать их, проверяя, является ли конец заполнения StdPadding или нет?
Нет. Точно так же, как вы знаете, что данные вообще закодированы в base64, вы также должны знать, как именно они кодируются, и использовать, например, либо base64.StdEncoding
или base64.RawStdEncoding
, а не оба. Вы не угадываете эти вещи, а просто используете метод decode, который соответствует кодировке, используемой отправителем.
Кодировка Base64 может отличаться на:
- дополненный / не дополненный (без
=
s в конце) - стандартный (
/
) или URL (-
,_
) алфавит - с / без перевода строк (например, MIME разбивает строки на 76 символов, PEM на 64)
Вы можете визуально осмотреть закодированную строку, чтобы угадать схему кодирования. Но обратите внимание, что заполнение присутствует не всегда — это зависит от того, кратна ли длина исходных данных 3 или нет, поскольку каждый кортеж из 3 байт кодируется как 4 6-битных символа.