Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.IO;
- namespace GrimoireTactics.Framework.Security
- {
- public static class Steganography
- {
- /// <summary>
- /// Encodes the message.
- /// </summary>
- /// <param name="bitmap">The bitmap.</param>
- /// <param name="password">The password.</param>
- /// <param name="message">The message.</param>
- public static void EncodeMessage(Bitmap bitmap, string password, string message)
- {
- Random rand = new Random(HashPassword(password));
- HashSet<string> usedPositions = new HashSet<string>();
- byte[] bytes = BitConverter.GetBytes(message.Length);
- for (int i = 0; i < bytes.Length; i++)
- {
- EncodeByte(bitmap, rand, bytes[i], usedPositions);
- }
- char[] chars = message.ToCharArray();
- for (int i = 0; i < chars.Length; i++)
- {
- EncodeByte(bitmap, rand, (byte)chars[i], usedPositions);
- }
- }
- /// <summary>
- /// Encodes the byte.
- /// </summary>
- /// <param name="bm">The bm.</param>
- /// <param name="rand">The rand.</param>
- /// <param name="value">The value.</param>
- /// <param name="usedPositions">The used positions.</param>
- private static void EncodeByte(Bitmap bm, Random rand, byte value, HashSet<string> usedPositions)
- {
- for (int i = 0; i < 8; i++)
- {
- int row, col, pix;
- PickPosition(bm, rand, usedPositions, out row, out col, out pix);
- Color clr = bm.GetPixel(row, col);
- byte r = clr.R;
- byte g = clr.G;
- byte b = clr.B;
- int bit = 0;
- if ((value & 1) == 1) bit = 1;
- switch (pix)
- {
- case 0:
- r = (byte)((r & 0xFE) | bit);
- break;
- case 1:
- g = (byte)((g & 0xFE) | bit);
- break;
- case 2:
- b = (byte)((b & 0xFE) | bit);
- break;
- }
- clr = Color.FromArgb(clr.A, r, g, b);
- bm.SetPixel(row, col, clr);
- value >>= 1;
- }
- }
- /// <summary>
- /// Picks the position.
- /// </summary>
- /// <param name="bm">The bm.</param>
- /// <param name="rand">The rand.</param>
- /// <param name="usedPositions">The used positions.</param>
- /// <param name="row">The row.</param>
- /// <param name="col">The col.</param>
- /// <param name="pix">The pix.</param>
- private static void PickPosition(Bitmap bm, Random rand, HashSet<string> usedPositions, out int row, out int col, out int pix)
- {
- for (;;)
- {
- row = rand.Next(0, bm.Width);
- col = rand.Next(0, bm.Height);
- pix = rand.Next(0, 3);
- string key =
- row + "/" +
- col + "/" +
- pix;
- if (!usedPositions.Contains(key))
- {
- usedPositions.Add(key);
- return;
- }
- }
- }
- /// <summary>
- /// Hashes the password.
- /// </summary>
- /// <param name="password">The password.</param>
- /// <returns></returns>
- private static int HashPassword(string password)
- {
- int shift1 = 3;
- int shift2 = 17;
- char[] chars = password.ToCharArray();
- int value = 0;
- for (int i = 1; i < password.Length; i++)
- {
- int chValue = chars[i];
- value ^= (chValue << shift1);
- value ^= (chValue << shift2);
- shift1 = (shift1 + 7) % 19;
- shift2 = (shift2 + 13) % 23;
- }
- return value;
- }
- /// <summary>
- /// Decodes the message.
- /// </summary>
- /// <param name="bm">The bm.</param>
- /// <param name="password">The password.</param>
- /// <returns></returns>
- /// <exception cref="InvalidDataException">Message length + len + is too big to make sense. Invalid password.</exception>
- public static string DecodeMessage(Bitmap bm, string password)
- {
- Random rand = new Random(HashPassword(password));
- HashSet<string> usedPositions = new HashSet<string>();
- int len = 0;
- byte[] bytes = BitConverter.GetBytes(len);
- for (int i = 0; i < bytes.Length; i++)
- {
- bytes[i] = DecodeByte(bm, rand, usedPositions);
- }
- len = BitConverter.ToInt32(bytes, 0);
- if (len > 10000)
- {
- throw new InvalidDataException(
- "Message length " + len +
- " is too big to make sense. Invalid password.");
- }
- char[] chars = new char[len];
- for (int i = 0; i < chars.Length; i++)
- {
- chars[i] = (char)DecodeByte(bm, rand, usedPositions);
- }
- return new string(chars);
- }
- /// <summary>
- /// Decodes the byte.
- /// </summary>
- /// <param name="bm">The bm.</param>
- /// <param name="rand">The rand.</param>
- /// <param name="usedPositions">The used positions.</param>
- /// <returns></returns>
- private static byte DecodeByte(Bitmap bm, Random rand, HashSet<string> usedPositions)
- {
- byte value = 0;
- byte valueMask = 1;
- for (int i = 0; i < 8; i++)
- {
- int row, col, pix;
- PickPosition(bm, rand, usedPositions, out row, out col, out pix);
- byte colorValue = 0;
- switch (pix)
- {
- case 0:
- colorValue = bm.GetPixel(row, col).R;
- break;
- case 1:
- colorValue = bm.GetPixel(row, col).G;
- break;
- case 2:
- colorValue = bm.GetPixel(row, col).B;
- break;
- }
- if ((colorValue & 1) == 1)
- {
- value = (byte)(value | valueMask);
- }
- valueMask <<= 1;
- }
- return value;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement