Программная реализация утилиты кодирования и декодирования формата BASE 64

Разработка утилиты кодирования и декодирования формата Base 64 в программной среде Linux с использованием компилятора. Написание программы на языке С++. Кодирование символьной строки любого набора байт в последовательность печатных ASCII символов.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 10.09.2013
Размер файла 1,4 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

ФЕДЕРАЛЬНОЕ Государственное АВТОНОМНОЕ образовательное учреждение высшего профессионального образования

БЕЛГОРОДСКИЙ ГОСУДАРСТВЕННЫЙ НАЦИОНАЛЬНЫЙ ИССЛЕДОВАТЕЛЬСКИЙ УНИВЕРСИТЕТ

(НИУ "БелГУ")

ФАКУЛЬТЕТ КОМПЬЮТЕРНЫХ НАУК И ТЕЛЕКОММУНИКАЦИЙ

КАФЕДРА МАТЕМАТИЧЕСКОГО И ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ

ИНФОРМАЦИОННЫХ СИСТЕМ

Курсовая работа

Программная реализация ультилиты кодирования и декодирования формата BASE 64

студента дневного отделения 2 курса группы 141103

Дихтяренко Александра Анатольевича

Научный руководитель:

доцент В.В. Румбешт

БЕЛГОРОД 2013

Содержание

  • Введение
  • 1. Теоретическая часть
  • 1.1 Что такое кодирования/декодирование формата BASE64, его применение
  • 1.2 Структура BASE64
  • 2. Практическая часть
  • 2.1 Алгоритм кодирования/декодирования
  • 2.2 Реализация программы
  • 2.3 Апробация приложения
  • Заключение
  • Список используемой литературы
  • Приложения

Введение

Необходимо разработать утилиту кодирования/декодирования формата BASE64. Разработка ведется в программной среде Linux, используя компилятор gcc. Программа будет писаться на языке С++.

Для того что бы выполнить поставленную задачу необходимо составить план для изучения данной темы и ее реализации, а конкретно:

· Сбор и изучение материалов по теме кодирования/декодирования формата BASE64;

· Разобраться с алгоритмом кодирования/декодирования;

· Реализовать алгоритм, используя полученные знания;

· Сделать вывод из проведенной работы

1. Теоретическая часть

1.1 Что такое кодирования/декодирование формата BASE64, его применение

Дело в том, что изначально для передачи электронной почты в Интернет использовался только текст (RFC822). Затем, с развитием компьютерных технологий, потребовалась возможность передачи нетекстовой информации: аудио, видео, графических файлов, файлов приложений и т.д. Однако почтовые сервера понимают только текст. Именно поэтому появилась необходимость каким-то образом преобразовать двоичный файл в текстовый для этого и был придуман BASE64. Этот способ используется в спецификации MIME.

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

Из этого можно сделать вывод, что Base64 - это схема кодирования символьной строки любого набора байт в последовательность только печатных ASCII символов.

утилита кодирование декодирование программный

Рисунок.1.1 ASCII символы

1.2 Структура BASE64

Так как в BASE64 используется алфавит из 64 символов, то для кодировки нам хватит вместо стандартных 8 байт шесть. При этом изменении, мы можем кодировать любые цифры с помощью нашего алфавита.

Преобразование происходит по принципу:

Берутся три последовательных байта по восемь бит (всего 24 бита), и побитно делятся на четыре 6-ти битных байта (всего 24 бита). Замечу, что используется только 6 битов, а 2 остаются "не использованными"

Схематично такое преобразование можно представить:

Рисунок. 1.2 Преобразование в 6 битный вариант

Так кодируется любая информация, но существует еще один важный момент, дело в том, что не обязательно всегда будет 3 байта, именно по этому отсутствующие байты заменяют символом "=”

2. Практическая часть

2.1 Алгоритм кодирования/декодирования

Кодирование Для начала взять 8-ой (старший) бит исходного байта и поместить его в начало 6-ти битового байта. Затем на место 8-го бита исходного байта поместить 7-й бит, а в 6-ти битовом байте первый бит (младший) переместить на место 2-го бита. После такого перемещения освобождается первый (младший) бит 6-ти битного числа. В него и поместим старший (бывший седьмой) бит исходного байта. Затем еще раз пердвинем биты в обоих байтах, после чего повторяем процедуру

Пример:

Рисунок 2.1 Пример

Рассмотрим шаг 1.

Для проверки установки старшего бита исходного 8-ми битного байта наложим на него так называемую "маску". Т.е. применим к нему побитовую операцию AND с числом 128 (10000000).

Рисунок 2.2 Наложение "маски-1"

