Advertisement
Krythic

Steganography

Jun 9th, 2016
313
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.74 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.IO;
  5.  
  6. namespace GrimoireTactics.Framework.Security
  7. {
  8.     public static class Steganography
  9.     {
  10.         /// <summary>
  11.         /// Encodes the message.
  12.         /// </summary>
  13.         /// <param name="bitmap">The bitmap.</param>
  14.         /// <param name="password">The password.</param>
  15.         /// <param name="message">The message.</param>
  16.         public static void EncodeMessage(Bitmap bitmap, string password, string message)
  17.         {
  18.             Random rand = new Random(HashPassword(password));
  19.             HashSet<string> usedPositions = new HashSet<string>();
  20.             byte[] bytes = BitConverter.GetBytes(message.Length);
  21.             for (int i = 0; i < bytes.Length; i++)
  22.             {
  23.                 EncodeByte(bitmap, rand, bytes[i], usedPositions);
  24.             }
  25.             char[] chars = message.ToCharArray();
  26.             for (int i = 0; i < chars.Length; i++)
  27.             {
  28.                 EncodeByte(bitmap, rand, (byte)chars[i], usedPositions);
  29.             }
  30.         }
  31.  
  32.         /// <summary>
  33.         /// Encodes the byte.
  34.         /// </summary>
  35.         /// <param name="bm">The bm.</param>
  36.         /// <param name="rand">The rand.</param>
  37.         /// <param name="value">The value.</param>
  38.         /// <param name="usedPositions">The used positions.</param>
  39.         private static void EncodeByte(Bitmap bm, Random rand, byte value, HashSet<string> usedPositions)
  40.         {
  41.             for (int i = 0; i < 8; i++)
  42.             {
  43.                 int row, col, pix;
  44.                 PickPosition(bm, rand, usedPositions, out row, out col, out pix);
  45.                 Color clr = bm.GetPixel(row, col);
  46.                 byte r = clr.R;
  47.                 byte g = clr.G;
  48.                 byte b = clr.B;
  49.                 int bit = 0;
  50.                 if ((value & 1) == 1) bit = 1;
  51.                 switch (pix)
  52.                 {
  53.                     case 0:
  54.                         r = (byte)((r & 0xFE) | bit);
  55.                         break;
  56.                     case 1:
  57.                         g = (byte)((g & 0xFE) | bit);
  58.                         break;
  59.                     case 2:
  60.                         b = (byte)((b & 0xFE) | bit);
  61.                         break;
  62.                 }
  63.                 clr = Color.FromArgb(clr.A, r, g, b);
  64.                 bm.SetPixel(row, col, clr);
  65.                 value >>= 1;
  66.             }
  67.         }
  68.  
  69.         /// <summary>
  70.         /// Picks the position.
  71.         /// </summary>
  72.         /// <param name="bm">The bm.</param>
  73.         /// <param name="rand">The rand.</param>
  74.         /// <param name="usedPositions">The used positions.</param>
  75.         /// <param name="row">The row.</param>
  76.         /// <param name="col">The col.</param>
  77.         /// <param name="pix">The pix.</param>
  78.         private static void PickPosition(Bitmap bm, Random rand, HashSet<string> usedPositions, out int row, out int col, out int pix)
  79.         {
  80.             for (;;)
  81.             {
  82.                 row = rand.Next(0, bm.Width);
  83.                 col = rand.Next(0, bm.Height);
  84.                 pix = rand.Next(0, 3);
  85.                 string key =
  86.                     row + "/" +
  87.                     col + "/" +
  88.                     pix;
  89.                 if (!usedPositions.Contains(key))
  90.                 {
  91.                     usedPositions.Add(key);
  92.                     return;
  93.                 }
  94.             }
  95.         }
  96.  
  97.         /// <summary>
  98.         /// Hashes the password.
  99.         /// </summary>
  100.         /// <param name="password">The password.</param>
  101.         /// <returns></returns>
  102.         private static int HashPassword(string password)
  103.         {
  104.             int shift1 = 3;
  105.             int shift2 = 17;
  106.             char[] chars = password.ToCharArray();
  107.             int value = 0;
  108.             for (int i = 1; i < password.Length; i++)
  109.             {
  110.                 int chValue = chars[i];
  111.                 value ^= (chValue << shift1);
  112.                 value ^= (chValue << shift2);
  113.                 shift1 = (shift1 + 7) % 19;
  114.                 shift2 = (shift2 + 13) % 23;
  115.             }
  116.             return value;
  117.         }
  118.  
  119.         /// <summary>
  120.         /// Decodes the message.
  121.         /// </summary>
  122.         /// <param name="bm">The bm.</param>
  123.         /// <param name="password">The password.</param>
  124.         /// <returns></returns>
  125.         /// <exception cref="InvalidDataException">Message length  + len + is too big to make sense. Invalid password.</exception>
  126.         public static string DecodeMessage(Bitmap bm, string password)
  127.         {
  128.             Random rand = new Random(HashPassword(password));
  129.             HashSet<string> usedPositions = new HashSet<string>();
  130.             int len = 0;
  131.             byte[] bytes = BitConverter.GetBytes(len);
  132.             for (int i = 0; i < bytes.Length; i++)
  133.             {
  134.                 bytes[i] = DecodeByte(bm, rand, usedPositions);
  135.             }
  136.             len = BitConverter.ToInt32(bytes, 0);
  137.             if (len > 10000)
  138.             {
  139.                 throw new InvalidDataException(
  140.                     "Message length " + len +
  141.                     " is too big to make sense. Invalid password.");
  142.             }
  143.             char[] chars = new char[len];
  144.             for (int i = 0; i < chars.Length; i++)
  145.             {
  146.                 chars[i] = (char)DecodeByte(bm, rand, usedPositions);
  147.             }
  148.             return new string(chars);
  149.         }
  150.  
  151.         /// <summary>
  152.         /// Decodes the byte.
  153.         /// </summary>
  154.         /// <param name="bm">The bm.</param>
  155.         /// <param name="rand">The rand.</param>
  156.         /// <param name="usedPositions">The used positions.</param>
  157.         /// <returns></returns>
  158.         private static byte DecodeByte(Bitmap bm, Random rand, HashSet<string> usedPositions)
  159.         {
  160.             byte value = 0;
  161.             byte valueMask = 1;
  162.             for (int i = 0; i < 8; i++)
  163.             {
  164.                 int row, col, pix;
  165.                 PickPosition(bm, rand, usedPositions, out row, out col, out pix);
  166.                 byte colorValue = 0;
  167.                 switch (pix)
  168.                 {
  169.                     case 0:
  170.                         colorValue = bm.GetPixel(row, col).R;
  171.                         break;
  172.                     case 1:
  173.                         colorValue = bm.GetPixel(row, col).G;
  174.                         break;
  175.                     case 2:
  176.                         colorValue = bm.GetPixel(row, col).B;
  177.                         break;
  178.                 }
  179.                 if ((colorValue & 1) == 1)
  180.                 {
  181.                     value = (byte)(value | valueMask);
  182.                 }
  183.                 valueMask <<= 1;
  184.             }
  185.             return value;
  186.         }
  187.     }
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement