Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Тарасов А. А._525ст.2ПЗ .docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
11.18 Mб
Скачать

6 Стадии и этапы разработки

6.1 Стадии разработки

Разработка должна быть проведена в три стадии:

1. Разработка технического задания;

2. Рабочее проектирование;

3. Тестирование.

6.2 Этапы разработки

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

На стадии рабочего проектирования должны быть выполнены перечисленные ниже этапы работ:

1. Разработка технического задания;

2. Рабочее проектирование;

3. Тестирование.

Приложение Б

Текст программы

Клас frmMain

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

using System.IO;

using System.Text;

namespace PictureKey

{

/// <summary>

/// Zusammendfassende Beschreibung fьr Form1.

/// </summary>

public class frmMain : System.Windows.Forms.Form

{

private System.Windows.Forms.GroupBox grpPicture;

private System.Windows.Forms.Label fileName;

private System.Windows.Forms.TextBox txtImageFile;

private System.Windows.Forms.PictureBox picImage;

private System.Windows.Forms.Button btnImageFile;

private System.Windows.Forms.TextBox txtKeyFile;

private System.Windows.Forms.RadioButton rdoKeyText;

private System.Windows.Forms.GroupBox grpKey;

private System.Windows.Forms.TextBox txtKeyText;

private System.Windows.Forms.RadioButton rdoKeyFile;

private System.Windows.Forms.Button btnHide;

private System.Windows.Forms.Button btnExtract;

private System.Windows.Forms.TabControl tabControl1;

private System.Windows.Forms.TabPage tabPage1;

private System.Windows.Forms.TabPage tabPage2;

private System.Windows.Forms.Button btnSaveBitmap;

private System.Windows.Forms.GroupBox grpMessage;

private System.Windows.Forms.RadioButton rdoMessageText;

private System.Windows.Forms.TextBox txtMessageFile;

private System.Windows.Forms.TextBox txtMessageText;

private System.Windows.Forms.Button btnMessage;

private System.Windows.Forms.RadioButton rdoMessageFile;

private System.Windows.Forms.GroupBox extractBox;

private System.Windows.Forms.Label saveExtracted;

private System.Windows.Forms.Label extractedText;

private System.Windows.Forms.Button btnKeyFile;

private System.Windows.Forms.TextBox txtExtractedMsgFile;

private System.Windows.Forms.Button btnExtractedMsgFile;

private System.Windows.Forms.TextBox txtExtractedMsgText;

private System.Windows.Forms.CheckBox chkGrayscale;

private System.ComponentModel.Container components = null;

public frmMain()

{

InitializeComponent();

}

/// <summary>Cleanup</summary>

protected override void Dispose( bool disposing )

{

if( disposing )

{

if (components != null)

{

components.Dispose();

}

}

base.Dispose( disposing );

}

static void Main()

{

Application.Run(new frmMain());

}

private void btnHide_Click(object sender, System.EventArgs e)

{

Bitmap bitmap = (Bitmap)picImage.Image;

//get a stream for the message to hide

Stream messageStream = GetMessageStream();

if(messageStream.Length == 0)

{

MessageBox.Show("Please enter a message or select a file.");

txtMessageText.Focus();

}

else

{

//get a stream fot the key

Stream keyStream = GetKeyStream();

if(keyStream.Length == 0)

{

MessageBox.Show("Please enter a password or select a key file.");

txtKeyText.Focus();

}

else

{

try

{

//hide the message

CryptUtility.HideMessageInBitmap(messageStream, bitmap, keyStream, chkGrayscale.Checked);

//display result

picImage.Image = bitmap;

btnSaveBitmap.Enabled = true;

}

catch(Exception ex)

{

MessageBox.Show("Exception:\r\n"+ex.Message);

}

}

keyStream.Close();

}

messageStream.Close();

bitmap = null;

}

private void btnExtract_Click(object sender, System.EventArgs e)

{

Bitmap bitmap = (Bitmap)picImage.Image;

//empty stream for the extracted message

Stream messageStream = new MemoryStream();

//get a stream for the key

Stream keyStream = GetKeyStream();

if(keyStream.Length == 0)

{

MessageBox.Show("Please enter a password or select a key file.");

txtKeyText.Focus();

}

else

{

try

{

//extract the hidden message from the bitmap

CryptUtility.ExtractMessageFromBitmap(bitmap, keyStream, ref messageStream);

//save the message, if a filename is available

if(txtExtractedMsgFile.Text.Length > 0)

{

messageStream.Seek(0, SeekOrigin.Begin);

FileStream fs = new FileStream(txtExtractedMsgFile.Text, FileMode.Create);

byte[] streamContent = new Byte[messageStream.Length];

messageStream.Read(streamContent, 0, streamContent.Length);

fs.Write(streamContent, 0, streamContent.Length);

}

//display the message - displays chaos, if it's no unicode text

messageStream.Seek(0, SeekOrigin.Begin);

StreamReader reader = new StreamReader(messageStream, UnicodeEncoding.Unicode);

String readerContent = reader.ReadToEnd();

if(readerContent.Length > txtExtractedMsgText.MaxLength){

readerContent = readerContent.Substring(0, txtExtractedMsgText.MaxLength);

}

txtExtractedMsgText.Text = readerContent;

}

catch(Exception ex)

{

MessageBox.Show("Exception:\r\n"+ex.Message);

}

}

//close the streams

messageStream.Close();

keyStream.Close();

bitmap = null;

}

/// <summary>Creates a stream to read the message from a string or a file</summary>

/// <returns>FileStream for a message file, or MemoryStream</returns>

private Stream GetMessageStream()

{

Stream messageStream;

if(rdoMessageText.Checked)

{

byte[] messageBytes = UnicodeEncoding.Unicode.GetBytes(txtMessageText.Text);

messageStream = new MemoryStream(messageBytes);

}

else

{

messageStream = new FileStream(txtMessageFile.Text, FileMode.Open, FileAccess.Read);

}

return messageStream;

}

/// <summary>Creates a stream to read the key from a string or a file</summary>

/// <returns>FileStream for a key file, or MemoryStream for a password</returns>

private Stream GetKeyStream()

{

Stream keyStream;

if(rdoKeyText.Checked)

{

byte[] keyBytes = UnicodeEncoding.Unicode.GetBytes(txtKeyText.Text);

keyStream = new MemoryStream(keyBytes);

}

else

{

keyStream = new FileStream(txtKeyFile.Text, FileMode.Open, FileAccess.Read);

}

return keyStream;

}

/// <summary>Opens a bitmap</summary>

/// <param name="fileName">Path and name of the bitmap file</param>

private void SetImage(String fileName)

{

picImage.Image = new Bitmap(fileName);

btnHide.Enabled = btnExtract.Enabled = true;

btnSaveBitmap.Enabled = false;

int index = fileName.LastIndexOf("\\")+1;

if(index > 0){ fileName = fileName.Substring(index); }

grpPicture.Text = "Carrier Bitmap ("+fileName+")";

}

/// <summary>Displays the OpenFile dialog</summary>

/// <returns>The selected file name, or null</returns>

private String GetFileName(String filter)

{

OpenFileDialog dlg = new OpenFileDialog();

dlg.Multiselect = false;

if(filter.Length > 0){ dlg.Filter = filter; }

if( dlg.ShowDialog(this) != DialogResult.Cancel)

{

return dlg.FileName;

}

else

{

return null;

}

}

private void rdoMessage_Click(object sender, System.EventArgs e)

{

txtMessageFile.Enabled = rdoMessageFile.Checked;

txtMessageText.Enabled = rdoMessageText.Checked;

}

private void rdoKey_Click(object sender, System.EventArgs e)

{

txtKeyFile.Enabled = rdoKeyFile.Checked;

txtKeyText.Enabled = rdoKeyText.Checked;

}

private void btnImageFile_Click(object sender, System.EventArgs e)

{

String fileName = GetFileName("Bitmaps (*.bmp)|*.bmp|Tagged Image File Format(*.tif)|*.tif|PNG-24(*.png)|*.png");

if(fileName != null)

{

txtImageFile.Text = fileName;

SetImage(fileName);

}

}

private void btnSaveBitmap_Click(object sender, System.EventArgs e)

{

SaveFileDialog dlg = new SaveFileDialog();

dlg.Filter = "Bitmaps (*.bmp)|*.bmp|Tagged Image File Format(*.tif)|*.tif|PNG-24(*.png)|*.png";

if( dlg.ShowDialog() == DialogResult.OK )

{

System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Bmp;

if(dlg.FilterIndex == 2)

{

format = System.Drawing.Imaging.ImageFormat.Tiff;

}

else if(dlg.FilterIndex == 3)

{

format = System.Drawing.Imaging.ImageFormat.Png;

}

//copy the bitmap

Image img = new Bitmap(picImage.Image);

//close bitmap file

this.SuspendLayout();

picImage.Image.Dispose();

picImage.Image = null;

btnSaveBitmap.Enabled = btnHide.Enabled = btnExtract.Enabled = false;

txtImageFile.Text = String.Empty;

this.ResumeLayout();

//save new bitmap

img.Save(dlg.FileName, format);

}

}

private void txtMessageFile_Enter(object sender, System.EventArgs e)

{

rdoKeyFile.Checked = true;

}

private void txtMessageText_Enter(object sender, System.EventArgs e)

{

rdoKeyText.Checked = true;

}

private void txtImageFile_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)

{

if(e.KeyCode == Keys.Enter)

{

SetImage(txtImageFile.Text);

}

}

private void btnMessage_Click(object sender, System.EventArgs e)

{

String fileName = GetFileName("Text Files | *.txt");

if(fileName != null)

{

txtMessageFile.Text = fileName;

rdoMessageFile.Checked = true;

}

}

private void btnExtractedMsgFile_Click(object sender, System.EventArgs e)

{

SaveFileDialog dlg = new SaveFileDialog();

dlg.Filter = "Text Files | *.txt";

if( dlg.ShowDialog() == DialogResult.OK )

{

txtExtractedMsgFile.Text = dlg.FileName;

}

}

private void btnKeyFile_Click(object sender, System.EventArgs e)

{

String fileName = GetFileName("Text Files | *.txt");

if(fileName != null)

{

txtKeyFile.Text = fileName;

rdoKeyFile.Checked = true;

}

}

}

}