Как видно из приведенной схемы, проверить установку старшего бита совсем несложно. Если результатом операции получается число 128, значит бит установлен, а если в результате получаем 0, значит старший бит не установлен. Далее в зависимости от полученного результата применим к 6-ти битовому байту битовую операцию OR с числом 1, которая в любом случае применения устанавливает первый (младший) байт в 1.

Рисунок 2.3 Наложение "маски-2"

Здесь необходимо учитывать то, что перед применением побитовой операции OR с числом 1 младший бит 6-ти битового байта всегда 0. В случае для первых двух шагов потому, что мы сами обнуляем его при инициализации, для последующих шагов, потому что применяем операцию SHR.

Шаг 2.

Сместим первый бит 6-ти битного байта на вторую позицию, одновременно обнуляя его первый бит. Сместим седьмой байт 8-ми битного байта на 8-е (старшее) место.

Повторяем шаги 1 и 2 шесть раз для каждого бита 6-ти битного байта. Одновременно необходимо следить за тем, что если мы обработали восемь бит байта-источника, следует перейти к новому байту. И последнее - если обработаны все три байта-источники, следует выйти из функции кодирования.

Декодирование

Декодирование ничем не отличается от кодирования. Делаем тоже самое, только источник и приемник меняются местами. Все операции происходят в обратном порядке: проверяем установку первого бита 6-ти битного байта (маску в этом случае надо накладывать с числом 32 (0010000) и в зависимости от результата устанавливаем (или не устанавливаем) младший байт 8-ми битного байта. Затем делаем побитовый сдвиг влево.

После того как мы разобрали весь алгоритм, стоит подготовиться к реализации программы, для этого изобразим блок схемы:

1) Всего алгоритма целиком см. Рисунок.2.4 Блок-схема №1 (Вся программа в целом)

2) Алгоритм кодирования см. Рисунок.2.5 Блок-схема №2 (Кодирование)

3) Алгоритм декодирования см. Рисунок.2.6 Блок-схема №3 (Декодирование)

Рисунок 2.4 Блок-схема №1 (Вся программа в целом)

Рисунок 2.5 Блок-схема №2 (Кодирование)

Рисунок 2.6 Блок-схема №3 (Декодирование)

2.2 Реализация программы

Программа реализована таким образом, что состоит из 3 файлов: kyrsov. cpp;

base64. h;

test. cpp.

Начнем по порядку:

kyrsov. cpp (Созданы функции кодирования/декодирования текста)

Любая программа, написанная на языке программирования С++ прежде всего начинается с подключения заголовочных файлов, или, другими словами, с директив препроцессора (include) Директива препроцессора - это, иными словами, сообщение препроцессору. Нам потребуется всего четыре библиотеки для работы нашей программы

Здесь мы используем директиву include, которая через заголовочные файлы подключает к коду программы необходимые библиотеки. Некоторые заголовочные файлы требуют расширения". h”, так как являются более старыми и унаследовали такой стиль подключения от языка-основателя С.

В представленном в приложении к курсовой работе программном коде, имеют место быть следующие строки:

Листинг 1.

#include "base64. h" // Написанный в ручную заголовочный файл (описан класс string)

#include <iostream> // Стандартная директива потокового ввода/вывода

Операции ввода/вывода выполняются с помощью классов istream (потоковый ввод) и ostream (потоковый вывод). Третий класс, iostream, является производным от них и поддерживает двунаправленный ввод/вывод. Для удобства в библиотеке определены три стандартных объекта-потока:

· cin - объект класса istream, соответствующий стандартному вводу. В общем случае он позволяет читать данные с терминала пользователя;

· cout - объект класса ostream, соответствующий стандартному выводу. В общем случае он позволяет выводить данные на терминал пользователя;

· cerr - объект класса ostream, соответствующий стандартному выводу для ошибок. В этот поток мы направляем сообщения об ошибках программы.

Вывод осуществляется, как правило, с помощью перегруженного оператора сдвига влево (<<), а ввод - с помощью оператора сдвига вправо (>>):

Любая программа также должна содержать функции - основную (обязательно) и дополнительные (опционально). В языке С++ содержится два типа функций:

· Функции возвращающие значение;

· Функции, не возвращающие значений.

Для начала рассмотрим пример функции, которая не возвращает значений.

void /*имя функции*/ (/*параметры функции*/) // заголовок функции

