kan3k1k3n
@kan3k1k3n

Как правильно расшифровать данные из изображения в c#?

вот код для шифрования текста в изображение и последующюю дешифровку:
using System;
using System.Drawing;
using AForge;
using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Imaging.ColorReduction;
using AForge.Math;

class SteganographyAForge
{
    const int bitsPerChannel = 1;

    public static void EncryptTextToImage(string inputImagePath, string outputImagePath, string textToEncrypt)
    {
        Bitmap bitmap = (Bitmap)System.Drawing.Image.FromFile(inputImagePath);
        int textLength = textToEncrypt.Length;
        int charIndex = 0;

        for (int y = 0; y < bitmap.Height; y++)
        {
            for (int x = 0; x < bitmap.Width; x++)
            {
                Color originalColor = bitmap.GetPixel(x, y);

                if (charIndex < textLength)
                {
                    char charToEncode = textToEncrypt[charIndex++];

                    byte[] colorBytes = new byte[] { originalColor.R, originalColor.G, originalColor.B };
                    for (int i = 0; i < 3; i++)
                    {
                        int bitIndex = (bitsPerChannel * i); 
                        if (bitIndex < 8)
                        {
                            colorBytes[i] = (byte)((colorBytes[i] & ~1) | ((charToEncode >> bitIndex) & 1));
                        }
                    }
                    bitmap.SetPixel(x, y, Color.FromArgb(colorBytes[0], colorBytes[1], colorBytes[2]));
                }
                else
                {
                    break;
                }
            }
        }

        bitmap.Save(outputImagePath);
    }

    public static string DecryptTextFromImage(string inputImagePath, int textLength)
    {
        Bitmap bitmap = (Bitmap)System.Drawing.Image.FromFile(inputImagePath);
        string encryptedText = string.Empty;

        for (int y = 0; y < bitmap.Height; y++)
        {
            for (int x = 0; x < bitmap.Width; x++)
            {
                Color encodedColor = bitmap.GetPixel(x, y);
                byte charCode = 0;
                for (int i = 0; i < 3; i++)
                {
                    int bitIndex = (bitsPerChannel * i);
                    if (bitIndex < 8)
                    {
                        charCode |= (byte)((encodedColor.ToArgb() >> bitIndex) & 1);
                        if (bitIndex <= 2)
                        {
                            charCode <<= bitsPerChannel;
                        }
                    }
                }
                encryptedText += (char)charCode;
                if (encryptedText.Length == textLength)
                {
                    break;
                }
            }
            if (encryptedText.Length == textLength)
            {
                break;
            }
        }

        return encryptedText;
    }

    static void Main()
    {
        string inputImagePath = "C:\\Users\\motor\\OneDrive\\Изображения\\дрейн.jpg";
        string outputImagePath = "C:\\Users\\motor\\OneDrive\\Изображения\\newimage.jpg";
        string textToEncrypt = "Hello, secret message!";

        EncryptTextToImage(inputImagePath, outputImagePath, textToEncrypt);

        string decryptedText = DecryptTextFromImage(outputImagePath, textToEncrypt.Length);
        Console.WriteLine("Decrypted Text: " + decryptedText);
    }
}

вот так выглядит строка вывода:
Decrypted Text: ♫♫♫♠♠♠♫♠♠

☻☻♀☻♀♦♀☻♫

как мне исправить ошибку кодировки и декодировки текста?

p.s. буду рад, если предложите другие рабочие реализации стеганографии
  • Вопрос задан
  • 128 просмотров
Пригласить эксперта
Ответы на вопрос 1
AshBlade
@AshBlade Куратор тега C#
Просто хочу быть счастливым
Нашел много недочетов, но главная ошибка здесь:
char charToEncode = textToEncrypt[charIndex++];

                    byte[] colorBytes = new byte[] { originalColor.R, originalColor.G, originalColor.B };
                    for (int i = 0; i < 3; i++)
                    {
                        int bitIndex = (bitsPerChannel * i); 
                        if (bitIndex < 8)
                        {
                            colorBytes[i] = (byte)((colorBytes[i] & ~1) | ((charToEncode >> bitIndex) & 1));
                        }
                    }


Я так полагаю, что символы сообщения кодируются в LSB, но проблема здесь в том, что кодируются только последние 3 бита - остальное (8 - 3 = 5 битов теряются). Т.е. сообщение восстановить никак

+ Сам цикл выглядит очень странно.
Главный вопрос - зачем?
Параметризовать алгоритм стеганографии подобным образом не очень оптимально, т.к. каждый создается с использованием тех или иных фич, который строго захардкожены и используют особенности конкретного формата. Цикл + проверка здесь только ухудшают понимание кода (ИМХО)
Убери этот цикл, т.к. во-первых, станет понятнее, во-вторых, условие внутри при этой константе всегда выполняется.

Теперь про декодирование:
for (int i = 0; i < 3; i++)
                {
                    int bitIndex = (bitsPerChannel * i);
                    if (bitIndex < 8)
                    {
                        charCode |= (byte)((encodedColor.ToArgb() >> bitIndex) & 1);
                        if (bitIndex <= 2)
                        {
                            charCode <<= bitsPerChannel;
                        }
                    }
                }

Вот этот участок тоже неправильно работает, т.к. ты кодируешь символы в LSB, а читаешь последние 3 бита - из них только 1 бит содержит данные.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы