541

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

Курсовая

Информатика, кибернетика и программирование

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

Русский

2013-01-06

81.5 KB

43 чел.

Министерство образования и науки РФ

Государственное образовательное учреждение высшего профессионального образования

Ивановский государственный энергетический университет имени В.И.Ленина

Кафедра программного обеспечения компьютерных систем

ОТЧЕТ

по курсовой работе

по курсу «Структуры и алгоритмы обработки данных»

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

Выполнил:

студент группы 3-42хх Чуенков И.Е.

Проверил:

Второв А.В.

Иваново 2011

Оглавление

1. Задание 3

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

3. Код программы 5


1. Задание

Написать программу, осуществляющую Base64 кодирование/декодирование.


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

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

Длина результирующего потока символов будет равна

ИСХОДНАЯ_ДЛИНА * 4 / 3 + 6

А если применяется перенос по строкам, то

ИСХОДНАЯ_ДЛИНА * 4 / 3 + len * 4 / (3 * 72) + 7

В общем случае длина исходно сообщения увеличивается примерно на 30%.

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

Байт состоит из 8 бит. Если представить входную информацию как цепочку битов, то это будет цепочка длиной N * 8. Разделив эту цепочку на “минибайты” длиной по 6 бит мы получаем следующее:

  •  Минибайт становится больше чем настоящих байт
  •  Каждый минибайт (из 6 бит) можно представить (закодировать) как один из символов английского алфавита.

Действительно. Этих символов уже хватит, т.к. 26 это 64. Нам всего лишь надо отыскать эти 64 символа. В base64 используются символы a..z A..Z 0..9 + / и специальный символ =. Для преобразования нужно разбить поток байт на куски по 6 бит, и каждый кусок будет соответствовать одному из представленных выше символов. И в результате любой поток бит можно преобразовать в печатный вид.

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

Наименьший общий делитель числа 8 и 6 - 24 (3 байта) является и тем самым числом байт на который должна быть выровнена исходная строка, что бы ее можно было кодировать. Если же байт до 3х кратного количества не хватает, то в конце результирующей строки base64 дописывается знак =. Если не хватает 1 байта - один знак =, если двух - два символа ==.

3. Код программы

#include <stdio.h>

#include <stdlib.h>

/*

** Tablica transliacii

*/

static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/*

** Tablica transliacii dlia decodirovaniia

*/

static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";

/*

** block kodirovaniia

**

** preobrazovaniie 3x 8-bitnix baitov v 4 6-bitnix

*/

void encodeblock( unsigned char in[3], unsigned char out[4], int len )

{

   out[0] = cb64[ in[0] >> 2 ];

   out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];

   out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');

   out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');

}

/*

** kodirovanie

**

** base64 kodirovanie stroki s dobavleniem simvolov = i perexodov

*/

void encode( FILE *infile, FILE *outfile, int linesize )

{

   unsigned char in[3], out[4];

   int i, len, blocksout = 0;

   while( !feof( infile ) ) {

       len = 0;

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

           in[i] = (unsigned char) getc( infile );

           if( !feof( infile ) ) {

               len++;

           }

           else {

               in[i] = 0;

           }

       }

       if( len ) {

           encodeblock( in, out, len );

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

               putc( out[i], outfile );

           }

           blocksout++;

       }

       if( blocksout >= (linesize/4) || feof( infile ) ) {

           if( blocksout ) {

               fprintf( outfile, "\r\n" );

           }

           blocksout = 0;

       }

   }

}

/*

** block dekodirovaniia

**

** preobrazovaniie 4x 6-bitnix minibaitov v 3 8-bitnix baitov

*/

void decodeblock( unsigned char in[4], unsigned char out[3] )

{   

   out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);

   out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);

   out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);

}

/*

** dekodirovaniie

**

** dekodirovanie base64 stroki s ydaleniem simvolov = i perexodov

*/

void decode( FILE *infile, FILE *outfile )

{

   unsigned char in[4], out[3], v;

   int i, len;

   while( !feof( infile ) ) {

       for( len = 0, i = 0; i < 4 && !feof( infile ); i++ ) {

           v = 0;

           while( !feof( infile ) && v == 0 ) {

               v = (unsigned char) getc( infile );

               v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);

               if( v ) {

                   v = (unsigned char) ((v == '$') ? 0 : v - 61);

               }

           }

           if( !feof( infile ) ) {

               len++;

               if( v ) {

                   in[ i ] = (unsigned char) (v - 1);

               }

           }

           else {

               in[i] = 0;

           }

       }

       if( len );; {

           decodeblock( in, out );

           for( i = 0; i < len - 1; i++ ) {

               putc( out[i], outfile );

           }

       }

   }

}

/*

** vozvrashiaemie oshibki

**

** Oshibki vozvrashiaemie operacionnoi sisteme.

**

*/

#define B64_SYNTAX_ERROR        1

#define B64_FILE_ERROR          2

#define B64_FILE_IO_ERROR       3

#define B64_ERROR_OUT_CLOSE     4

#define B64_LINE_SIZE_TO_MIN    5

