Dziwne \ nw łańcuchu zakodowanym algorytmem base64 w Rubim

159

Wbudowana biblioteka Base64 w Rubim dodaje kilka '\ n'. Nie mogę znaleźć przyczyny. W tym szczególnym przykładzie:

irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'base64'
=> true
irb(main):003:0> str =  "1110--ad6ca0b06e1fbeb7e6518a0418a73a6e04a67054"
=> "1110--ad6ca0b06e1fbeb7e6518a0418a73a6e04a67054"
irb(main):004:0> Base64.encode64(str)
=> "MTExMC0tYWQ2Y2EwYjA2ZTFmYmViN2U2NTE4YTA0MThhNzNhNmUwNGE2NzA1\nNA==\n"

\ N są na ostatniej i szóstej pozycji od końca. Dekoder (Base64.decode64) doskonale zwraca stary ciąg. Dziwne jest to, że te \ n nie dodają żadnej wartości do zakodowanego ciągu. Kiedy usuwam znaki nowej linii z ciągu wyjściowego, dekoder dekoduje go ponownie doskonale.

irb(main):005:0> Base64.decode64(Base64.encode64(str).gsub("\n", '')) == str
=> true

Co więcej, użyłem innej biblioteki JS do wytworzenia wyjścia zakodowanego w base64 tego samego ciągu wejściowego, wyjście jest bez \ n.

Czy to błąd czy coś innego? Czy ktoś wcześniej spotkał się z tym problemem?

FYI,

$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
intellidiot
źródło
ten sam dziwny problem
Nadav B

Odpowiedzi:

223

Edycja: Odkąd napisałem, ta odpowiedź Base64.strict_encode64()została dodana, co nie dodaje nowych linii.


Dokumentacja jest nieco zagmatwana, b64encodemetoda ma dodawać nową linię dla każdego 60-tego znaku, a przykład encode64metody faktycznie używa tej b64encodemetody.

Wygląda na to, że pack("m")metoda klasy Array używana przez encode64również dodaje nowe linie. Uznałbym za błąd projektowy, że nie jest to opcjonalne.

Możesz albo samodzielnie usunąć znaki nowej linii, albo jeśli używasz railsów , możesz skorzystać z encode64smetody ActiveSupport :: CoreExtensions :: Base64 :: Encoding .

Christoffer Hammarström
źródło
44
Wydaje się, że odkąd napisałem tę odpowiedź, jest teraz, strict_encode64()która rzekomo nie dodaje nowych linii.
Christoffer Hammarström
15
Bardzo głupi! Dlaczego mi to robisz, Ruby?
Josh M.
1
Jest to domyślne ustawienie assinie, ale jak wspomina @ ChristofferHammarström, jest sposób na uzyskanie prawdziwego kodowania b64.
Dan
1
Najwyraźniej istnieje po to, aby zachować wsteczną kompatybilność z oprogramowaniem, które nie obsługuje długich linii. stackoverflow.com/a/20065991/5749914
Warlike Chimpanzee
115

W ruby-1.9.2 masz Base64.strict_encode64, który nie dodaje tego \ n (nowej linii) na końcu.

ghtn
źródło
To znacznie łatwiejsze rozwiązanie!
Avishai,
Sprawdziłem, że Base64.strict_encode64 nie jest poprawnie zakodowany trzyznakowy ciąg. jak Base64.strict_encode64 ('abc') -> YWJj. powyższy przykład nie jest poprawnie zakodowany.
CodeMaker
9

Tak, to całkiem normalne. Dokument podaje przykład wykazujące skład podziału. base64 robi to samo również w innych językach (np. Python).

Powodem dodawania nowych linii bez treści na etapie kodowania jest to, że base64 został pierwotnie opracowany jako mechanizm kodowania do wysyłania binarnej zawartości w wiadomości e-mail, gdzie długość linii jest ograniczona. Możesz je wymienić, jeśli ich nie potrzebujesz.

bobince
źródło
1
To właśnie wydarzyło się w mojej aplikacji na Androida (biblioteka Java Base64). Byłem całkowicie zdezorientowany tym dziwnym zjawiskiem. Zajęło mi dosłownie godzinę, aby dowiedzieć się, co jest nie tak, a następnie szukałem błędu. Ten komentarz pomaga zrozumieć starsze problemy nawet po 6 latach.
włamywacz
5

Wygląda na to, że należy je usunąć / zignorować, na przykład:

Base64.encode64(str).gsub(/\n/, '')
meesern
źródło
To rozwiązanie jest brudne… czy gdzie indziej?
Arnold Roa,
1
@yaauie ( poprzez sugerowaną edycję ): zasadniczo nie należy wprowadzać edycji, które powodują istotne zmiany. Polecam opublikowanie tego jako osobnej odpowiedzi.
Pokechu 22
3

Użyj strict_encode64metody. encode64dodaje \ n co 60 symboli

Александр Тихонович
źródło
czy możemy to zmienić, aby dodać po 76 symbolach?
dźwiękowy