public Container(ref PreparedData data, Point[] selectedPoints, Point[] NotSelectedPoints, int x, int y, int xSize, int ySize) { if (selectedPoints != null) { this.points_Checked = new General.Point[selectedPoints.Length]; for (int i = 0; i < selectedPoints.Length; i++) { this.points_Checked[i] = new General.Point(selectedPoints[i].x + x, selectedPoints[i].y + y); } this.sumBits_Checked = getSumBits(this.points_Checked, ref data); } if (NotSelectedPoints != null) { this.points_NotChecked = new General.Point[NotSelectedPoints.Length]; for (int i = 0; i < NotSelectedPoints.Length; i++) { this.points_NotChecked[i] = new General.Point(NotSelectedPoints[i].x + x, NotSelectedPoints[i].y + y); } this.sumBits_NotChecked = getSumBits(this.points_NotChecked, ref data); } this.xSize = xSize; this.ySize = ySize; }
public Container(int x1, int y1, int x2, int y2, ref PreparedData data) { this.top = new Point(x1, y1); // верхняя левая точка контейнера this.bottom = new Point(x2, y2); // верхняя правая точка контейнера sumBits = getSumBits(this.top, this.bottom, ref data); // получаем "сумму по модулю" всех бит контейнера }
public void Coder(ref PreparedData data, int xSize, int ySize) { int calContainers = (data.img.Width / xSize); // получаю количество контейнеров по оси Х int rowContainers = (data.img.Height / ySize); // получаю количество контейнеров по оси Y int numberOfContainers = rowContainers * calContainers; // Получаю общее количество контейнеров if (numberOfContainers < data.msgBits.Length) // проверяю возможность внедрении информации относительно размеров контейнеров и длины сообщения { throw new Exception("Не достаточно места для хранения информации. Измените размер контейнера или длину сообщения"); } Container[] containers = new Container[data.msgBits.Length]; // формирую массив контейнеров (по одномерному должно работать быстрее) Длинной в сообщение // формирую блоки и считаю их контрольные суммы getContainers(ref data, ref containers, xSize, ySize, calContainers, rowContainers, data.msgBits.Length); // начинаем заполнять блоки информацией int index = 0; while (index < containers.Length) { if (containers[index].sumBits != data.msgBits[index]) { //Console.WriteLine("Container #{0}: Changed from {1} to {2}", index, containers[index].sumBits, msgBits[index]); containers[index].updateValue(data.msgBits[index], ref data); } index++; } data.imgCoded = Utils.setColorChanel(ref data); }
public string Decrypt(ref PreparedData data, string start, int offset = 0) { start = Information.key; BitArray startBits = new BitArray(Encoding.UTF8.GetBytes(start)); // введенные пользователем BitArray startBitsFromImage = new BitArray(startBits.Length); // из изображения int m = 0; // по у int n = 0; // по х int limit = start.Length; // граница считывания string result = getInformation(ref data, ref m, ref n, limit, offset); // ключ if (!result.Equals(start)) throw new Exception("We don't have information here, or key not valid"); limit += (32 / 8); string length = getInformation(ref data, ref m, ref n, limit, offset); // длина сообщения (дает с мусором) limit += Convert.ToInt32(length); string message = getInformation(ref data, ref m, ref n, limit, offset); // сообщение Information.msg = message; return message; }
public void Coder(ref PreparedData data, General.Point[] selectedPoints, General.Point[] NotSelectedPoints, int xSize, int ySize) { int colContainers = (data.img.Width / xSize); // получаю количество контейнеров по оси Х int rowContainers = (data.img.Height / ySize); // получаю количество контейнеров по оси Y int numberOfContainers = rowContainers * colContainers; // Получаю общее количество контейнеров if (numberOfContainers < data.msgBits.Length) // проверяю возможность внедрении информации относительно размеров контейнеров и длины сообщения { throw new Exception("Не достаточно места для хранения информации. Измените размер контейнера или длину сообщения"); } Methods.Block_Different_Shape.Container[] containers = new Methods.Block_Different_Shape.Container[data.msgBits.Length]; // формирую массив контейнеров (по одномерному должно работать быстрее) Длинной в сообщение getContainers(ref data, ref containers, selectedPoints, NotSelectedPoints, xSize, ySize, rowContainers, colContainers, containers.Length); // начинаем заполнять блоки информацией int index = 0; while (index < containers.Length) { if (containers[index].points_NotChecked == null || containers[index].points_Checked == null) { if (containers[index].points_NotChecked == null) { if (containers[index].sumBits_Checked != data.msgBits[index]) { containers[index].updateValue(data.msgBits[index], false, ref data); } } else { if (containers[index].sumBits_NotChecked != data.msgBits[index]) { containers[index].updateValue(data.msgBits[index], true, ref data); } } } else { if(index % 2 == 0 && containers[index].sumBits_Checked != data.msgBits[index]) { containers[index].updateValue(data.msgBits[index], Convert.ToBoolean(index % 2), ref data); } else if(index % 2 == 1 && containers[index].sumBits_NotChecked != data.msgBits[index]) { containers[index].updateValue(data.msgBits[index], Convert.ToBoolean(index % 2), ref data); } } index++; } data.imgCoded = Utils.setColorChanel(ref data); }
public bool getSumBits(Point[] points, ref PreparedData data) { bool sum = false; // полходим по всему контейнеру for (int i = 0; i < points.Length; i++) { char[] colorBits = Convert.ToString(data.imgChanel[points[i].y][points[i].x], 2).ToCharArray(); // переводим текущую цветовую компоненту в двоичный вид if (colorBits[colorBits.Length - 1] == '1') // если последний бит единица { sum ^= true; // складываем с единицей } else { sum ^= false; // складываем с нулем } } return sum; }
// обновление значения "суммы по модулю" public void updateValue(bool value, ref PreparedData data) { // случайным образом выбираем позицию в контейнере Random rnd = new Random(); int x = rnd.Next(this.top.x, this.bottom.x); int y = rnd.Next(this.top.y, this.bottom.y); char[] colorBits = Convert.ToString(data.imgChanel[y][x], 2).ToCharArray(); // переводим текущую цветовую компоненту в 2й вид if (colorBits[colorBits.Length - 1] == '1') // если последний бит единица { colorBits[colorBits.Length - 1] = '0'; // записываем в объект 1 } else { colorBits[colorBits.Length - 1] = '1'; // записываем в объект 0 } data.imgChanel[y][x] = Convert.ToInt32(new string(colorBits), 2); // записываем обновленное значение цветовой компоненты в цветовом канале sumBits = value; // обновляем значение в объекте контейнера }
public bool getSumBits(Point top, Point bottom, ref PreparedData data) { bool sum = false; // полходим по всему контейнеру for (int y = top.y; y < bottom.y; y++) { for (int x = top.x; x < bottom.x; x++) { char[] colorBits = Convert.ToString(data.imgChanel[y][x], 2).ToCharArray(); // переводим текущую цветовую компоненту в двоичный вид if (colorBits[colorBits.Length - 1] == '1') // если последний бит единица { sum ^= true; // складываем с единицей } else { sum ^= false; // складываем с нулем } } } return sum; }
public void Encrypt(ref PreparedData data, int offset = 0) { Console.WriteLine("Message length including offset {0}", data.msgBits.Length * (offset + 1)); if (data.img.Height * data.img.Width < data.msgBits.Length * (offset + 1)) throw new Exception("Не достаточно места для сокрытия данных"); int m = 0; int n = 0; while (m < data.img.Height) { n = n - data.imgChanel[m].Length; if (n % data.imgChanel[m].Length == 0) n = 0; while (n < data.img.Width) { if (((m * data.img.Width + n) / (offset + 1)) >= data.msgBits.Length) { data.imgCoded = Utils.setColorChanel(ref data); return; // нужно присмотреться } char[] colorBits = Convert.ToString(data.imgChanel[m][n], 2).ToCharArray(); if (data.msgBits[((m * data.img.Width + n) / (offset + 1))]) { colorBits[colorBits.Length - 1] = '1'; } else { colorBits[colorBits.Length - 1] = '0'; } data.imgChanel[m][n] = Convert.ToInt32(new string(colorBits), 2); n += offset + 1; } m++; } }
private void getContainers(ref PreparedData data, ref Container[] containers, int xSize, int ySize, int calContainers, int rowContainers, int limit, int startFrom = 0) { int index = 0; // индекс в контейнера int yStart = 0; int xStart = 0; if(startFrom > 0) { yStart = startFrom / calContainers; xStart = startFrom % calContainers; } for (int y = yStart * ySize; y < ySize * rowContainers && index < limit; y += ySize) { for (int x = xStart * xSize; x < xSize * calContainers && index < limit; x += xSize) { containers[index] = new Container(x, y, (x + xSize) - 1, (y + ySize) - 1, ref data); // берем текущие кооридинаты и координаты, смещенные относительно index++; } xStart = 0; } }
private string getInformation(ref PreparedData data, ref int m, ref int n, int limit, int offset = 0) { int k = 0; // итератор по данным BitArray hiddenData = new BitArray(limit * 8); while(m < data.img.Height) { if (n - data.imgChanel[m].Length > 0) n = n - data.imgChanel[m].Length; if (n % data.imgChanel[m].Length == 0) n = 0; while(n < data.img.Width) { if (((m * data.img.Width + n) / (offset + 1)) >= (limit * 8)) { byte[] hiddenDataBytes = new byte[limit]; hiddenData.CopyTo(hiddenDataBytes, 0); return Encoding.UTF8.GetString(hiddenDataBytes); // изменить } char[] bitsOfColorComponent = Convert.ToString(data.imgChanel[m][n], 2).ToCharArray(); // переводим текущу. цветовую компоненту в 2й вид if (bitsOfColorComponent[bitsOfColorComponent.Length - 1] == '1') // если последний бит единица { hiddenData[k] = true; // записываем в объект 1 } else { hiddenData[k] = false; // записываем в объект 0 } n += offset + 1; // сдвигаем указатель дальше k++; } m++; } return null; }
public string Decoder(ref PreparedData data, int xSize, int ySize, string start) { string message = null; int startFrom = 0; BitArray startBits = new BitArray(Encoding.UTF8.GetBytes(start)); // введенные пользователем BitArray startBitsFromImage = new BitArray(startBits.Length); // из изображения int calContainers = (data.img.Width / xSize); // получаю количество контейнеров по оси Х int rowContainers = (data.img.Height / ySize); // получаю количество контейнеров по оси Y int numberOfContainers = rowContainers * calContainers; // Получаю общее количество контейнеров int limit = start.Length * 8; // граница считывания int index = 0; // ключ // формирую блоки и считаю их контрольные суммы message = getDecodedInfo(ref data, xSize, ySize, calContainers, rowContainers, ref startFrom, limit, ref index); Console.WriteLine("Ключ: {0}", message); if(!message.Equals(start)) throw new Exception("Информация не найдена или ключ не верен"); limit = 32; message = getDecodedInfo(ref data, xSize, ySize, calContainers, rowContainers, ref startFrom, limit, ref index); Console.WriteLine("Длина: {0}", message); limit = Convert.ToInt32(message) * 8; message = getDecodedInfo(ref data, xSize, ySize, calContainers, rowContainers, ref startFrom, limit, ref index); Console.WriteLine("Сообщение: {0}", message); Information.msg = message; return message; }
static void Main(string[] args) { // Отладка. Замер времени выполнения Stopwatch sw = new Stopwatch(); // Входные данные Information.msg = "Helloooooworld----------F**K"; Information.key = "Nachalo"; Information.imgPath = @"C:\Users\Евгений\Pictures\check-in-minion-BMP.bmp"; Information.colorChanel = "B"; Information.container.xSize = 128; Information.container.ySize = 128; // Обработка входных данных // Явное преобразование регистра цветовой компоненты Information.colorChanel = Information.colorChanel.ToUpper(); // Преобразование секретного сообщения в массив бит BitArray msgBit = new BitArray(Encoding.UTF8.GetBytes(Information.msg)); // Получение изобрадения по выбранному цветовому каналу Bitmap img = new Bitmap(Information.imgPath, true); // Вывод информации о входных данных Console.WriteLine("Шифруемое сообщение: {0}", Information.msg); Console.WriteLine("Количество бит в сообщении: {0}", msgBit.Length); Console.WriteLine("Размер изображения: {0}х{1}", img.Width, img.Height); Console.WriteLine("Количество пикселей в изображении: {0}", img.Width * img.Height); Console.WriteLine("Размер контейнера: {0}x{1}", Information.container.xSize, Information.container.ySize); Console.WriteLine("Количество пикселей в контейнере: {0}", Information.container.xSize * Information.container.ySize); //// Замер времени выполнения //Console.WriteLine(); //Console.WriteLine("Получение цветового канала..."); //sw.Start(); //int[][] imgChanel = Utils.getColorChanel(img, Information.colorChanel); //sw.Stop(); //Console.WriteLine("Затрачено времени: {0}", sw.Elapsed); //sw.Reset(); PreparedData data = new PreparedData("code"); LeastSignificantBit lsb = new LeastSignificantBit(); string decrypt_message; lsb.Encrypt(ref data, 0); decrypt_message = lsb.Decrypt(ref data, Information.key, 0); //Block blockMethod = new Block(); //blockMethod.Coder(ref data, 10, 10); //blockMethod.Decoder(ref data, 10, 10, "Nachalo"); Console.WriteLine("Message is \"{0}\"", decrypt_message); // Чего потеря в весе почти в 2 раза? // #1 Отсутствие метаданных изображения Console.WriteLine(); Console.WriteLine("Запись обработанного цветового канала..."); sw.Start(); // Utils.setColorChanel(img, data.imgChanel, Information.colorChanel).Save(@"C:\Users\Евгений\Pictures\check-in-minion2.bmp"); sw.Stop(); Console.WriteLine("Затрачено времени: {0}", sw.Elapsed); Console.WriteLine(); Console.WriteLine("Выполнено"); Console.ReadLine(); }
private string getDecodedInfo(ref PreparedData data, int xSize, int ySize, int calContainers, int rowContainers, ref int startFrom, int limit, ref int index) { startFrom += index; BitArray hiddenData = new BitArray(limit); // считанные данные; byte[] hiddenDataBytes = new byte[limit / 8];; Container[] containers = new Container[hiddenData.Length]; // формирую блоки и считаю их контрольные суммы getContainers(ref data, ref containers, xSize, ySize, calContainers, rowContainers, hiddenData.Length, startFrom); index = 0; while (index < hiddenData.Length) { hiddenData[index] = containers[index].sumBits; index++; } hiddenData.CopyTo(hiddenDataBytes, 0); return Encoding.UTF8.GetString(hiddenDataBytes); // расшифрованные данные }
private void button_Decode_Click(object sender, EventArgs e) { int row; int col; try { row = Convert.ToInt32(textBox_Block_Diff_M.Text); col = Convert.ToInt32(textBox_Block_Diff_N.Text); } catch (Exception) { MessageBox.Show("В полях размера блока введены недопустимые символы"); return; } string colorComponent = "R"; if (radioButton_Red.Checked) colorComponent = "R"; else if (radioButton_Green.Checked) colorComponent = "G"; else if (radioButton_Blue.Checked) colorComponent = "B"; Regex pattern = new Regex(@"^\s*\d+\s*$"); if (pattern.IsMatch(textBox_Offset.Text) && pattern.IsMatch(textBox_M.Text) && pattern.IsMatch(textBox_N.Text) && Image_Default.Image != null) { string xSize; string ySize; if (radioButton_Block_Method.Checked) { xSize = textBox_M.Text; ySize = textBox_N.Text; } else { xSize = textBox_Block_Diff_M.Text; ySize = textBox_Block_Diff_N.Text; } Utils.initialize(imgPath, richTextBoxKey.Text, colorComponent, (textBox_Offset.Text.Length == 0 ? 0 : Convert.ToInt32(textBox_Offset.Text)), (xSize.Length == 0 ? 0 : Convert.ToInt32(xSize)), (ySize.Length == 0 ? 0 : Convert.ToInt32(ySize))); data = new PreparedData("decode"); if (Utils.checkFields("decode")) { MessageBox.Show("Одно или более полей - пустые"); return; } //try //{ if (radioButtonLSB_Static.Checked) { Methods.LeastSignificantBit lsb = new Methods.LeastSignificantBit(); message_box.Text = lsb.Decrypt(ref data, Information.key, Information.offset); } else if (radioButton_Block_Method.Checked) { Methods.Block.Block block = new Methods.Block.Block(); message_box.Text = block.Decoder(ref data, Information.container.xSize, Information.container.ySize, Information.key); } else if (radioButton_Block_Different_Shape.Checked) { Methods.Block_Different_Shape.Block_Different_Shape block = new Methods.Block_Different_Shape.Block_Different_Shape(); General.Point[] selectedPoints = null; General.Point[] notSelectedPoints = null; General.Utils.getShapePoints(row, col, boxes, out selectedPoints, out notSelectedPoints); message_box.Text = block.Decoder(ref data, selectedPoints, notSelectedPoints, Information.container.xSize, Information.container.ySize, Information.key); } //} //catch (Exception msg) //{ // MessageBox.Show("Произошли проблемы при шифровании.\n " + msg.Message); // return; //} MessageBox.Show("Дешифрирование прошло успешно"); } }
private void getContainers(ref PreparedData data, ref Methods.Block_Different_Shape.Container[] containers, General.Point[] selectedPoints, General.Point[] NotSelectedPoints, int xSize, int ySize, int rowContainers, int colContainers, int limit, int startFrom = 0) { int index = 0; // индекс контейнера int yStart = 0; int xStart = 0; if (startFrom > 0) { yStart = startFrom / colContainers; xStart = startFrom % colContainers; } for (int y = yStart * ySize; y < ySize * rowContainers && index < limit; y += ySize) { for (int x = xStart * xSize; x < xSize * colContainers && index < limit; x += xSize) { containers[index] = new Methods.Block_Different_Shape.Container(ref data, selectedPoints, NotSelectedPoints, x, y, xSize, ySize); // берем текущие кооридинаты и координаты, смещенные относительно index++; } xStart = 0; } }
public void updateValue(bool value, bool block, ref PreparedData data) { Point[] points; if (block) points = this.points_NotChecked; else points = this.points_Checked; // случайным образом выбираем позицию в контейнере Random rnd = new Random(); int i = rnd.Next(points.Length); char[] colorBits = Convert.ToString(data.imgChanel[points[i].y][points[i].x], 2).ToCharArray(); // переводим текущую цветовую компоненту в 2й вид if (colorBits[colorBits.Length - 1] == '1') // если последний бит единица { colorBits[colorBits.Length - 1] = '0'; // записываем в объект 1 } else { colorBits[colorBits.Length - 1] = '1'; // записываем в объект 0 } data.imgChanel[points[i].y][points[i].x] = Convert.ToInt32(new string(colorBits), 2); // записываем обновленное значение цветовой компоненты в цветовом канале if(block) sumBits_NotChecked = value; // обновляем значение в объекте контейнера else sumBits_Checked = value; // обновляем значение в объекте контейнера }
// Нужно исправить, чтобы уменьшить количество кода и условий public static Bitmap setColorChanel(ref PreparedData data) { Bitmap img = new Bitmap(data.img); Color pixel; for (int i = 0; i < data.img.Height; i++) { for (int j = 0; j < data.img.Width; j++) { pixel = img.GetPixel(j, i); Color newPixel = setToChanel(pixel, data.imgChanel, i, j, Information.colorChanel); img.SetPixel(j, i, newPixel); // Here Can be implemented progress bar } } return img; throw new Exception("Недопустимая цветовая компонента. Возможные варианты - R, G, B"); }