Алгоритмы

индекс
298,92

SGVsbG8gd29ybGQh или история base64

Краткая предыстория


Вообще, все началось давно. Настолько давно, что вряд ли остались свидетели holy wars тех дней, когда решалось — сколько же бит должно быть в байте.

Это сейчас нам кажется само собой разумеющимся, что 1 байт = 8 бит, что в байте можно закодировать 256 различных значений. Но когда-то было совсем не так. История помнит и семибитные кодировки, и шестибитные, и даже более экзотические системы (например — ЭВМ «Сетунь», которая использовала троичную логику, то есть один троичный бит — трит мог иметь три, а не два значения, для нее было справедливо соотношение 1 трайт = 6 тритам). Но если оставить в стороне всякую экзотику, то мэйнстримом все-таки были кодировки, в которых 6, 7 или 8 бит в байте.

Шестибитная кодировка (например — BCD) позволяла закодировать в одном байте 64 различных значения, что, как казалось, было вполне достаточно для кодирования алфавитно-цифровых символов, а «лишний» седьмой бит расширял кодировку уже до 128 символов.

Однако скоро восьмибитный байт стал общепринятым.

Проблема восьмого бита


Утверждение восьмибитных кодировок как стандарта де-факто принесло много проблем. К этому моменту уже существовала определенная инфраструктура, использующая именно семибитные кодировки, и holy wars разгорелись с новой силой.

До нас они дошли в виде проблем с «обрезанием восьмого бита» в системе электронной почты. Утверждение восьмибитного байта дало 256 различных значений для одного байта, что, в свою очередь позволило уместить в одной кодовой таблице и общепринятые символы (цифры, знаки препинания, латиницу) и символы, скажем кириллицы. Казалось бы — сплошное удобство, текст можно набирать хоть русскими буквами, хоть английскими, а если нужно — и для немецких умлаутов место найдется!

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

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

Для временного решения этой проблемы было предложено несколько вариантов. Одним из них стала кодировка «КОИ-8». Решение, нужно признать, весьма элегантное — в этой кодировке русские буквы располагались по порядку латинских и отличались от них ровно на тот самый старший бит. Таким образом при обрезании этого бита русская «А» превращалась в латинскую «A», «Б» — в «B» и так далее, сообщение просто транслитерировалось и его все-таки можно было прочитать. Правда, и тут не обошлось без скелета в шкафу — сортировка в русском алфавитном порядке в «КОИ» становилась кошмаром…

А что было делать другим языкам, народам и кодировкам? А бинарные данные? Все равно кодировки с транслитерацией не решали фундаментальную проблему — потерю восьмого бита, потерю части информации. Так родилась кодировка (а точнее — алгоритм) Base64.

Алгоритм Base64


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

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

Пример:
Возьмем текст русский текст «АБВГД». В двоичной форме в кодировке Windows-1251 мы получим 5 байтов:
11000000
11000001
11000010

11000011
11000100
(00000000) — лишний нулевой байт нужен, чтобы общее число бит делилось на 6

Разделим эти биты на группы по 6:
110000
001100
000111
000010

110000
111100
010000
000000

Берем массив символов «ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/» и получившиеся числа переводим в эти символы, используя их, как индексы массива, получаем «wMHCw8Q». Остается только добавить в конце один символ "=", как указание на один лишний нулевой байт, который мы добавляли на первом шаге и получить окончательный результат:

«АБВГД»: base64 = «wMHCw8Q=»

Обратное преобразование не менее легко, попробуйте, например, расшифровать то, что вынесено в заголовок этой статьи.

Применение


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

Можно представить себе и другие применения base64 — например при сохранении в базу данных, если заранее неизвестно окружение (ох уж эти magic_qoutes в PHP!) и нет необходимости в индексации и поиске по тексту, можно воспользоваться base64.

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

Ну и наконец Data URI

Ссылки


ru.wikipedia.org/wiki/Base64
base64.ru/
+57
19 марта 2010, 17:26
31

комментарии (36)

НЛО прилетело и опубликовало эту надпись здесь
+6
AlexLeonov #
Ну вот, раскрыли интригу -))
Плюс к комменту за интуицию.
+1
Frike #
Познавательно
+2
YuZZ #
Спасибо, интересно.
Кстати, base64 еще используют для «вшивания» картинок напрямую в html
0
AlexLeonov #
Точно.
Знал, держал в голове, но в последний момент забыл. Сейчас добавлю.
НЛО прилетело и опубликовало эту надпись здесь
0
Kaluchi #
data:image/png;base64, и бесконечное бла-бла-бла…

Самое необычное его применение увидел недавно в Webpage Screenshot-плагине к хрому.

0
YuZZ #
да, строка такого кода может поразить) Я увидел первый раз на работе, когда разбирался в коде и в верстке — в начале долго не мог понять что ЭТО и для чего)
0
Aux #
Я впервые юзал data URI в плагине (точнее панеле) для Opera — оч клёвое решение получилось.
0
glib #
а ещё и в кодировании аттачей к письмам, перед тем как передавать по протоколу SMTP. почему, если по POP3 забирать потом письма, размер письма раза в полтора больше реального размера прикрепления.
0
bolk #
Картинок? Почему картинок? Всего, чего угодно: html, css, js, любые данные (хоть флеш).
+1
alienator #
Можно добавить ещё про URL-safe Base64, где вместо «+» и «/» используются «-» и «_» — чтобы беспроблемно передавать бинарные данные в query string.

