Esempio n. 1
0
        private void extractMesssageButton_Click(object sender, EventArgs e)
        {
            extractMessageButton.Text    = @"Extracting ...";
            extractMessageButton.Enabled = false;

            try {
                _message = _embedder.ExtractMessage(
                    _stegoImage,
                    stegoPasswordTextbox.Text,
                    bppComboBox.SelectedIndex + 1,
                    bitPlaneFirstRadio.Checked
                    );

                // Fill labels with data
                messageNameLabel.Text = _message.Name;
                messageSizeLabel.Text = Converter.BytesToHumanReadableString(_message.FullSizeInBytes);
            } catch (OverflowException ex) {
                MessageBox.Show(
                    @"The sysem caught an exception:"
                    + "\nType:        " + ex.GetType().Name
                    + "\nMessage:  " + ex.Message,
                    @"Critical error!",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                    );
            }

            // Check GUI components
            extractMessageButton.Text = @"Extract message";
            CheckEverything();
        }
Esempio n. 2
0
        /// <summary>
        /// Removes the message from the system.
        /// </summary>
        private void ClearMessage()
        {
            // Reset message object
            _message = null;

            // Remove data from labels
            messageNameLabel.Text = _defaultLabelValue;
            messageSizeLabel.Text = _defaultLabelValue;

            // Check GUI components
            CheckEverything();
        }
Esempio n. 3
0
        /// <summary>
        /// Rates a carrier image based on the amount of bits that have to be changed during the embedding process.
        /// The result is the exact amount of LSBs inside a carrier that stay the same
        /// during sequential embedding (without a stego password) in percent.
        /// </summary>
        /// <param name="carrier">The carrier image which is to be rated</param>
        /// <param name="message">The message which is to be hidden inside the carrier image</param>
        /// <exception cref="MessageNameTooBigException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="EncoderFallbackException"></exception>
        /// <returns>The suitability rating of the carrier for the specific message</returns>
        public float RateCarrier(StegoImage carrier, StegoMessage message)
        {
            // Get all necessary information of the carrier
            uint   capacityInBytes = CalculateCapacity(carrier, 1);                     // Only use LSBs
            uint   capacityInBits  = capacityInBytes * 8;
            string completeMessage = GenerateMessageBitPattern(message);

            // Directly return 0 if the message exceeds the capacity
            if (completeMessage.Length > capacityInBits)
            {
                return(0.00f);
            }

            // Collect all LSBs of the carrier
            //string carrierBits = collectCarrierBits(carrier, 1, bitPlanesFirst);
            string carrierLsbs = CollectCarrierLsbs(carrier);

            // Calculate the Hamming distance
            uint hammingDistance = 0;
            int  lsbCounter      = 0;

            foreach (char bit in completeMessage)
            {
                // If the index of an array reaches 2^31 it needs to be resetted
                // This is because an array is accessible only by int values
                if (lsbCounter == int.MaxValue)
                {
                    carrierLsbs = carrierLsbs.Substring(lsbCounter);
                    lsbCounter  = 0;
                }

                // Increase Hamming distance if message bit and carrier bit do not match
                if (!char.Equals(bit, carrierLsbs[lsbCounter]))
                {
                    hammingDistance++;
                }
                lsbCounter++;
            }

            double rating = (double)(capacityInBits - hammingDistance) / capacityInBits;

            return((float)Math.Round((rating * 100), 3));
        }
Esempio n. 4
0
        /// <summary>
        /// Generates a binary bit string from a <see cref="StegoMessage"/> object.
        /// At this, the message itself along with its name and its size is transformed to a series of 0s and 1s.
        /// </summary>
        /// <param name="message">The message whose bit string is to be generated</param>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="EncoderFallbackException"></exception>
        /// <exception cref="MessageNameTooBigException"></exception>
        /// <returns>The bit string that represents the message</returns>
        public string GenerateMessageBitPattern(StegoMessage message)
        {
            // Extract data from the message object
            string messageName = message.Name;

            byte[] payload     = message.Payload;
            long   payloadSize = message.PayloadSizeInBits;

            string payloadNameBinary = EncodeMessageName(messageName, 64);
            string payloadSizeBinary = Converter.DecimalToBinary(payloadSize, 24);
            string payloadBinary     = Converter.ByteArrayToBinary(payload);

            // Generate complete message
            StringBuilder sb = new StringBuilder();

            sb.Append(payloadNameBinary);
            sb.Append(payloadSizeBinary);
            sb.Append(payloadBinary);

            return(sb.ToString());
        }
