Программа стеганографии дает странные результаты - PullRequest
2 голосов
/ 01 июля 2011

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

import java.awt.*;
class HideMessage {
    public void encodeMessage(Picture stegoObject, int[] binaryArray) {
        Pixel pixelTarget = new Pixel(stegoObject, 0, 0);
        Pixel[] pixelArray = stegoObject.getPixels();
        Color pixelColor = null;
        int redValue = 0;

        for (int x = 0; x < binaryArray.length; x++) {
            redValue = binaryArray[x];
            pixelTarget = pixelArray[x];
            pixelTarget.setRed(redValue);
        }
        pixelTarget = pixelArray[binaryArray.length];
        pixelTarget.setRed(255);
        System.out.println("FinishedPic");
        stegoObject.write("SecretMessage.bmp");
        stegoObject.explore();

    }
    public void decodeMessage(Picture decodepic) {

        int redValue = 0;
        Pixel targetPixel = null;
        Color pixelColor = null;
        int sum = 0;

        for (int x = 0; redValue < 2; x++) {
                //inside nested loop to traverse the image from left to right
                for (int count = 1; count < 9; count++) {

                    targetPixel =
                        decodepic.getPixel(count + (8 * x), 0);
                    //gets the x,y coordinate of the target pixel
                    pixelColor = targetPixel.getColor();
                    //gets the color of the target pixel

                    redValue = pixelColor.getRed();

                    if (redValue == 1) {
                        if (count == 1) {
                            sum = sum + 128;
                        }
                        if (count == 2) {
                            sum = sum + 64;
                        }
                        if (count == 3) {
                            sum = sum + 32;
                        }
                        if (count == 4) {
                            sum = sum + 16;
                        }
                        if (count == 5) {
                            sum = sum + 8;
                        }
                        if (count == 6) {
                            sum = sum + 4;
                        }
                        if (count == 7) {
                            sum = sum + 2;
                        }
                        if (count == 8) {
                            sum = sum + 1;
                        }
                    }

                    System.out.println(sum);

                }
                System.out.println((char)sum);
                sum = 0;
            }   //end of the inner for loop
    }
}

public class HideMessageTester {
    public static void main(String[] args) {
        int[] bitArray =
            { 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1,
           0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0,
           1, 1, 1, 1, 0, 0, 1 };
        //int[] bitArray =
        { 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1,
                0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1,
                1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0,
                0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1,
                0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
                0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1,
                0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1,
                0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
                0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1,
                0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1,
                1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0,
                0, 1, 0, 0, 0, 0, 1};

        Picture stegoObject = new Picture("Earth.bmp");

        HideMessage stego = new HideMessage();

        stego.encodeMessage(stegoObject, bitArray);
        Picture decodeObject = new Picture("SecretMessage.bmp");
        System.out.println("Now Decoding");
        stego.decodeMessage(decodeObject);
    }
}

1 Ответ

2 голосов
/ 01 июля 2011

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

Picture stegoObject = new Picture("Earth.bmp");
HideMessage stego = new HideMessage();
stego.encodeMessage(stegoObject, bitArray);
Picture decodeObject = new Picture("SecretMessage.bmp");
System.out.println("Now Decoding");
stego.decodeMessage(decodeObject);

Я был очень удивлен, увидев SecretMessage.bmp;было совсем не очевидно, что вы пытаетесь декодировать объект, который вы только что создали.Конечно, после прочтения метода encodeMessage() было достаточно легко определить, откуда он пришел, но я думаю, что этот процесс был бы проще:

/* encode */
Picture pic_to_steg = new Picture("foo.bmp");
HideMessage stego = new HideMessage();
Picture secret = stego.encodeMessage(pic_to_steg, bitArray);
secret.write("SecretMessage.bmp");

/* decode */
Picture pic_with_message = new Picture("SecretMessage.bmp");
int[] hidden = stego.decodeMessage(pic_with_message);

/* output `hidden` and compare against `bitArray` */

Другими словами: оставьте файл ввода / вывода полностью доосновной поток программы.Возможно, ваши подпрограммы будут вызываться с сетевого сервера в будущем, и изображения никогда не будут сохранены на диск.Эта модификация будет намного проще, если подпрограммы работают на Picture s и возвращают исправленные Picture s и int[].

Можете ли вы проверить свой метод encodeMessage() изолированно?Возможно, посмотрите на различия в том, что он делает между входным файлом и выходным файлом.Этот раздел выглядит хлопотно:

public void encodeMessage(Picture stegoObject, int[] binaryArray) {
    Pixel pixelTarget = new Pixel(stegoObject, 0, 0);
    Pixel[] pixelArray = stegoObject.getPixels();
    Color pixelColor = null;
    int redValue = 0;

    for (int x = 0; x < binaryArray.length; x++) {
        redValue = binaryArray[x];
        pixelTarget = pixelArray[x];
        pixelTarget.setRed(redValue);
    }
    pixelTarget = pixelArray[binaryArray.length];
    pixelTarget.setRed(255);

Действительно ли pixelArray ссылка на изображение, которое можно обновить с помощью простого назначения?Я действительно ожидал бы, что дизайн будет больше похож на этот псевдокод:

pixel p = image.getPixel(x, y);
p.setred(binaryArray[i]);
image.setPixel(x, y, p);

Декодирование имеет несколько странных циклов:

    for (int x = 0; redValue < 2; x++) {
            //inside nested loop to traverse the image from left to right
            for (int count = 1; count < 9; count++) {

Этот цикл может работать точно так, как вы его разработали, но при первом чтении кажется очень неправильным: вы начинаете с x=0, вы увеличиваете x каждый раз в цикле, но вы используете redValue < 2 в качестве правила завершения цикла.

Я бы предпочел, чтобы цикл был написан так:

int x = 0;
while (redValue < 2) {
    /* stuff */
    x++;
}

(Он не идентичен; x все еще действует вне цикла, что может быть опасно. Однако ядумаю, это гораздо яснее.)

Есть случаи, когда условие завершения цикла for не связано с предложениями установки или приращения - по моему опыту, они очень редко.

В этом случае это похоже на ошибку;условие redValue < 2 является инвариантом цикла, но внутренний цикл предполагает, что это произойдет только с пикселями, кратными 8, что является предположением, которое не применяется в методе encodeMessage().

Попытка вычисленияцелочисленное значение из ваших redValue s, когда вы читаете их, без необходимости усложняет вашу процедуру декодирования.Я предлагаю удалить внутренний цикл и вернуть массив точно так же, как массив, переданный в подпрограмму encodeMessage().Это будет (а) легче (б) легче отлаживать (в) легче тестировать (г) в тысячу раз легче обрабатывать записи битовых массивов, которые не делятся поровну на 8.

Затем пишите second метод, который преобразует вывод битового массива в сумму, или символы ASCII, или символы EBCDIC, или параметры ключа RSA, или что бы то ни было, что кодируется.Не пытайтесь делать слишком много сразу.Написание отдельного метода для декодирования массива битов будет (а) легче (б) легче отлаживать (в) легче тестировать (г) в тысячу раз легче обрабатывать произвольные выходные изменения.

Надеюсь, эти подсказкипомощь.

...