Dlaczego łańcuch zakodowany w base64 ma na końcu znak =

321

Wiem, co to base64jest kodowanie i jak obliczyć base64kodowanie w C #, jednak kilkakrotnie widziałem, że kiedy przekonwertuję ciąg na base64, jest =na końcu.

Pojawiło się kilka pytań:

  1. Czy base64ciąg zawsze kończy się na =?
  2. Dlaczego =dodaje się na końcu?
Santosh Singh
źródło
9
Nie ma to absolutnie nic wspólnego z C #.
BoltClock
19
W rzeczywistości jest to związane z c #, nie wszystkie języki będą zawierać =, na przykład wiele bibliotek perla pomija =, więc znajomość środowiska, z którego korzysta użytkownik, jest rzeczywiście istotna.
Jacob
Wygląda na to, że w niektórych przypadkach jest to mniej skuteczna metoda zaciemniania, ponieważ jest dość wykrywalna.
dgo
6
@ user1167442 Base64 nie służy do zaciemniania. Służy do transportu danych binarnych (lub ciągów znaków z Unicode i innymi znakami specjalnymi) jako ciąg.
NH.

Odpowiedzi:

269

Służy jako wyściółka .

Bardziej kompletną odpowiedzią jest to, że łańcuch zakodowany w base64 nie zawsze kończy się na a =, kończy się tylko na jednym lub dwóch, =jeśli są one wymagane do uzupełnienia łańcucha na odpowiednią długość.

Andrew Hare
źródło
3
„Jednym z przypadków, w których wymagane są znaki dopełniające, jest łączenie wielu plików zakodowanych w standardzie Base64”.
André Puel,
1
@ AndréPuel: =wystarczy zsynchronizować jeden singiel . Jeśli chcesz znaleźć granice, to zawsze powinien być obecny terminator (i wciąż potrzebny jest tylko jeden znak). Cała koncepcja wypełniania Base64 to tylko mózg ...
6502
5
Ten link jest jednak zupełnie nieistotny dla base64.
NH.
1
Chciałbym tylko, aby opublikowano odpowiedni i niezawodny link, który wyjaśnia base64efektywne wypełnianie za pomocą ilustracji i przykładów. Obecny link do wikipedii jest absolutnie nieistotny jak @NH. wzmiankowany.
Fr0zenFyr
1
@ Fr0zenFyr Jeśli chcesz link, en.wikipedia.org/wiki/Base64#Output_padding jest całkiem niezły. Ale odpowiedź Badra jest naprawdę lepsza (po prostu jeszcze nie dogoniła głosów).
NH.
312

1-nr

2- Jako krótka odpowiedź: 65. znak (znak „=”) jest używany tylko jako uzupełnienie w końcowym procesie kodowania wiadomości.

Nie będziesz miał znaku „=”, jeśli ciąg ma wielokrotność liczby 3 znaków, ponieważ Base64kodowanie zajmuje każde trzy bajty (8 bitów) i reprezentuje je jako cztery znaki do wydrukowania w standardzie ASCII.

Detale :

(a) Jeśli chcesz zakodować