Здесь код начинается с зарезервированного слова void - тип данных, который не хранит какие-либо данные. Этот тип данных показывает, что функция не возвращает никаких значений. void никак по-другому не используется и нужен в программе только для того, чтобы компилятор мог определить тип функции. После зарезервированного слова void пишется имя функции за которым ставятся две круглые скобочки, открывающаяся и закрывающаяся. Если функция будет передавать какие-то данные, то внутри круглых скобочек объявляются параметры функции, которые отделяются друг от друга запятыми. Вся эта строка называется заголовком функции, после которого в функции пишутся две фигурные скобочки - внутри которых будет находится алгоритм, называемый телом функции.

Это был пример дополнительной функции, которая значений не возвращает, так как тип ее данных - void.

Далее мы создаем две функции, для кодирования текста и для декодирования текста: base64_encode и base64_decode соответственно.

Разберем их по отдельности.

Листинг 2.

{

string ret;

int i = 0;

int j = 0;

unsigned char char_array_3 [3];

unsigned char char_array_4 [4];

……………}

Здесь мы описываем переменные.

Класс String

Строки - это объекты, которые представляют

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

В строка класс-это экземпляр basic_string шаблон класса, который использует char как тип персонажа, его значение по умолчанию char_traits и распределитель типов.

После этого действия, мы циклично модифицируем из 8 битного вида в 6 битный вид нашу строку. Начиная с конца

Листнг 3.

while (in_len--) {

char_array_3 [i++] = * (bytes_to_encode++);

if (i == 3) {

char_array_4 [0] = (char_array_3 [0] & 0xfc) >> 2;

char_array_4 [1] = ( (char_array_3 [0] & 0x03) << 4) + ( (char_array_3 [1] & 0xf0) >> 4);

char_array_4 [2] = ( (char_array_3 [1] & 0x0f) << 2) + ( (char_array_3 [2] & 0xc0) >> 6);

char_array_4 [3] = char_array_3 [2] & 0x3f;

………………………………}

<< - знак побитового смещения

& - знак побитового "и”

Как рассказано и показано в теории здесь специально используется побитовое умножение для проверки установки старших битов с последующим смещение.

Далее повторяется эта же операция, но при условии наличия еще необработанных байтов.

И в конце если не хватает байтов, тоесть их меньше 3, то мы просто заменяем в комбинации отсутствующие байты на знак "=" b дописываем в строку результат.

Листинг 4

while ( (i++ < 3))

ret += '=';

}

Вторая функия base64_decode, ведет и состоит аналогично только что описанной, но с измененным порядком действий (в обратном) и поменянными входом и выходом программы местами.

Теперь рассмотрим заголовочный файл base64. h

В нем описан класс стринг

Листинг 6

#include <string> // заголовочный файл подключающий возможности класса string

using namespace std; // подключаемое пространство имен std

string base64_encode (unsigned char const*, unsigned int len); // инициализация функции base64_encode

string base64_decode (string const& s); // инициализация функции base64_encode

Теперь рассмотрим файл test. cpp (Файл в котором задается). Так же как и в первом файле используются подключаемые модули:

Стандартная библиотека ввода/вывода <iostream> и заголовочный файл "base64. h"

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

При создании нового консольного приложения в языке программирования С++, автоматически создается таккая строка: int main (int argc, char* argv [])

Это - заголовок главной функции main (), в скобочках которого объявлены параметры argс и argv. Так вот, если программу запускать через командную строку, то существует возможность передать какую-либо информацию этой программе через параметры argc и argv []. Первый имеет тип данных int, и содержит количество параметров, передаваемых в функцию main. Причем argc никогда не меньше 1, даже когда мы не передаем никакой информации, потому как первым параметром считается имя функции. Второй параметр - это массив указателей на строки. Через командную строку можно передать только данные строкового типа и именно через параметр argv [] и передается какая-либо информация.

Рисунок 3.1 Схема обьявлений функциив с++

Листинг 7

int main () {

const string s = "kot begit po doroge i myrchit"; // присваиваем переменной s текст который хотели бы закодировать.

string encoded = base64_encode (reinterpret_cast<const unsigned char*> (s. c_str ()), s. length ());

string decoded = base64_decode (encoded);

cout << "encoded: " << encoded << endl;

cout << "decoded: " << decoded << endl;

return 0;

}

В этом коде мы присваиваем переменным string, то значение которое получил функции из файла kyrsov. cpp, при этов в функции мы передаем аргументы

После этого воспользовавшись командой вывода cout. Показываем результат на экран

И после возврщаем 0, командой return 0

Так же здесь присутствуют функции для работы с строковыми данными

s. c_str ()

Возвращает указатель на массив, который содержит null-terminated последовательность символов (т.е., C-string), представляющий текущее значение строка объекта. Этот массив включает в себя одну и ту же последовательность символов, составляющих стоимость строка объект плюс дополнительный завершающий null-символ ('\0') в конце.

s. length ()

