Будь умным!


У вас вопросы?
У нас ответы:) SamZan.net

Лабораторная работа 4 Шифрование данных в

Работа добавлена на сайт samzan.net:

Поможем написать учебную работу

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

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 24.11.2024

Лабораторная работа № 4

Шифрование данных в .NET Framework

Цель работы: изучение криптографической системы .NET

Теоретические сведения

Шифрование с симметричным ключом

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

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

Симметричные алгоритмы работают очень быстро и хорошо подходят для шифрования больших объемов данных.

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

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

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

Классы симметричных алгоритмов в .NET Framework

Большинство криптографических функций .NET Framework встроено в пространство имен System.Security.Cryptography, включая четыре реализации алгоритмов симметричного шифрования.

Таблица. Классы для работы с асимметричными алгоритмами

Класс

Длина ключа

Описание

SymmetricAlgorithm

He определена

Базовый класс, от которого производны все симметричные алгоритмы

RijndaelManaged

128-256 бит с 32-битовым приращением

Реализация алгоритма симметричного шифрования Rijndael в .NET Framework. Этот алгоритм является стандартом шифрования, принятым правительством США, и известен также как AES (Advanced Encryption Standard). Класс RijndaelManaged — единственный полностью управляемый класс алгоритмов симметричного шифрования в .NET Framework. Все остальные классы алгоритмов шифрования вызывают неуправляемый код. Поэтому класс RijndaelManaged является предпочтительным выбором, если приложение будет работать в среде с частичным доверием

DES

56 битов

Data Encryption Standard (DES) — алгоритм симметричного шифрования, использующий относительно короткие ключи, уязвимые к атаке перебором, из-за чего следует избегать его использования. Однако этот алгоритм до сих пор часто используется, так как совместим со многими устаревшими платформами.

TripleDES

156 битов, из которых для шифрования используется только 112

Реализация алгоритма симметричного шифрования Triple DES (3DES) в .NET Framework. По сути, этот алгоритм применяет алгоритм DES три раза

Все классы симметричных алгоритмов производны от базового класса System.Security.Cryptography.SymmetricAlgorithm и имеют следующие общие свойства:

  •  BlockSize — размер блока криптографической операции в битах. Размер блока — это число бит, одновременно обрабатываемых алгоритмом. При создании приложения, использующего шифрование, это свойство обычно можно игнорировать;
  •  FeedbackSize — размер обратной связи криптографической операции в битах. Разработчик может игнорировать это свойство;
  •  IV — определяет вектор инициализации (initialization vector) симметричного алгоритма. Как и для свойства Key, шифратор и дешифратор должны указать одинаковое значение. Чтобы избежать лишних действий, необходимых для безопасной передачи вектора инициализации между шифратором и дешифратором, можно статически определить его в приложении или получать на основе свойства Key;
  •  Key — секретный ключ для симметричного алгоритма. Если ключи не определить, они будут генерироваться автоматически. После выполнения шифрования нужно сохранить это значение и передать дешифратору. Во время расшифровки нужно указать тот же ключ, что и при шифровании;
  •  KeySize — размер секретного ключа, используемого симметричным алгоритмом, в битах. При создании объекта симметричного алгоритма исполняющая среда выберет ключ наибольшей длины, поддерживаемый платформой. Поэтому обычно можно игнорировать это свойство. Однако если получатель сообщения не поддерживает ту же длину ключа, что и отправитель, нужно задать этому свойству максимальное значение, поддерживаемое как шифратором, так и дешифратором;
  •  LegalBlockSizes — массив типа KeySizes, хранящий размеры блоков, поддерживаемые симметричным алгоритмом. Каждый член массива имеет свойства minSize и maxSize, определяющие допустимые диапазоны ключей в битах, а также свойство skipSize, указывающее интервал между допустимыми размерами ключей в битах;
  •  LegalKeySizes — массив типа KeySizes, хранящий размеры ключей, которые поддерживаются симметричным алгоритмом. Каждый член массива имеет свойства minSize и maxSize, определяющие допустимые диапазоны ключей в битах, а также свойство skipSize, указывающее интервал между допустимыми размерами ключей в битах;
  •  Mode — имеет одно из значений перечислимого CipherMode, определяющее режим алгоритма шифрования. Обычно по умолчанию установлен режим Cipher Block Chaining (CBC), который рекомендуется оставлять без изменений. Если нужно изменить это значение, его нужно изменять как на шифраторе, так и на дешифраторе;
  •  Padding — значение перечислимого PaddingMode, определяющее, как алгоритм шифрования обрабатывает различия между размером блока алгоритма и длиной простого текста. Обычно изменять это свойство не нужно.