Esempio n. 5
0
        /// <summary>
        /// Invokes the <see cref="FileManager"/> to load a message from a specified path.
        /// </summary>
        /// <param name="path">Preferably the absolute path of a message file</param>
        private void LoadMessage(string path)
        {
            //  Do nothing if the file does not exist
            if (!File.Exists(path))
            {
                return;
            }

            // Generate message object
            _message = new StegoMessage(
                Path.GetFileName(path),
                _fm.ReadMessageFile(path)
                );

            // Fill labels with data
            messageNameLabel.Text = _message.Name;
            messageSizeLabel.Text = Converter.BytesToHumanReadableString(_message.FullSizeInBytes);

            // Check GUI components
            CheckEverything();
        }
Esempio n. 6
0
        /// <summary>
        /// Hides a <see cref="StegoMessage"/> object inside a
        /// <see cref="StegoImage"/> object.
        /// </summary>
        /// <param name="carrierImage">The carrier image which is to be used to hide the message</param>
        /// <param name="message">The message which is to be hidden inside the carrier image</param>
        /// <param name="stegoPassword">The password which is to be used to hide the message (Randomized Hide and Seek)</param>
        /// <param name="bitPlanes">The amount of bit planes that are to be used to hide the message</param>
        /// <param name="bitPlanesFirst">true for bit planes first-mode and false for pixels first-mode</param>
        /// <exception cref="MessageNameTooBigException"></exception>
        /// <exception cref="MessageTooBigException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="FormatException"></exception>
        /// <exception cref="EncoderFallbackException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="System.Reflection.TargetInvocationException"></exception>
        /// <exception cref="Exception"></exception>
        /// <returns>The stego image containing the hidden message</returns>
        public StegoImage HideMessage(
            StegoImage carrierImage,
            StegoMessage message,
            string stegoPassword,
            int bitPlanes,
            bool bitPlanesFirst)
        {
            // Check if a password is set
            bool passwordSet = !(stegoPassword.Equals(""));

            // Generate stego image (Pass by reference)
            StegoImage stegoImage = new StegoImage(
                new Bitmap(
                    carrierImage.Image
                    ),
                carrierImage.Name,
                carrierImage.SizeInBytes
                );

            // Rename the stego image
            stegoImage.Name = "stegged_" + Path.GetFileNameWithoutExtension(stegoImage.Name) + ".png";

            // Base variable declaration
            int  carrierWidth     = carrierImage.Image.Width;
            int  carrierHeight    = carrierImage.Image.Height;
            uint maxCarrierPixels = (uint)(carrierWidth * carrierHeight);
            uint pixelDistance    = 1;

            // Get the binary string of a message object and its length
            string completeMessage       = GenerateMessageBitPattern(message);
            uint   completeMessageLength = (uint)completeMessage.Length;

            // Throw exception if the message is too big
            uint carrierCapacity = CalculateCapacity(carrierImage, bitPlanes);

            if (completeMessageLength > carrierCapacity * 8)
            {
                throw new MessageTooBigException();
            }

            // If a stego password is specified, scramble the image and change the pixelDistance value
            if (passwordSet)
            {
                // Transform the password into a value defining the distance between pixels
                byte[] passwordBytes = Encoding.UTF8.GetBytes(stegoPassword);
                passwordBytes = Hasher.HashSha256(passwordBytes);
                pixelDistance = (uint)((ulong)BitConverter.ToInt64(passwordBytes, 0) % maxCarrierPixels);

                // Scramble image
                stegoImage.Image = ImageScrambler.ScrambleOne(stegoImage.Image);
                stegoImage.Image = ImageScrambler.ScrambleThree(stegoImage.Image);
                stegoImage.Image = ImageScrambler.ScrambleTwo(stegoImage.Image);
            }

            // Hiding variables
            int  messageBitCounter = 0;                 // Counter iterating over all message bits
            uint currentPixel      = 0;                 // Variable storing the currently considered pixel
            uint restClassCounter  = 0;                 // Counter iterating over all rest classes
            byte bitPlaneSelector  = 0;                 // Variable used to select which bit plane is used for embedding

            // While there is something left to hide
            while (messageBitCounter < completeMessageLength)
            {
                var currentPixelXValue = (int)(currentPixel % carrierWidth);                    // x coordinate of current pixel
                var currentPixelYValue = (int)(currentPixel / carrierWidth);                    // y coordinate of current pixel

                // Get current pixel
                var pixel = stegoImage.Image.GetPixel(currentPixelXValue, currentPixelYValue);                  // Pixel object used to generate the new color

                // Define which of the three LSBs of a pixel should be used
                byte color;
                switch (messageBitCounter % 3)
                {
                case 0:
                    color = SetBit(pixel.R, completeMessage[messageBitCounter].ToString(), bitPlaneSelector);
                    stegoImage.Image.SetPixel(currentPixelXValue, currentPixelYValue, Color.FromArgb(color, pixel.G, pixel.B));
                    break;

                case 1:
                    color = SetBit(pixel.G, completeMessage[messageBitCounter].ToString(), bitPlaneSelector);
                    stegoImage.Image.SetPixel(currentPixelXValue, currentPixelYValue, Color.FromArgb(pixel.R, color, pixel.B));
                    break;

                case 2:
                    color = SetBit(pixel.B, completeMessage[messageBitCounter].ToString(), bitPlaneSelector);
                    stegoImage.Image.SetPixel(currentPixelXValue, currentPixelYValue, Color.FromArgb(pixel.R, pixel.G, color));

                    // If the whole bit plane should be filled before a pixel should be reused
                    if (bitPlanesFirst)
                    {
                        // Go to the next pixel
                        currentPixel += pixelDistance;

                        // If the pixel exceeds the maximum amount of pixels
                        // go to the next rest class
                        if (currentPixel >= maxCarrierPixels)
                        {
                            currentPixel = ++restClassCounter;

                            // If all rest classes are exhausted,
                            // begin at pixel 0 again but go to the next bit plane
                            if (restClassCounter >= pixelDistance)
                            {
                                currentPixel     = 0;
                                restClassCounter = 0;
                                bitPlaneSelector++;
                            }
                        }

                        // If a pixel should be used in full before the next pixel is chosen
                    }
                    else
                    {
                        // Go to the next bit plane
                        bitPlaneSelector++;

                        // If all allowed bits of a single pixel are used
                        // go to the next pixel
                        if (bitPlaneSelector >= bitPlanes)
                        {
                            currentPixel    += pixelDistance;
                            bitPlaneSelector = 0;

                            // If the pixel exceeds the maximum amount of pixels
                            // go to the next rest class
                            if (currentPixel >= maxCarrierPixels)
                            {
                                currentPixel = ++restClassCounter;
                            }
                        }         // if
                    }             // else
                    break;
                }                 // switch
                messageBitCounter++;
            }

            // If a password has been used, scramble back the image
            if (passwordSet)
            {
                stegoImage.Image = ImageScrambler.ScrambleOne(ImageScrambler.ScrambleThree(ImageScrambler.ScrambleTwo(stegoImage.Image)));
            }
            return(stegoImage);
        }