Свойство Length возвращает число объектов Char в данном экземпляре, а не число знаков Юникода. Причина в том, что знак Юникода может быть представлен несколькими Char. Для работы с каждым знаком Юникода используйте класс System. Globalization:: StringInfo вместо класса Char.

В некоторых языках, таких как C и C++, знак null указывает на конец строки. На платформе.net Framework знак null может быть внедрен в строку. Когда строка включает один или более знаков null, они могут находиться в любом месте строки. Например, в следующей строке подстроки"abc" и "def" разделены знаком null. Свойство Length возвращает значение 7, показывающее, что строка содержит шесть знаков алфавита и знак null.

2.3 Апробация приложения

В данном разделе находятся тестовые данные и отчет о работе приложения.

Скриншот №1 (Пример работы1)

Скриншот №2 (Пример работы2)

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

1 команда. g++ - c kyrsov. cpp test. cpp

Команда благодаря ключу - с создает 2 отдельных объектных файла, заголовочный файл base64. h,разместим в том же каталоге, что и другие файлы, его мы подключили внутри программы.

2 команда. g++ kyrsov. o test. o - o result

Команда собирает вместе 2 объектных файла и создает файл запуск для нашей программы.

3 команда. /result

Эта команда запускает нашу программу, после чего мы видим результат на наших скриншотах

На апробации выяснилось, что программа рабочая, выводы верны, декодирование и кодирование прошли успешно

Заключение

В ходе данной курсовой работы были изучены различные аспекты языка программирования С++. Так же был разобран алгоритм кодирования декодирования формата BASE64 и после чего реализован.

Апробация прошла успешно, скриншоты это подтверждают.

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

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

Список используемой литературы

1. Холзнер С. Visual C++6: Учебный курс - СПб: Питер, 2001. - 576 с.

2. Андрей Александреску, Современное проектирование на С++ - СПб.: Вильямс, 2002. - 335с.

3. Брюс Эккель, Философия С++ - К.: Питер, 2004, - 575с.

4. Е.Л. Романов, Практикум по программированию на С++. СПб: БВХ-Петербург, 2004. - 425 с.

5. Страуструп Б. Программирование: принципы и практика использования C++, исправленное издание = Programming: Principles and Practice Using C++. - М.: "Вильямс", 2011. - С.1248. - ISBN 978-5-8459-1705-8

6. http://www.cppstudio.com/obuchenie_cpp

7. Р. Лафоре, Объектно-ориентированное программирование в С++. К.: Питер, 2004, - 920с.

8. http://brucha.ru/category/spp/

Приложения

Приложение 1. Программная реализация ультилиты кодирования декодирования формата Base64

1) kyrsov. cpp

#include "base64. h"

#include <iostream>

using namespace std;

// Использование 64 ьитного алфавита base64

static const string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

// Проверка вводимых значений

static inline bool is_base64 (unsigned char c) {

return (isalnum (c) || (c == '+') || (c == '/'));

}

// Кодирум наш текст

string base64_encode (unsigned char const* bytes_to_encode, unsigned int in_len) {

string ret;

int i = 0;

int j = 0;

unsigned char char_array_3 [3];

unsigned char char_array_4 [4];

// Запускаем цикл в котором выбираем по 3 байта и модифицируем их, как бы из 8 битного байта в 6 битный байт

while (in_len--) {

char_array_3 [i++] = * (bytes_to_encode++);

if (i == 3) {

char_array_4 [0] = (char_array_3 [0] & 0xfc) >> 2;

char_array_4 [1] = ( (char_array_3 [0] & 0x03) << 4) + ( (char_array_3 [1] & 0xf0) >> 4);

char_array_4 [2] = ( (char_array_3 [1] & 0x0f) << 2) + ( (char_array_3 [2] & 0xc0) >> 6);

char_array_4 [3] = char_array_3 [2] & 0x3f;

// То что получилось запишем в переменную ret

for (i = 0; (i <4); i++)

ret += base64_chars [char_array_4 [i]];

i = 0;

}

}

// Продолжаем, если отправили не пустое сообщение

if (i)

{

for (j = i; j < 3; j++)

// лобавляем в конце ноль, что бы сделать сишную строку

char_array_3 [j] = '\0';

char_array_4 [0] = (char_array_3 [0] & 0xfc) >> 2;

char_array_4 [1] = ( (char_array_3 [0] & 0x03) << 4) + ( (char_array_3 [1] & 0xf0) >> 4);

char_array_4 [2] = ( (char_array_3 [1] & 0x0f) << 2) + ( (char_array_3 [2] & 0xc0) >> 6);

char_array_4 [3] = char_array_3 [2] & 0x3f;

for (j = 0; (j < i + 1); j++)

ret += base64_chars [char_array_4 [j]];

// Если байтов меньше 3, то вместо них записывается знак "=", сколько отсутствует столько и "="

while ( (i++ < 3))

ret += '=';

}

return ret;

}