Класс CryptUtility

using System;

using System.Drawing;

using System.Windows.Forms;

using System.Text;

using System.IO;

namespace PictureKey

{

public class CryptUtility

{

/// <summary>Hides a message in a bitmap</summary>

/// <param name="messageStream">The message to hide</param>

/// <param name="bitmap">The carrier bitmap</param>

/// <param name="keyStream">The key to use</param>

public static void HideMessageInBitmap(Stream messageStream, Bitmap bitmap, Stream keyStream, bool useGrayscale)

{

HideOrExtract(ref messageStream, bitmap, keyStream, false, useGrayscale);

messageStream = null;

}

/// <summary>Extracts an hidden message from a bitmap</summary>

/// <param name="bitmap">The carrier bitmap</param>

/// <param name="keyStream">The key used for hiding the message</param>

/// <param name="messageStream">Empty stream to receive the message</param>

public static void ExtractMessageFromBitmap(Bitmap bitmap, Stream keyStream, ref Stream messageStream)

{

HideOrExtract(ref messageStream, bitmap, keyStream, true, false);

}

/// <summary>Stepts through the pixels of a bitmap using a key pattern and hides or extracts a message</summary>

/// <param name="messageStream">If exctract is false, the message to hide - otherwise an empty stream to receive the extracted message</param>

/// <param name="bitmap">The carrier bitmap</param>

/// <param name="keyStream">The key specifying the unchanged pixels between two hidden bytes</param>

/// <param name="extract">Extract a hidden message (true), or hide a message in a clean carrier bitmap (false)</param>

private static void HideOrExtract(ref Stream messageStream, Bitmap bitmap, Stream keyStream, bool extract, bool useGrayscale)

{

//Current count of pixels between two hidden message-bytes

//Changes with every hidden byte according to the key

int currentStepWidth = 0;

//Current byte in the key stream - normal direction

byte currentKeyByte;

//Current byte in the key stream - reverse direction

byte currentReverseKeyByte;

//current position in the key stream

long keyPosition;

//maximum X and Y position

int bitmapWidth = bitmap.Width-1;

int bitmapHeight = bitmap.Height-1;

//Color component to hide the next byte in (0-R, 1-G, 2-B)

//Rotates with every hidden byte

int currentColorComponent = 0;

//Stores the color of a pixel

Color pixelColor;

//Length of the message

Int32 messageLength;

if(extract)

{

//Read the length of the hidden message from the first pixel

pixelColor = bitmap.GetPixel(0,0);

messageLength = (pixelColor.R << 2) + (pixelColor.G << 1) + pixelColor.B;

messageStream = new MemoryStream(messageLength);

}

else

{

messageLength = (Int32)messageStream.Length;

if(messageStream.Length >= 16777215)

{ //The message is too long

String exceptionMessage = "Themessage is too long, only 16777215 bytes are allowed.";

throw new Exception(exceptionMessage);

}

//Check size of the carrier image

//Pixels available

long countPixels = (bitmapWidth*bitmapHeight) -1;

//Pixels required - start with one pixel for length of message

long countRequiredPixels = 1;

//add up the gaps between used pixels (sum up all the bytes of the key)

while((keyStream.Position < keyStream.Length)&&(keyStream.Position < messageLength))

{

countRequiredPixels += keyStream.ReadByte();

}

//If the key is shorter than the message, it will be repeated again and again

//Multiply with count of key periods

countRequiredPixels *= (long)System.Math.Ceiling( ((float)messageStream.Length / (float)keyStream.Length) );

if(countRequiredPixels > countPixels)

{ //The bitmap is too small

String exceptionMessage = "The image is too small for this message and key. "+countRequiredPixels+" pixels are required.";

throw new Exception(exceptionMessage);

}

//Write length of the bitmap into the first pixel

int colorValue = messageLength;

int red = colorValue >> 2;

colorValue -= red << 2;

int green = colorValue >> 1;

int blue = colorValue - (green << 1);

pixelColor = Color.FromArgb(red, green, blue);

bitmap.SetPixel(0,0, pixelColor);

}

//Reset the streams

keyStream.Seek(0, SeekOrigin.Begin);

messageStream.Seek(0, SeekOrigin.Begin);

//Current position in the carrier bitmap

//Start with 1, because (0,0) contains the message's length

Point pixelPosition = new Point(1,0);

//Loop over the message and hide each byte

for(int messageIndex = 0; messageIndex < messageLength; messageIndex++)

{

//repeat the key, if it is shorter than the message

if(keyStream.Position == keyStream.Length)

{

keyStream.Seek(0, SeekOrigin.Begin);//set it to 0

}

//Get the next pixel-count from the key, use "1" if it's 0

currentKeyByte = (byte)keyStream.ReadByte();

currentStepWidth = (currentKeyByte==0) ? (byte)1 : currentKeyByte;

//jump to reverse-read position and read from the end of the stream

keyPosition = keyStream.Position;

keyStream.Seek(-keyPosition, SeekOrigin.End);

currentReverseKeyByte = (byte)keyStream.ReadByte();

//jump back to normal read position

keyStream.Seek(keyPosition, SeekOrigin.Begin);

//Perform line breaks, if current step is wider than the image

while(currentStepWidth > bitmapWidth)

{

currentStepWidth -= bitmapWidth;

pixelPosition.Y++;

}

//Move X-position

if((bitmapWidth - pixelPosition.X) < currentStepWidth)

{

pixelPosition.X = currentStepWidth - (bitmapWidth - pixelPosition.X);

pixelPosition.Y++;

}

else

{

pixelPosition.X += currentStepWidth;

}

//Get color of the "clean" pixel

pixelColor = bitmap.GetPixel(pixelPosition.X, pixelPosition.Y);

if(extract)

{

//Extract the hidden message-byte from the color

byte foundByte = (byte)(currentReverseKeyByte ^ GetColorComponent(pixelColor, currentColorComponent));

messageStream.WriteByte(foundByte);

//Rotate color components

currentColorComponent = (currentColorComponent==2) ? 0 : (currentColorComponent+1);

}

else

{

//To add a bit of confusion, xor the byte with a byte read from the keyStream

int currentByte = messageStream.ReadByte() ^ currentReverseKeyByte;

if(useGrayscale)

{

pixelColor = Color.FromArgb(currentByte, currentByte, currentByte);

}

else

{

//Change one component of the color to the message-byte

SetColorComponent(ref pixelColor, currentColorComponent, currentByte);

//Rotate color components

currentColorComponent = (currentColorComponent==2) ? 0 : (currentColorComponent+1);

}

bitmap.SetPixel(pixelPosition.X, pixelPosition.Y, pixelColor);

}

}

//the stream will be closed by the calling method

bitmap = null;

keyStream = null;

}

/// <summary>Return one component of a color</summary>

/// <param name="pixelColor">The Color</param>

/// <param name="colorComponent">The component to return (0-R, 1-G, 2-B)</param>

/// <returns>The requested component</returns>

private static byte GetColorComponent(Color pixelColor, int colorComponent)

{

byte returnValue = 0;

switch(colorComponent)

{

case 0:

returnValue = pixelColor.R;

break;

case 1:

returnValue = pixelColor.G;

break;

case 2:

returnValue = pixelColor.B;

break;

}

return returnValue;

}

/// <summary>Changees one component of a color</summary>

/// <param name="pixelColor">The Color</param>

/// <param name="colorComponent">The component to change (0-R, 1-G, 2-B)</param>

/// <param name="newValue">New value of the component</param>

private static void SetColorComponent(ref Color pixelColor, int colorComponent, int newValue)

{

switch(colorComponent)

{

case 0:

pixelColor = Color.FromArgb(newValue, pixelColor.G, pixelColor.B);

break;

case 1:

pixelColor = Color.FromArgb(pixelColor.R, newValue, pixelColor.B);

break;

case 2:

pixelColor = Color.FromArgb(pixelColor.R, pixelColor.G, newValue);

break;

}

}

private static String UnTrimColorString(String color, int desiredLength)

{

int difference = desiredLength - color.Length;

if(difference > 0)

{

color = new String('0', difference) + color;

}

return color;

}

}

}

Приложение В

Руководство пользователя

Назначение программы

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

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

Программа предназначена для эксплуатации на ПК, установленном дома или в офисе.

Эксплуатация программы

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

Рисунок В.1 – Окно программы

Для того что бы скрыть тест необходимо нажать на кнопку «Hide Message» в правом нижнем углу окна программы. После этого появится возможность сохранить результат работы программы (кнопка «Save Result» станет доступной).

Для обратного действия, то есть получения зашифрованной ранее информации из картинки, необходимо перейти на вкладку «Extract» в правой части приложения. Далее необходимо ввести пароль и нажат кнопку «Extract hidden message», спрятанный текст появится в текстовом окне (рисунок В.2).

Рисунок В.2 –Извлечение сообщения

Извлеченный текст можно сохранить, указав путь к текстовому файлу и повторно нажать на кнопку «Extract hidden message».

Если пользователь попытается спрятать или извлечь сообщение, не введя пароль, то программа выдает сообщение, изображенное на рисунке В.3.

Рисунок В.3 – Сообщение об ошибке

Приложение Г Презентация