Кроме того, классы симметричных алгоритмов имеют одинаковые методы:

  •  CreateDecryptor — для расшифровки сообщений нужно использовать объект симметричного алгоритма и вызнать этот метод, чтобы создать объект ICryptoTransform, который объект CryptoStream может использовать для расшифровки потока;
  •  CreateEncryptor — создает объект симметричною шифратора, используемый объектами CryptoStream для шифрования потока;
  •  GenerateIV — генерирует случайный вектор инициализации, который будет использоваться алгоритмом. Обычно этот метод вызывать не нужно, так как случайные векторы генерируются автоматически, если их явно не определять. Этот метод нужно вызывать, только если разработчик определил собственный вектор инициализации и хочет его использовать;
  •  GenerateKey — генерирует случайный ключ, который будет использоваться алгоритмом. Этот метод, как и GenerateIV, нужно вызывать только в том случае, если уже определено свойство Key, и в дальнейшем нужно использовать случайный ключ;
  •  ValidKeySize — определяет, допустим ли указанный размер ключа для текущего алгоритма и возвращает значение типа Boolean. Используйте этот метод при работе с неизвестным классом симметричного алгоритма, чтобы проверить, допустим ли ваш ключ для данного алгоритма.

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

Классы .NET Framework позволяют обрабатывать только 64-разрядные числа, поэтому ключи можно отображать двумя способами: в виде шестнадцатеричных чисел и в кодировке Base64.

SymmetricAlgorithm myAlg = new RijndaelManaged();

foreach (byte thisByte in myAlg.Key)

 Console.Write(thisByte.ToString("X"));

SyrnmetricAlgorithm myAlg = new RijndaelManaged();

Console.WriteLine(Convert.ToBase64String(myAlg.Key));

Для создания криптографически случайных чисел. Нужно использовать класс System.Security.Cryptography.RNGCryptoServiceProvider. Класс RNGCryptoServiceProvider генерирует случайные значения при вызове метода GetBytes. При этом создаются только массивы случайных байтов, поэтому нужно самостоятельно преобразовывать случайные байты в значения нужного формата. Для этого можно воспользоваться классом System.BitConverter, который включает методы преобразования случайных байтов во все распространенные числовые классы. Приведенный фрагмент кода консольного приложения генерирует случайное значение и преобразовывает его в 64-разрядное целое число без знака и число с плавающей запятой:

RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();

byte[] randValue = new byte[256];

rand.GetBytes(randValue);

Consols.WriteLine(System.BitConverter.ToUInt64(randValue, 0));

Console.WriteLine(System.BitConverter.ToDouble(randValue, 0));

Если задача передачи секретного ключа лежит на пользователях, генерируйте ключи симметричного шифрования на основе паролей. Однако пароль проще подобрать, чем обычный ключ. Кроме того, многие пароли не являются случайными, так что злоумышленник может сократить время взлома, используя словари паролей. Нельзя использовать в качестве ключей шифрования непосредственно пароли, но можно преобразовать пароль в ключ, используя класс System.Security.Cryptography.PasswordDeriveBytes.

Класс PasswordDeriveBytes, кроме пароля пользователя, принимает три значения: случайное значение, присоединяемое к паролю, название применяемого хэш алгоритма и число итераций для операции создания ключа. В идеале, все три значения должны быть случайными. Изменение этих значении приводит к генерации другого ключа, поэтому шифратор и дешифратор должны использовать одинаковые значения.

public PasswordDeriveBytes(string strPassword, byte[] rgbSalt, string strHashName, int Iterations);

После инициализации можно получить ключ, вызвав метод PasswordDeriveBytes.GetBytes. Метод GetBytes принимает число байтов, которое нужно вернуть. При получении ключа нужно определить длину, исходя из числа битов, требуемого свойствами KeySize и Blocksize объекта алгоритма. Кроме ключа, алгоритм шифрования использует вектор инициализации, который нужно указать как для шифратора, так и для дешифратора. Тогда как длина генерируемого ключа определяется на основе свойства KeySize, длина вектора инициализации должна определяться на основе свойства Blocksize алгоритма шифрования.

В следующем примере создается ключ и вектор инициализации для ранее созданного объекта симметричного алгоритма myAlg при помощи ранее заданной строки password. В этом фрагменте кода используются статическое значение, добавляемое к паролю, и статическое число итераций.