ABCDEFG <=> [ ABC] [ DEF] [G

Base64poradzi sobie (wytwarzając 4 znaki) z pierwszym blokiem i drugim (gdy są kompletne), ale w przypadku trzeciego doda podwójny ==wynik w celu uzupełnienia 4 potrzebnych znaków. Zatem wynik będzie QUJD REVG Rw == (bez spacji)

(b) Jeśli chcesz zakodować ...

ABCDEFGH <=> [ ABC] [ DEF] [GH

Podobnie doda tylko jeden =koniec na wyjściu, aby uzyskać 4 znaki, wynikiem będzie QUJD REVG R0g = (bez spacji)

Badr Bellaj
źródło
26
Jest to bardziej kompletne i jasne niż inne odpowiedzi, a nawet Wikipedia, i powinno zasłużyć na więcej głosów niż zaakceptowana odpowiedź, która jedynie wskazuje na link do Wikipedii. Uznanie dla ciebie! Pozytywne!
ANewGuyInTown
2
@ANewGuyInTown link do Wikipedii w zaakceptowanym rozwiązaniu jest niepoprawny, nie ma nic wspólnego z wypełnianiem na base64. Prawidłowa strona została połączona przez Legolasa w odpowiedzi poniżej
Fr0zenFyr
Kolejna dobra (IMHO) odpowiedź na temat wypełnienia base64
spottedmahn
66

Z Wikipedii :

Ostatnia sekwencja „==” wskazuje, że ostatnia grupa zawierała tylko jeden bajt, a „=” oznacza, że ​​zawierał dwa bajty.

Jest to więc rodzaj wypełnienia.

Legolas
źródło
16
  1. Nie.
  2. Aby dopełnić ciąg zakodowany w Base64 do długości 4 znaków, aby można go było poprawnie zdekodować.
Ian Kemp
źródło
3
Usunąłem =pod koniec i przetestowałem to dla 1 miliona ciągów. Dekodowanie zawsze pasowało.
vivek_23,
15

Jest zdefiniowany w RFC 2045 jako specjalny znak wypełniający, jeśli na końcu zakodowanych danych dostępnych jest mniej niż 24 bity.

iandotkelly
źródło
11

Znak równości (=) jest używany jako dopełnienie w niektórych formach kodowania base64. Artykuł w Wikipedii na temat base64 zawiera wszystkie szczegóły.

Sam Holloway
źródło
2
Czy możesz wyjaśnić logikę, dlaczego „==” ma 1 bajt, a „=” to 2 bajty? Po prostu nie mogę tego zrozumieć. Jak przychodzi wkład: „jakakolwiek cielesna przyjemność”. może otrzymać wynik „YW55IGNhcm5hbCBwbGVhc3VyZS4 =”, podczas gdy „jakakolwiek cielesna przyjemność” może uzyskać wynik „YW55IGNhcm5hbCBwbGVhc3VyZQ ==”?
null
14
Nie jest tak, że „==” to 1 bajt, a „=” to 2 bajty. Jest tak, że musisz zawsze mieć wielokrotność 4 bajtów w całym ciągu. Więc wpisuj znaki „=”, dopóki tego nie uzyskasz. Pierwszy ciąg ma jeszcze jeden znak niż drugi, więc wymagany jest jeden mniej „=” wypełnienia.
Sam Holloway
2
Czy ta odpowiedź ma być komentarzem?
Fr0zenFyr
9

Padding Od http://en.wikipedia.org/wiki/Base64 :

Teoretycznie znak wypełniania nie jest potrzebny do dekodowania, ponieważ liczbę brakujących bajtów można obliczyć na podstawie liczby cyfr Base64. W niektórych implementacjach znak wypełniający jest obowiązkowy, podczas gdy w innych nie jest używany. Jednym z przypadków, w których wymagane są znaki dopełniające, jest łączenie wielu plików zakodowanych w standardzie Base64.

Thomas Leonard
źródło
1
Część o „Jednym przypadku, w którym wymagane są znaki dopełniające, jest łączenie wielu plików zakodowanych w standardzie Base64”. jest źle. Na przykład podczas łączenia dwóch plików base64, w których bajty źródłowe dla każdego pliku mają długość 3 bajtów, łańcuchy base64 będą miały długość 4 znaków i nie będą zawierać bajtów wypełniania. Kiedy połączysz te dwa ciągi base64, nie będzie sposobu, aby powiedzieć, gdzie zaczyna się, a drugi opiera wyłącznie na łączonym ciągu. Więc poleganie na padding base64, aby pomóc w tym, nie zadziała. Ten problem będzie występował dla każdego pliku o długości bajtów równomiernie podzielnej przez 3.
Ron C
1
Myślę, że oznacza to przypadek, w którym końcowym rezultatem powinna być konkatenacja danych wejściowych. np. decode(encode(A)+encode(B))=A+Bdziała z wypełnieniem, ale nie bez.
Thomas Leonard
być może, ale takie ograniczone użycie nie pozwala na poleganie na znakach wypełniających w ogólnym przypadku oddzielania zakodowanych ciągów, gdy zakodowane ciągi są łączone razem. Wspominam o tym tylko, aby pomóc programistom, którzy mogą myśleć, że mogą z niego korzystać w ten sposób.
Ron C
1
Myślę, że twój sprzeciw naprawdę podkreśla różnicę między pojęciami wypełniania i rozgraniczania. Na ogół nie oczekuje się, że wyniki konkatenacji będą zawierać wystarczającą ilość informacji, aby umożliwić ich odwrócenie. Nie będziesz wiedział, czy „c3dpenpsZXJz” był pierwotnie „c3dpenps” + „ZXJz” czy „c3dp” + „enpsZXJz”. Ale nie wiesz również, czy „swizzlers” był pierwotnie „swi” + „zzlers” czy „swizzl” + „ers”.
GargantuChet
1
Skopiowanie mojego komentarza z pokrewnej odpowiedzi wypełniania Base64 :> konkatenacja Base64 [z '=' padding] pozwala koderom przetwarzać duże porcje równolegle bez konieczności wyrównywania wielkości porcji do wielokrotności trzech. Podobnie, jako szczegół implementacji, może istnieć koder, który musi opróżnić wewnętrzny bufor danych o rozmiarze, który nie jest wielokrotnością trzech.
Andre D
7

http://www.hcidata.info/base64.htm

Kodowanie „Mary miała” na podstawie 64

W tym przykładzie używamy prostego ciągu tekstowego („Mary miała”), ale zasada obowiązuje bez względu na dane (np. Plik graficzny). Aby przekonwertować każde 24 bity danych wejściowych na 32 bity wyjściowe, kodowanie Base 64 dzieli 24 bity na 4 porcje po 6 bitów. Pierwszym problemem, jaki zauważamy, jest to, że „Mary miała” nie jest wielokrotnością 3 bajtów - ma długość 8 bajtów. Z tego powodu ostatnia grupa bitów ma tylko 4 bity. Aby temu zaradzić, dodajemy dwa dodatkowe bity „0” i zapamiętujemy ten fakt, umieszczając na końcu „=”. Jeśli ciąg tekstowy, który ma zostać przekonwertowany na bazę 64, miałby 7 bajtów, ostatnia grupa miałaby 2 bity. W tym przypadku dodalibyśmy cztery dodatkowe bity „0” i pamiętamy ten fakt, umieszczając na końcu „==”.

Dev
źródło