Twój wniosek, że wypełnienie jest niepotrzebne, jest słuszny. Długość wejścia zawsze można jednoznacznie określić na podstawie długości zakodowanej sekwencji.
Jednak dopełnianie jest przydatne w sytuacjach, gdy łańcuchy kodowane algorytmem base64 są łączone w taki sposób, że tracone są długości poszczególnych sekwencji, co może się zdarzyć na przykład w bardzo prostym protokole sieciowym.
Jeśli ciągi nieparzyste są łączone, niemożliwe jest odzyskanie oryginalnych danych, ponieważ informacja o liczbie nieparzystych bajtów na końcu każdej pojedynczej sekwencji zostaje utracona. Jeśli jednak używane są sekwencje wypełnione, nie ma niejednoznaczności, a sekwencja jako całość może zostać poprawnie zdekodowana.
Edycja: ilustracja
Załóżmy, że mamy program, który koduje słowa base64, łączy je i wysyła przez sieć. Koduje „I”, „AM” i „TJM”, umieszcza wyniki razem bez wypełniania i przesyła je.
I
koduje do SQ
( SQ==
z dopełnieniem)
AM
koduje do QU0
( QU0=
z dopełnieniem)
TJM
koduje do VEpN
( VEpN
z dopełnieniem)
Więc przesyłane dane są SQQU0VEpN
. Odbiornik base64 dekoduje to zgodnie I\x04\x14\xd1Q)
z przeznaczeniem IAMTJM
. Wynik jest bezsensowny, ponieważ nadawca zniszczył informacje o tym, gdzie kończy się każde słowo w zakodowanej sekwencji. Gdyby nadawca wysłał SQ==QU0=VEpN
zamiast tego, odbiorca mógłby zdekodować to jako trzy oddzielne sekwencje base64, które połączyłyby się, aby dać IAMTJM
.
Po co zawracać sobie głowę wyściółką?
Dlaczego nie zaprojektować protokołu tak, aby poprzedzał każde słowo liczbą całkowitą? Wtedy odbiornik mógłby poprawnie dekodować strumień i nie byłoby potrzeby wypełniania.
To świetny pomysł, o ile znamy długość danych, które kodujemy, zanim zaczniemy je kodować. Ale co by było, gdybyśmy zamiast słów zakodowali fragmenty wideo z kamery na żywo? Możemy nie znać z góry długości każdego fragmentu.
Gdyby protokół używał wypełnienia, nie byłoby w ogóle potrzeby przesyłania długości. Dane mogą być zakodowane, gdy nadchodzą z kamery, każdy fragment zostałby zakończony wypełnieniem, a odbiornik byłby w stanie poprawnie zdekodować strumień.
Oczywiście jest to bardzo wymyślony przykład, ale być może ilustruje, dlaczego wypełnienie mogłoby być pomocne w niektórych sytuacjach.
A propos, oto podstawowy konwerter do dowolnej konwersji bazowej, który dla Ciebie stworzyłem. Cieszyć się! https://convert.zamicol.com/
Co to są znaki dopełniające?
Znaki dopełniające pomagają spełnić wymagania dotyczące długości i nie mają znaczenia.
Dziesiętny przykład dopełnienia: biorąc pod uwagę dowolne wymaganie, aby wszystkie ciągi miały długość 8 znaków, liczba 640 może spełnić to wymaganie, używając poprzedzających 0 jako znaków dopełniających, ponieważ nie mają one znaczenia „00000640”.
Kodowanie binarne
Paradygmat bajtów: bajt jest de facto standardową jednostką miary, a każdy schemat kodowania musi odnosić się z powrotem do bajtów.
Base256 dokładnie pasuje do tego paradygmatu. Jeden bajt to jeden znak w base256.
Base16 , szesnastkowy lub szesnastkowy, wykorzystuje 4 bity na każdy znak. Jeden bajt może reprezentować dwa znaki base16.
Base64 nie pasuje równomiernie do paradygmatu bajtów (ani base32), w przeciwieństwie do base256 i base16. Wszystkie znaki base64 mogą być reprezentowane w 6 bitach, 2 bity krótkie od pełnego bajtu.
Możemy przedstawić kodowanie base64 w porównaniu z paradygmatem bajtów jako ułamek: 6 bitów na znak w 8 bitach na bajt . Zmniejszono ten ułamek o 3 bajty ponad 4 znaki.
Ten współczynnik, 3 bajty na każde 4 znaki base64, jest regułą, której chcemy przestrzegać podczas kodowania base64. Kodowanie Base64 może obiecać tylko pomiary z pakietami 3-bajtowymi, w przeciwieństwie do base16 i base256, gdzie każdy bajt może stać sam.
Dlaczego więc zachęca się do wypełniania, mimo że kodowanie mogłoby działać dobrze bez znaków wypełniających?
Jeśli długość strumienia jest nieznana lub jeśli może być pomocne dokładne poznanie końca strumienia danych, użyj dopełnienia. Znaki wypełniające wyraźnie informują, że te dodatkowe miejsca powinny być puste, i wyklucza jakąkolwiek dwuznaczność. Nawet jeśli długość jest nieznana z dopełnieniem, będziesz wiedzieć, gdzie kończy się strumień danych.
Jako kontrprzykład, niektóre standardy, takie jak JOSE , nie pozwalają na dopełnianie znaków. W takim przypadku, jeśli czegoś brakuje, podpis kryptograficzny nie będzie działał lub będzie brakować innych znaków spoza base64 (np. „.”). Chociaż założenia dotyczące długości nie są poczynione, wypełnienie nie jest potrzebne, ponieważ jeśli coś jest nie tak, po prostu nie zadziała.
Dokładnie tak mówi dokument RFC dotyczący base64 :
Dopełnienie pozwala nam dekodować kodowanie base64 z obietnicą braku utraconych bitów. Bez wypełnienia nie ma już wyraźnego potwierdzenia pomiaru w pakietach trzech bajtów. Bez dopełnienia możesz nie być w stanie zagwarantować dokładnego odtworzenia oryginalnego kodowania bez dodatkowych informacji, zwykle z innego miejsca na stosie, takich jak TCP, sumy kontrolne lub inne metody.
Przykłady
Oto przykład formularza RFC 4648 ( http://tools.ietf.org/html/rfc4648#section-8 )
Każdy znak wewnątrz funkcji „BASE64” zajmuje jeden bajt (base256). Następnie tłumaczymy to na base64.
Oto koder, z którym możesz się pobawić: http://www.motobit.com/util/base64-decoder-encoder.asp
źródło
char*
, potrzebujesz rozmiaru łańcucha lub terminatora null. Wypełnienie jest zbędne. Stąd pytanie OP.W dzisiejszych czasach nie ma z tego wiele korzyści. Spójrzmy więc na to jako na pytanie, jaki mógł być pierwotny cel historyczny.
Kodowanie Base64 pojawia się po raz pierwszy w dokumencie RFC 1421 z 1993 r. Ten dokument RFC w rzeczywistości koncentruje się na szyfrowaniu wiadomości e-mail, a base64 jest opisany w jednej małej sekcji 4.3.2.4 .
W tym dokumencie RFC nie wyjaśniono celu wypełnienia. Najbliższą nam wzmianką o pierwotnym celu jest to zdanie:
Nie sugeruje konkatenacji (najlepsza odpowiedź tutaj) ani łatwości implementacji jako wyraźnego celu wypełnienia. Jednak biorąc pod uwagę cały opis, nie jest nierozsądne założenie, że mogło to mieć na celu ułatwienie dekoderowi odczytywania danych wejściowych w jednostkach 32-bitowych ( „kwantach” ). Obecnie nie przynosi to żadnych korzyści, jednak w 1993 roku niebezpieczny kod C najprawdopodobniej faktycznie wykorzystałby tę właściwość.
źródło
b'Zm9vYmFyZm9vYg==' b'Zm9vYmFyZm9vYmE=' b'Zm9vYmFyZm9vYmFy' b'Zm9vYmFyZm9vYmFyZg==' b'Zm9vYmFyZm9vYmFyZm8=' b'Zm9vYmFyZm9vYmFyZm9v'
jest taka sama jak w przypadkub'Zm9vYmFyZm9vYg=' b'Zm9vYmFyZm9vYmE=' b'Zm9vYmFyZm9vYmFy=' b'Zm9vYmFyZm9vYmFyZg=' b'Zm9vYmFyZm9vYmFyZm8=' b'Zm9vYmFyZm9vYmFyZm9v='