byte[] saltValueBytes = Encoding.ASCII.GetBytes("This is my salt");

PasswordDeriveBytes passwordKey = new PasswordDeriveBytes(password, saltValueBytes, "SHA1", 3);

myAlg.Key = passwordKey.GetBytes(myAlg.KeySize/8);

myAlg.IV = passwordKey.GetBytes(myAlg.BlockSize/8);

Шифрование и расшифровка сообщений

Чтобы зашифровать или расшифровать сообщение выполните следующее:

1. Создайте объект Stream для обращения к файлу или памяти откуда нужно считать или записать данные.

2. Создайте объект SymmetricAlgorithm.

3. Укажите ключ и вектор инициализации.

4. Вызовите метод SymmetricAlgorithm.CreateEncryptor() или SymmetricAlgorithm.CreateDecryptor(), чтобы создать объект ICryptoTransform.

5. Создайте объект CryptoStream, используя объекты Stream и ICryptoTransform.

6. Прочитайте или запишите данные в объект CryptoStream, как в любой другой объект Stream.

Следующее консольное приложение считывает нешифрованный файл, шифрует его и сохраняет результат как новый файл. Это приложение принимает 2 аргумента: имя нешифрованного файла и имя файла, который будет создан при шифровании. Показан только метод Main, но приложение использует пространства имен System.IO System.Security.Cryptography.

string unencryptedFileName = args[0];

string encryptedFileName = args[1];

//Шаг 1: Создаем объекты Stream

FileStream unencryptedFile = new FileStream(unencryptedFileName, FileMode.Open, FileAccess.Read);

FileStream encryptedFile = new FileStream(encryptedFileName, FileMode.OpenOrCreate, FileAccess.Write);

//Шаг 2: Создаем объект SymmetricAlgorithm

SymmetricAlgorithm myAlg = new RijndaelManaged();

//Шаг 3 (необязательный): Указываем ключ

myAlg.GenerateKey();

//Считываем нешифрованный файл в fileData

byte[] fileData = new byte [unencryptedFile.Length];

unencryptedFile.Read(fileData, 0, (int)unencryptedFile.Length);

//Шаг 4: Создаем объект ICryptoTransform

ICryptoTransform encryptor = myAlg.CreateEncryptor();

//Шаг 5: Создаем объект CryptoStream

CryptoStream encryptStream = new CryptoStream(encryptedFile, encryptor, CryptoStreamMode.Write);

//Шаг 6: Записываем содержимое в объект CryptoStream

encryptStream.Write (fileData, 0, (int)unencryptedFile.Length);

//Закрываем файлы

encryptStream.Close();

unencryptedFile.Close();

encryptedFile.Close();

Асимметричное шифрование

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

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

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

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

Классы ассиметричных алгоритмов в .NET Framework

В .NET Framework есть 2 класса для работы с ассиметричным шифрованием, и оба они основаны на классе System.Security.Cryptography.AsymmetricAlgorithm. Базовый класс имеет следующие свойства, некоторые из которых идентичны свойствам класса SymmetricAlgorithm:

  •  KeyExchangeAlgorithm — указывает имя алгоритма обмена ключами. Обычно не требуется обращаться к этому свойству напрямую;
  •  KeySize — размер секретного ключа, используемого симметричным алгоритмом (в битах). Асимметричные ключи имеют гораздо большую длину, чем симметричные. Например, обычный симметричный ключ имеет длину 182 бита, а в реализации .NET Framework алгоритма RSA поддерживаются ключи длиной от 384 до 16384 битов.
  •  LegalKeySizes — массив типа KeySizes, хранящий размеры ключей, поддерживаемые асимметричным алгоритмом. Каждый член массива имеет свойства MinSize и MaxSize, определяющие допустимый диапазон размера ключа в битах, и свойство SkipSize, определяющее интервал между размерами ключей в битах;
  •  SignatureAlgorithm — адрес URL документа XML, описывающего алгоритм подписания. Обычно не нужно обращаться к этому свойству напрямую.

В отличие от базового класса SymmetricAlgorithm, класс AsymmetricAlgorithm не имеет полезных методов. Вместо этого функциональность шифрования встраивается в объекты, реализующие класс AsymmetricAlgorithm. .NET Framework предоставляет две реализации этого класса:

  •  RSACryptoServiceProvider — используется для всех операций асимметричного шифрования и расшифрования. Это реализация .NET Framework алгоритма RSA. Аббревиатура RSA составлена из первых букв фамилий людей, создавших этот алгоритм в 1977 г. - Ronald Rivest, Adi Shamir, Leonard Adleman. Класс RSACryptoServiceProvider является управляемой оболочкой для неуправляемой реализации RSA, имеющейся в Cryptography API;
  •  DSACryptoServiceProvider — используется для цифрового подписания сообщений; так же является управляемой оболочкой для неуправляемого кода.