И можно добавить про Base32 и Base16.

Наконец, можно дать ссылку на RFC 3548 :)
0
AlexLeonov #
Ссылку на статью в Википедии я дал, там все это есть.
+2
Veter9 #
Я и в самом деле всегда был уверен, что СРАЗУ придумали, что 1 байт = 8 бит. =)
0
Shark #
Ну впринципе логично было бы 4 или 8 бит (как степени двойки, всё таки), но 6, или даже 7 (ужас, наверное с адресацией был)…
–3
Veter9 #
Лет через 50 люди будут думать «чо за глупое 8бит?!, сейчас все итак у каждого в часах пару йотабайт храниться» и «Зачем такие мелкие величины вообще использовать??!»
А уж про ipv4 и ipv6 вообще молчу )))) Это та, к слову вспомнил…
И так же думать, что так, как есть (например в 2060году) что так и было с самого начала)
0
Shark #
Удивительно, что байт это буквально вторая ступень, ибо меньше бита ничего даже в теории нет. И уже на второй ступени устраивали холивары, были проблемы и пр. и пр. :)
0
Veter9 #
хыхы. Оффтоп, но вспомнил так же:
как то читал, что ограничение в 140символов в смс не техническое ограничение, а автор подумал, что «да вроде хватит этого» :D и сделали так. Сволочи )))
0
Dreadatour #
На самом деле там вполне себе техническое ограничение ;)
0
guessss_who #
160.
0
Olif #
это если используется utf-7. а в utf-8 «влезет» 140 символов.
русский же текст кодируют в UCS-2 — ограничение получается в 70 символов.
0
masai #
Почему же нет? В теории информации легко можно встретить и половинку бита.

А холивары были потому, что единственная единица измерения информации — это бит. Байт — лишь производная от него, тут нет однозначности. (Да и с самим битом тоже не всё гладко, раз говорят о тритах, натах и дитах).
0
anonimouse #
Ну вы же не разучились считать рубли по одной монете только лишь потому, что хлеб нынче стоит более десяти рублей. :)
НЛО прилетело и опубликовало эту надпись здесь
0
usr #
user [~] > echo password | base64
cGFzc3dvcmQK
user [~] > echo cGFzc3dvcmQK | base64 -d
password
user [~] >
НЛО прилетело и опубликовало эту надпись здесь
0
OlegTar #
В PHP — функции base64_decode, base64_encode,
В Perl — пакет MIME::Base64, который предоставляет команды с такими же названиями: base64_decode, base64_encode,
В Javascript — соответствующий класс, www.webtoolkit.info/javascript-base64.html

Онлайн Декодеры/Кодеры:
www.opinionatedgeek.com/dotnet/tools/Base64Decode/
www.opinionatedgeek.com/dotnet/tools/Base64Encode/Default.aspx
www.artlebedev.ru/tools/decoder/advanced/
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
–1
Zyava #
Э нет, тогда даже Нео не сможет прочитать :)
+3
Shark #
 ___________
< habrahabr >
 -----------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

0
Shark #
Подумал что вы сначала закодировали, а потом сжали. Очевидно же, что не так :) Наверное, устал)
0
guessss_who #
Честно говоря, не совсем понятно, зачем было холиворить насчет количества бит в байте. 8 — степень базы двоичной системы исчисления. В отличие от 6 и 7. 4 бит было бы откровенно мало (хотя для кодирования половины байта — в самый раз, наш любимый шестнадцатеричный код).

В общем, всё кажется вполне очевидным. imho.
0
AlexLeonov #
Все очевидно, если вспомнить, что память первых «настоящих» компьютеров исчислялась даже не тысячами бит, а едва сотнями.
Тут каждый бит на счету был вообще-то.
0
OlegTar #
кому надо раскодировать/закодировать base64 онлайн, прошу сюда: www.artlebedev.ru/tools/decoder/advanced/
— Да, base64 удобен. Была у меня задачка передать в javascirpt в json`е большой текст.

Так вот, концы строк приходится помечать символами слеш, кавычки и слеши слешировать, при том, вечно какие-то ошибки были.
Пример, о чём речь:
{
text: 'bla-bla-bla\
test \''
}

Так вот я потом познакомился с Base64, и кодировал текст в неё.
А потом в javascript`е текст раскодировал (есть класс для раскодирования Base64 javascript`овый), и всё нормально.
=================================

Для тех, кто хочет увидеть base64 в действии, зайдите в Gmail отправьте себе письмо со смайликом, а потом получите это письмо, зайдите в него и в меню с кнопкой «Ответить», выберите «Показать оригинал»
В Thunderbird можно при просмотре письма нажать сочетание клавиш Ctrl+U

=================================
Насчёт кодирования паролей в Base64 при хэшировании в md5: клин клином вышибают.
Можно сделать такой брутфорсер, который будет подбираемые пароли в Base64 сначала кодировать, а потом уже получать md5.
+1
pvasili #
В свое время, для компактного кодирования значения GUID (для поиска документов в 1С сканером штрих-кода), я делал конвертирование 78ричную систему ;)
1c.proclub.ru/modules/mydownloads/personal.php?cid=120&lid=4484

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.