string base64_decode (string const& encoded_string) {

int in_len = encoded_string. size ();

int i = 0;

int j = 0;

int in_ = 0;

unsigned char char_array_4 [4], char_array_3 [3];

string ret;

// берем наш закодированную строку, идем обратном порядке и смотрим наличи пустых байтов

while (in_len - && (encoded_string [in_]! = '=') && is_base64 (encoded_string [in_])) {

char_array_4 [i++] = encoded_string [in_]; in_++;

// аналогичные действия в обратном порядке

if (i ==4) {

for (i = 0; i <4; i++)

char_array_4 [i] = base64_chars. find (char_array_4 [i]);

char_array_3 [0] = (char_array_4 [0] << 2) + ( (char_array_4 [1] & 0x30) >> 4);

char_array_3 [1] = ( (char_array_4 [1] & 0xf) << 4) + ( (char_array_4 [2] & 0x3c) >> 2);

char_array_3 [2] = ( (char_array_4 [2] & 0x3) << 6) + char_array_4 [3];

for (i = 0; (i < 3); i++)

ret += char_array_3 [i];

i = 0;

}

}

if (i) {

for (j = i; j <4; j++)

char_array_4 [j] = 0;

for (j = 0; j <4; j++)

char_array_4 [j] = base64_chars. find (char_array_4 [j]);

char_array_3 [0] = (char_array_4 [0] << 2) + ( (char_array_4 [1] & 0x30) >> 4);

char_array_3 [1] = ( (char_array_4 [1] & 0xf) << 4) + ( (char_array_4 [2] & 0x3c) >> 2);

char_array_3 [2] = ( (char_array_4 [2] & 0x3) << 6) + char_array_4 [3];

for (j = 0; (j < i - 1); j++) ret += char_array_3 [j];

}

return ret;

}

2) base64. h

#include <string>

using namespace std;

string base64_encode (unsigned char const*, unsigned int len);

string base64_decode (string const& s);

3) test. cpp

#include "base64. h"

#include <iostream>

using namespace std;

int main () {

const string s = "kot begit po doroge i myrchit";

string encoded = base64_encode (reinterpret_cast<const unsigned char*> (s. c_str ()), s. length ());

string decoded = base64_decode (encoded);

cout << "encoded: " << encoded << endl;

cout << "decoded: " << decoded << endl;

return 0;

}

Программная реализация утилиты кодирования декодирования формата Base64

Размещено на Allbest.ru


Подобные документы

  • Анализ способов кодирования информации. Разработка устройства кодирования (кодера) информации методом Хемминга. Реализация кодера–декодера на базе ИМС К555ВЖ1. Разработка стенда контроля передаваемой информации, принципиальная схема устройства.

    дипломная работа [602,9 K], добавлен 30.08.2010

  • Разработка программы кодирования текстового файла при помощи блочного алгоритма шифрования ТЕА типа "Сеть Фейштеля", который основан на битовых операциях с 64-битным блоком и имеет 128-битный ключ шифрования. Результаты кодирования и декодирования.

    лабораторная работа [299,9 K], добавлен 18.07.2013

  • Анализ методов сверточного кодирования. Понятие канала связи и корректирующих кодов, характеристика автомата типа Мура. Особенности сверточного декодирования Витерби. Сущность разработки программного обеспечения системы кодирования сверточным кодом.

    дипломная работа [4,9 M], добавлен 11.03.2012

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

    презентация [16,3 K], добавлен 07.06.2011

  • Определение понятий кода, кодирования и декодирования, виды, правила и задачи кодирования. Применение теорем Шеннона в теории связи. Классификация, параметры и построение помехоустойчивых кодов. Методы передачи кодов. Пример построения кода Шеннона.

    курсовая работа [212,6 K], добавлен 25.02.2009

  • Методика разработки и механизм отладки программы на языке Лисп, реализующей криптографический алгоритм кодирования информации с открытым ключом – RSA. Математические и алгоритмические основы решения задачи, его программная модель, составление блок-схемы.

    курсовая работа [675,7 K], добавлен 20.01.2010

  • Представление информации в двоичной системе. Необходимость кодирования в программировании. Кодирование графической информации, чисел, текста, звука. Разница между кодированием и шифрованием. Двоичное кодирование символьной (текстовой) информации.

    реферат [31,7 K], добавлен 27.03.2010

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.