В дополнение к свойствам класса AsymmetricAlgorithm, класс RSACryptoServiceProvider имеет следующие свойства:

  •  PersistKeyInCsp — значение, указывающее, должен ли ключ храниться в провайдере криптографических услуг (CSP). Задайте значение true, если хотите повторно использовать ключ, не экспортируя его;
  •  UseMachineKeyStore — значение, указывающее, должен ли ключ храниться в хранилище ключей компьютера, а не в хранилище пользовательского профиля.

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

Класс RSACryptoServiceProvider также имеет методы шифрования и расшифровки, а также для импорта и экспорта ключей:

  •  Decrypt — расшифровывает данные, зашифрованные алгоритмом RSA;
  •  Encrypt — шифрует данные алгоритмом RSA;
  •  ExportParameters — экспортирует структуру RSAParameters, которая определяет пару ключей алгоритма. Передайте этому методу значение true, чтобы экспортировать оба ключа, или значение false, чтобы экспортировать только открытый ключ;
  •  FromXmlString — импортирует пару ключей в строку XML;
  •  ImportParameters — импортирует открытый ключ или пару ключей для указанного объекта RSAParameters;
  •  SignData — вычисляет значение хэша указанных данных и сохраняет подпись в массиве байтов;
  •  SignHash — вычисляет подпись для указанного значения хэша, шифруя его при помощи закрытого ключа и сохраняя подпись в массиве байтов;
  •  VerifyData — проверяет указанную подпись данных, сравнивая ее с подписью, вычисленной для указанных данных;
  •  VerifyHash — проверяет указанную подпись данных, сравнивая ее с подписью, вычисленной для указанного значения хэша.

Экспорт и импорт асимметричных ключей и пар ключей

Ключи RSA намного более сложны, чем ключи симметричного шифрования. Ключи RSA называются параметрами и представлены структурой RSAParameters. В таблице перечислены наиболее важные члены этой структуры и их предназначение. Структура включает несколько параметров, которые в таблице не приведены и к которым не нужно обращаться напрямую: DP, DQ, InverseQ, P И Q.

Таблица. Члены структуры RSAParameters

Параметр

Описание

D

Закрытый ключ

Exponent

Короткая часть открытого ключа. Сокращенное обозначение — e

Modulus

Длинная часть открытого ключа. Сокращенное обозначение — n

Почти всегда нужно экспортировать открытый ключ, так как без этого ключа никто не сможет отправлять владельцу закрытого ключа зашифрованные данные. Чтобы экспортировать открытый ключ в экземпляр структуры RSAParameters, используйте метод RSACryptoServiceProvider.ExportParameters, передав ему значение false.

В следующем примере продемонстрировано, как можно создать экземпляр алгоритма RSA и экспортировать его автоматически сгенерированный открытый ключ в объект RSAParameters с именем publicKey.

//Создаем экземпляр объекта алгоритма RSA

RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider();

//Создаем объект RSAParameters, содержащий только открытый ключ

RSAParameters publicKey = myRSA.ExportParameters(false);

Чтобы поместить закрытые ключи в хранилище, выполните следующее:

1. Создайте объект CspParameters.

2. Укажите свойство CspParameters.KeyContainerName.

3. Создайте объект RSACryptoServiceProvider, используя перегруженный конструктор, принимающий объект CspParameters.

4. Присвойте свойству RSACryptoServiceProvider.PersistKeyInCsp значение true.

Шифрование и расшифровка сообщений при помощи асимметричных ключей

Чтобы шифровать и расшифровывать сообщения при помощи асимметричных ключей, вызовите методы RSACryptoServiceProvider.Encrypt и RSACryptoServiceProvider.Decrypt. Оба метода принимают два параметра:

  •  byte[] rgb — массив байтов, содержащий сообщение, которое нужно зашифровать или расшифровать;
  •  bool fOAEP — значение типа Boolean. Если оно равно true, при шифровании или расшифровании будут использоваться данные заполнителя ОАЕР, поддерживаемые только в Windows XP и более поздних версия ОС. Если установлено значение false, будут использоваться данные заполнителя PKCS#1 v1.5. Методы шифрования и расшифровки должны использовать одинаковые данные заполнителя.

Заполнение данных