/*

** b64_message

**

** Gryppirovka tekstovix soobshenii.

**

*/

char *b64_message( int errcode )

{

   #define B64_MAX_MESSAGES 6

   char *msgs[ B64_MAX_MESSAGES ] = {

           "b64:000:Nepravilnii kod soobsheniia.",

           "b64:001:Sintakcicheskaia oshibka.",

           "b64:002:Oshibka otkritiia/sozdaniia faila.",

           "b64:003:Oshibka vvoda-vivoda faila.",

           "b64:004:Oshibka zakritiia vixodnogo faila.",

           "b64:004:Ystanovlen minimalnii razmer stroki."

   };

   char *msg = msgs[ 0 ];

   if( errcode > 0 && errcode < B64_MAX_MESSAGES ) {

       msg = msgs[ errcode ];

   }

   return( msg );

}

/*

** b64

**

** mexanizm otkritiia potokov i vizova kodirovaniia/decodirovaniia

*/

int b64( int opt, char *infilename, char *outfilename, int linesize )

{

   FILE *infile;

   int retcode = B64_FILE_ERROR;

   if( !infilename ) {

       infile = stdin;

   }

   else {

       infile = fopen( infilename, "rb" );

   }

   if( !infile ) {

       perror( infilename );

   }

   else {

       FILE *outfile;

       if( !outfilename ) {

           outfile = stdout;

       }

       else {

           outfile = fopen( outfilename, "wb" );

       }

       if( !outfile ) {

           perror( outfilename );

       }

       else {

           if( opt == 'e' ) {

               encode( infile, outfile, linesize );

           }

           else {

               decode( infile, outfile );

           }

           if (ferror( infile ) || ferror( outfile )) {

               retcode = B64_FILE_IO_ERROR;

           }

           else {

                retcode = 0;

           }

           if( outfile != stdout ) {

               if( fclose( outfile ) != 0 ) {

                   perror( b64_message( B64_ERROR_OUT_CLOSE ) );

                   retcode = B64_FILE_IO_ERROR;

               }

           }

       }

       if( infile != stdin ) {

           fclose( infile );

       }

   }

   return( retcode );

}

/*

** rykovodstvo

**

** otobrazheniie poleznoi informacii

*/

void showuse( int morehelp )

{

   {

       printf( "\n" );

       printf( "  b64      (Base64 Kodirovaniie/Dekodirovaniie)                     \n" );

       printf( "  Ispolzovaniie:   b64 -opciia  [ -l num ] [<FileIn> [<FileOut>]]  \n" );

       printf( "  Naznacheniie: Eta programma ocishestvliaiet             \n" );

       printf( "           Base64 Kodirovaniie-Dekodirovaniie.                \n" );

   }

   if( !morehelp ) {

       printf( "           Nazmite -h dlia dopolnitelnoi pomoshi.              \n" );

   }

   else {

       printf( "  Opcii: -e  kodirovaniie v  Base64   -h  Pomosh.       \n" );

       printf( "           -d  dekodirovaniie iz Base64 -?  Pomosh.       \n" );

       printf( "  Primechaniie:    -l  nazmite dlia izmeneniia dlini stroki (ot 72 simvolov)\n" );

       printf( "  Vozvrat: 0 = yspex.  Nenylevoi kod - oshibochnii.        \n" );

       printf( "  Obrazec: b64 -e binfile b64file     <- Kodirovaniie     \n" );

       printf( "           b64 -d b64file binfile     <- Dekodirovaniie   \n" );

       printf( "           b64 -e -l40 infile outfile <- dlina stroki 40  \n" );

   }

}

#define B64_DEF_LINE_SIZE   72

#define B64_MIN_LINE_SIZE    4

#define THIS_OPT(ac, av) (ac > 1 ? av[1][0] == '-' ? av[1][1] : 0 : 0)

/*

** glavnaia fynkciia

**

** analiziryet parametri i vizivaet b64 ili pomosh

*/

int main( int argc, char **argv )

{

   int opt = 0;

   int retcode = 0;

   int linesize = B64_DEF_LINE_SIZE;

   char *infilename = NULL, *outfilename = NULL;

   while( THIS_OPT( argc, argv ) ) {

       switch( THIS_OPT(argc, argv) ) {

           case 'l':

                   linesize = atoi( &(argv[1][2]) );

                   if( linesize < B64_MIN_LINE_SIZE ) {

                       linesize = B64_MIN_LINE_SIZE;

                       printf( "%s\n", b64_message( B64_LINE_SIZE_TO_MIN ) );

                   }

                   break;

           case '?':

           case 'h':

                   opt = 'h';

                   break;

           case 'e':

           case 'd':

                   opt = THIS_OPT(argc, argv);

                   break;

            default:

                   opt = 0;

                   break;

       }

       argv++;

       argc--;

   }

   switch( opt ) {

       case 'e':

       case 'd':

           infilename = argc > 1 ? argv[1] : NULL;

           outfilename = argc > 2 ? argv[2] : NULL;

           retcode = b64( opt, infilename, outfilename, linesize );

           break;

       case 0:

           retcode = B64_SYNTAX_ERROR;

       case 'h':

           showuse( opt );

           break;

   }

   if( retcode ) {

       printf( "%s\n", b64_message( retcode ) );

   }

   return( retcode );

}


 