Esempio n. 7
0
        /// <summary>
        /// Extracts a <see cref="StegoMessage"/> object from a
        /// <see cref="StegoImage"/> object.
        /// </summary>
        /// <param name="stegoImage">The stego image which hides the message</param>
        /// <param name="stegoPassword">The password used to hide the message (Randomized Hide and Seek)</param>
        /// <param name="bitPlanes">The amount of bit planes that have been used to hide the message</param>
        /// <param name="bitPlanesFirst">true for bit planes first-mode and false for pixels first-mode</param>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="System.Reflection.TargetInvocationException"></exception>
        /// <exception cref="FormatException"></exception>
        /// <exception cref="OverflowException"></exception>
        /// <exception cref="DecoderFallbackException"></exception>
        /// <exception cref="Exception"></exception>
        /// <returns>The message that has been hidden inside the stego image</returns>
        public StegoMessage ExtractMessage(StegoImage stegoImage,
                                           string stegoPassword,
                                           int bitPlanes,
                                           bool bitPlanesFirst)
        {
            // Generate new stego image object to omit f*****g pass by reference
            Bitmap stegoImageCopy = new Bitmap(stegoImage.Image);

            // Set extraction option
            bool passwordSet = !(stegoPassword.Equals(""));

            // Base variable declaration
            StringBuilder messageNameBuilder = new StringBuilder();
            StringBuilder payloadSizeBuilder = new StringBuilder();
            StringBuilder payloadBuilder     = new StringBuilder();
            int           stegoWidth         = stegoImageCopy.Width;
            int           stegoHeight        = stegoImageCopy.Height;
            uint          maxStegoPixels     = (uint)(stegoWidth * stegoHeight);
            uint          pixelDistance      = 1;

            // If a stego password is specified
            if (passwordSet)
            {
                // Transform the password into a value defining the distance between pixels
                byte[] passwordBytes = Encoding.UTF8.GetBytes(stegoPassword);
                passwordBytes = Hasher.HashSha256(passwordBytes);
                pixelDistance = (uint)((ulong)BitConverter.ToInt64(passwordBytes, 0) % maxStegoPixels);

                // Scramble image
                stegoImageCopy = ImageScrambler.ScrambleOne(stegoImageCopy);
                stegoImageCopy = ImageScrambler.ScrambleThree(stegoImageCopy);
                stegoImageCopy = ImageScrambler.ScrambleTwo(stegoImageCopy);
            }

            // Variables for LSB extraction
            int   messageBitCounter = 0;            // Counter iterating over all message bits
            Color pixel;                            // Pixel object used to generate the new color
            int   currentPixelXValue;               // x coordinate of current pixel
            int   currentPixelYValue;               // y coordinate of current pixel
            uint  currentPixel     = 0;             // Variable storing the currently considered pixel
            uint  restClassCounter = 0;             // Counter iterating over all rest classes
            byte  bitPlaneSelector = 0;             // Variable used to select which bit plane is used for embedding

            // Extract the first 512 bits which encode the message's name
            while (messageBitCounter < 512)
            {
                // Get current pixel
                currentPixelXValue = (int)currentPixel % stegoWidth;
                currentPixelYValue = (int)currentPixel / stegoWidth;
                pixel = stegoImageCopy.GetPixel(currentPixelXValue, currentPixelYValue);

                switch (messageBitCounter % 3)
                {
                case 0:
                    messageNameBuilder.Append(GetBit(pixel.R, bitPlaneSelector));
                    break;

                case 1:
                    messageNameBuilder.Append(GetBit(pixel.G, bitPlaneSelector));
                    break;

                case 2:
                    messageNameBuilder.Append(GetBit(pixel.B, bitPlaneSelector));

                    // If the whole bit plane should be filled before a pixel should be reused
                    if (bitPlanesFirst)
                    {
                        // Go to the next pixel
                        currentPixel += pixelDistance;

                        // If the pixel exceeds the maximum amount of pixels
                        // go to the next rest class
                        if (currentPixel >= maxStegoPixels)
                        {
                            currentPixel = ++restClassCounter;

                            // If all rest classes are exhausted,
                            // begin at pixel 0 again but go to the next bit plane
                            if (restClassCounter >= pixelDistance)
                            {
                                currentPixel     = 0;
                                restClassCounter = 0;
                                bitPlaneSelector++;
                            }
                        }

                        // If a pixel should be used in full before the next pixel is chosen
                    }
                    else
                    {
                        // Go to the next bit plane
                        bitPlaneSelector++;

                        // If all allowed bits of a single pixel are used
                        // go to the next pixel
                        if (bitPlaneSelector >= bitPlanes)
                        {
                            currentPixel    += pixelDistance;
                            bitPlaneSelector = 0;

                            // If the pixel exceeds the maximum amount of pixels
                            // go to the next rest class
                            if (currentPixel >= maxStegoPixels)
                            {
                                currentPixel = ++restClassCounter;
                            }
                        }         // if
                    }             // else
                    break;
                }                 // switch
                messageBitCounter++;
            }

            // Compose the message's name
            string messageNameString = messageNameBuilder.ToString();
            string messageName       = Converter.BinaryToString(messageNameString).Replace("\0", "");

            // Extract the next 24 bits which encode the message's payload size
            while (messageBitCounter < 536)
            {
                // Get current pixel
                currentPixelXValue = (int)currentPixel % stegoWidth;
                currentPixelYValue = (int)currentPixel / stegoWidth;
                pixel = stegoImageCopy.GetPixel(currentPixelXValue, currentPixelYValue);

                switch (messageBitCounter % 3)
                {
                case 0:
                    payloadSizeBuilder.Append(GetBit(pixel.R, bitPlaneSelector));
                    break;

                case 1:
                    payloadSizeBuilder.Append(GetBit(pixel.G, bitPlaneSelector));
                    break;

                case 2:
                    payloadSizeBuilder.Append(GetBit(pixel.B, bitPlaneSelector));

                    // If the whole bit plane should be filled before a pixel should be reused
                    if (bitPlanesFirst)
                    {
                        // Go to the next pixel
                        currentPixel += pixelDistance;

                        // If the pixel exceeds the maximum amount of pixels
                        // go to the next rest class
                        if (currentPixel >= maxStegoPixels)
                        {
                            currentPixel = ++restClassCounter;

                            // If all rest classes are exhausted,
                            // begin at pixel 0 again but go to the next bit plane
                            if (restClassCounter >= pixelDistance)
                            {
                                currentPixel     = 0;
                                restClassCounter = 0;
                                bitPlaneSelector++;
                            }
                        }

                        // If a pixel should be used in full before the next pixel is chosen
                    }
                    else
                    {
                        // Go to the next bit plane
                        bitPlaneSelector++;

                        // If all allowed bits of a single pixel are used
                        // go to the next pixel
                        if (bitPlaneSelector >= bitPlanes)
                        {
                            currentPixel    += pixelDistance;
                            bitPlaneSelector = 0;

                            // If the pixel exceeds the maximum amount of pixels
                            // go to the next rest class
                            if (currentPixel >= maxStegoPixels)
                            {
                                currentPixel = ++restClassCounter;
                            }
                        }         // if
                    }             // else
                    break;
                }                 // switch
                messageBitCounter++;
            }

            // Compose the payloads's size
            string payloadSizeString = payloadSizeBuilder.ToString();
            uint   payloadSize       = Converter.BinaryToUint(payloadSizeString);

            // Extract the payload
            while (messageBitCounter < payloadSize + 536)
            {
                // Get current pixel
                currentPixelXValue = (int)currentPixel % stegoWidth;
                currentPixelYValue = (int)currentPixel / stegoWidth;
                pixel = stegoImageCopy.GetPixel(currentPixelXValue, currentPixelYValue);

                switch (messageBitCounter % 3)
                {
                case 0:
                    payloadBuilder.Append(GetBit(pixel.R, bitPlaneSelector));
                    break;

                case 1:
                    payloadBuilder.Append(GetBit(pixel.G, bitPlaneSelector));
                    break;

                case 2:
                    payloadBuilder.Append(GetBit(pixel.B, bitPlaneSelector));

                    // If the whole bit plane should be filled before a pixel should be reused
                    if (bitPlanesFirst)
                    {
                        // Go to the next pixel
                        currentPixel += pixelDistance;

                        // If the pixel exceeds the maximum amount of pixels
                        // go to the next rest class
                        if (currentPixel >= maxStegoPixels)
                        {
                            currentPixel = ++restClassCounter;

                            // If all rest classes are exhausted,
                            // begin at pixel 0 again but go to the next bit plane
                            if (restClassCounter >= pixelDistance)
                            {
                                currentPixel     = 0;
                                restClassCounter = 0;
                                bitPlaneSelector++;
                            }
                        }

                        // If a pixel should be used in full before the next pixel is chosen
                    }
                    else
                    {
                        // Go to the next bit plane
                        bitPlaneSelector++;

                        // If all allowed bits of a single pixel are used
                        // go to the next pixel
                        if (bitPlaneSelector >= bitPlanes)
                        {
                            currentPixel    += pixelDistance;
                            bitPlaneSelector = 0;

                            // If the pixel exceeds the maximum amount of pixels
                            // go to the next rest class
                            if (currentPixel >= maxStegoPixels)
                            {
                                currentPixel = ++restClassCounter;
                            }
                        }         // if
                    }             // else
                    break;
                }                 // switch
                messageBitCounter++;
            }

            // Compose the message object
            string payloadString = payloadBuilder.ToString();

            byte[]       payload = payloadString.ConvertBitstringToByteArray();
            StegoMessage message = new StegoMessage(messageName, payload);

            return(message);
        }