Заполнение данных — криптографический прием, используемый в асимметричных алгоритмах для защиты от атак, рассчитанных на то, что шифруется простой текст. .NET Framework поддерживает две схемы заполнения для алгоритма RSA:

  •  ОАЕР (Optimal Asymmetric Encryption Padding)
  •  PKCS #1 vl.5.

Обычно следует использовать ОАЕР, так как это более новая и более безопасная схема по сравнению с PKCS. PKCS используйте только в том случае, если нужно взаимодействовать с устаревшими клиентскими системами, не поддерживающими ОАЕР. Поддержка ОАЕР отсутствует во всех операционных системах, выпущенных до Windows XP, включая Windows 2000.

Самый сложный момент в шифровании — преобразование данных в формат байтового массива. Чтобы преобразовать строки в массивы байтов, используйте методы System.Text.Encoding.Unicode.GetBytes и System.Text.Encoding.Unicode.GetString. Например, следующее консольное приложение шифрует строку, используя заполнение данных PKCS#l v 1.5, а затем сразу же расшифровывает строку и выводит ее на экран:

string messageString = "Hello, World!";

RSACryptoServiceProvider myRsa = new RSACryptoServiceProvider();

Byte[] messageBytes = Encoding.Unicode.GetBytes(messageString);

Byte[] encryptedMessage = myRsa.Encrypt(messageBytes, false);

Byte[] decryptedBytes = myRsa.Decrypt(encryptedMessage, false);

Console.WriteLine(Encoding.Unicode GetString(decryptedBytes);

Контрольные вопросы

1. Поясните понятие шифрования с симметричным ключом.

2. Опишите классы симметричных алгоритмов в .NET.

3. Опишите свойства класса SymmetricAlgorithm.

4. Опишите методы класса SymmetricAlgorithm.

5. Опишите создание криптографически случайных чисел.

6. Поясните понятие ассиметричного шифрования.

7. Опишите свойства базового класса ассимметричного алгоритмов в .NET.

8. Опишите реализации базового класса ассиметричного шифрования и их дополнительные свойства.

9. Опишите методы класса RSACryptoServiceProvider.

10. Опишите экспорт и импорт ассиметричных ключей.

11. Поясните понятие заполнения данных.

Практическое задание

1. Задать пароль.

2. Сгенерировать пару ассиметричных ключей.

3. Зашифровать пароль алгоритмом RSA.

4. Расшифровать пароль.

5. Сгенерировать на основе пароля симметричный ключ шифрования.

6. Зашифровать файл указанным алгоритмом.

7. Расшифровать зашифрованный файл.

Варианты симметричных алгоритмов

Вариант

Алгоритм

1

Rijndael

2

DES

3

3DES




1. Тема 6 Организация и планирование труда на железнодорожном транспорте
2. Тема 2 Добыча транспортировка предварительная подготовка и хранение сырьевых материалов
3. Конструкторская и технологическая подготовка производства моделей мужских пиджаков
4. 100 110 в мин Живот мягкий незначительно болезненный в нижних отделах
5. Правовая защита суррогатного материнства
6. Стереотипы мышления и методы избавления от них
7. ТЕМА- АДМІНІСТРАТИВНОПРАВОВЕ РЕГУЛЮВАННЯ У СФЕРІ ЕКОНОМІКИ ПЛАН Загальна характеристика та з
8. Характеристика фруктовых соков и некратов
9. Одна из жен сынов пророческих с воплем говорила Елисею- раб твой мой муж умер; а ты знаешь что раб твой боялс
10. Реформирование системы контроля платежеспособности страховых компаний в странах ЕС
11. Тема 1 Становление и структура международной экономики Вопрос 1
12. Тема V ЛИЧНОСТЬ МЕЖЛИЧНОСТНЫЕ ОТНОШЕНИЯ Уроки 7173
13. Факторы формирующие образ человека
14. ТЕМА- Реформы Александра II ПЛАН ВВЕДЕНИЕ 1
15. РЕФЕРАТ дисертації на здобуття наукового ступеня кандидата наук з державного управління
16. Олимпиада означает- а четырехлетний период между Олимпийскими играми; б первый год четырехлетия наст
17. Технологія кондитерських виробів 1.
18. Курсовая работа- Загальне дослідження ринку дитячого харчування та конкретно дитячих соків.html
19. Уральский государственный педагогический университет Факультет туризма и гостиничного сервиса Кафед
20. Лекция 6 Особенности применения метода контентанализа в социологии журналистики В общем курсе социологи