А также другие работы, которые могут Вас заинтересовать

13436. СТВОРЕННЯ ЗВЕДЕННИХ ТАБЛИЦЬ В MICROSOFT EXCEL 354.5 KB
  МЕТОДИЧНІ ВКАЗІВКИ ДО ЛАБОРАТОРНОЇ РОБОТИ №6 СТВОРЕННЯ ЗВЕДЕННИХ ТАБЛИЦЬ В MICROSOFT EXCEL 1. Мета роботи Придбати практичні навички по створенню і використанню зведених таблиць в Microsoft Excel. 2. Задачі роботи Опанувати прийоми формування редагування зміни та
13437. Опрацювання результатів прямих багаторазових вимірювань 238 KB
  ЛАБОРАТОРНА РОБОТА 1 ОПРАЦЮВАННЯ РЕЗУЛЬТАТІВ ПРЯМИХ БАГАТОРАЗОВИХ ВИМІРЮВАНЬ Мета роботи: вивчити методику опрацювання результатів прямих багаторазових вимірювань; навчитись визначати характеристики похибки результату вимірювання в залежності від кількості в...
13438. Повірка чи калібрування приладів прямої дії 102.5 KB
  Лабораторна робота 2 Повірка чи калібрування приладів прямої дії Мета роботи: вивчити теоретичні та практичні основи повірки чи калібрування приладів прямої дії на прикладі калібрування амперметра та вольтметра зіставленням їх показів із показами робочих еталонів.
13439. ВИМІРЮВАННЯ ПОСТІЙНИХ СТРУМІВ ТА НАПРУГ 160 KB
  ЛАБОРАТОРНА РОБОТА 3 ВИМІРЮВАННЯ ПОСТІЙНИХ СТРУМІВ ТА НАПРУГ Мета роботи: Навчитись: вимірювати постійні струми та напруги електромеханічними приладами; раціонально обирати межу вимірювання та клас точності стрілкового приладу для вимірювання заданої з допустим
13440. ВИМІРЮВАННЯ СТРУМІВ, НАПРУГ ТА ПАРАМЕТРІВ ЕЛЕКТРИЧНИХ ЛАНЦЮГІВ КОМБІНОВАНИМИ ПРИЛАДАМИ (ТЕСТЕРАМИ) 2.84 MB
  ЛАБОРАТОРНА РОБОТА 4 ВИМІРЮВАННЯ СТРУМІВ НАПРУГ ТА ПАРАМЕТРІВ ЕЛЕКТРИЧНИХ ЛАНЦЮГІВ КОМБІНОВАНИМИ ПРИЛАДАМИ ТЕСТЕРАМИ Мета роботи: вивчити принцип дії будову та властивості комбінованих приладів КП здобути навички вимірювань і перевірки справності елементів ...
13441. Деякі особливості використання вольтметрів змінного струму 237.5 KB
  ЛАБОРАТОРНА РАБОТА № 5 Деякі особливості використання вольтметрів змінного струму Мета роботи : Опрацювати опис даної роботи та відповідні розділи рекомендованої літератури [1] [2] [3] [5]. 2. Уміти відповідати на наступні запитання: 1. Поясніть будову та принцип д
13442. ДОСЛІДЖЕННЯ ВИМІРЮВАЛЬНИХ МОСТІВ ПОСТІЙНОГО СТРУМУ 131.5 KB
  Лабораторна робота № 6 ДОСЛІДЖЕННЯ ВИМІРЮВАЛЬНИХ МОСТІВ ПОСТІЙНОГО СТРУМУ Мета роботи: вивчити основи теорії схеми та будову врівноважених мостів постійного струму дослідити властивості врівноважених мостів здобути навички вимірювань за допомогою мостів. При пі...
13443. НЕВРІВНОВАЖЕНИЙ ВИМІРЮВАЛЬНИЙ МІСТ ПОСТІЙНОГО СТРУМУ 118.5 KB
  ЛАБОРАТОРНА РОБОТА 7 НЕВРІВНОВАЖЕНИЙ ВИМІРЮВАЛЬНИЙ МІСТ ПОСТІЙНОГО СТРУМУ Мета роботи: вивчити принцип дії елементи теорії схеми властивості та особливості застосування неврівноважених вимірювальних мостів НМ постійного струму. При підготовці до виконання р...
13444. ДОСЛІДЖЕННЯ ВИМІРЮВАЛЬНИХ МОСТІВ ЗМІННОГО СТРУМУ 193.5 KB
  ЛАБОРАТОРНА РОБОТА N 8 ДОСЛІДЖЕННЯ ВИМІРЮВАЛЬНИХ МОСТІВ ЗМІННОГО СТРУМУ Мета роботи: вивчити основи теорії принцип дії схеми властивості і особливості експлуатації мостів змінного струму МЗС. Провести дослідження властивостей мостів змінного струму. При п...