Advertisement
mrAnderson33

AES

Jun 14th, 2018
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.88 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3.  
  4. using Cryptography.Algorithms.Symmetric.Helpers;
  5.  
  6. namespace Cryptography.Algorithms.Symmetric
  7. {
  8.  
  9.     public sealed class AES
  10.     {
  11.  
  12.         #region Static fields
  13.  
  14.         private static byte[] _sBox;
  15.         private static byte[] _inversedSBox;
  16.         private static byte[,] _multiplyByModulo283Remainders;
  17.         private static byte[] _cPolynomial;
  18.         private static byte[] _inversedCPolynomial;
  19.         private static byte[] _rCon;
  20.  
  21.         #endregion
  22.  
  23.         #region Fields
  24.  
  25.         private byte[] _key;
  26.         private byte[][] _roundKeys;
  27.         private byte _roundsCount;
  28.  
  29.         #endregion
  30.  
  31.         #region Constructors
  32.  
  33.         static AES()
  34.         {
  35.             MultiplyByModulo283Remainders = CreateMultiplyByModulo283Remainders();
  36.             SBox = CreateSBox();
  37.             InversedSBox = CreateInversedSBox(SBox);
  38.             CPolynomial = new byte[] { 2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2 };
  39.             InversedCPolynomial = new byte[] { 14, 11, 13, 9, 9, 14, 11, 13, 13, 9, 14, 11, 11, 13, 9, 14 };
  40.             RCon = new byte[] { 1, 2, 4, 8, 16, 32, 64, 128, 27, 54 };
  41.         }
  42.  
  43.         public AES()
  44.         {
  45.             Key = new byte[16];
  46.         }
  47.  
  48.         #endregion
  49.  
  50.         #region Static properties
  51.  
  52.         private static byte[,] MultiplyByModulo283Remainders
  53.         {
  54.             get => _multiplyByModulo283Remainders ?? throw new ArgumentNullException("MultiplyByModulo283Remainders");
  55.  
  56.             set => _multiplyByModulo283Remainders = value;
  57.         }
  58.  
  59.         private static byte[] SBox
  60.         {
  61.             get => _sBox ?? throw new ArgumentNullException("SBox");
  62.  
  63.             set => _sBox = value;
  64.         }
  65.  
  66.         private static byte[] InversedSBox
  67.         {
  68.             get => _inversedSBox ?? throw new ArgumentNullException("InversedSBox");
  69.  
  70.             set => _inversedSBox = value;
  71.         }
  72.  
  73.         private static byte[] CPolynomial
  74.         {
  75.             get => _cPolynomial ?? throw new ArgumentNullException("CPolynomial");
  76.  
  77.             set => _cPolynomial = value;
  78.         }
  79.  
  80.         private static byte[] InversedCPolynomial
  81.         {
  82.             get => _inversedCPolynomial ?? throw new ArgumentNullException("InversedCPolynomial");
  83.  
  84.             set => _inversedCPolynomial = value;
  85.         }
  86.  
  87.         private static byte[] RCon
  88.         {
  89.             get => _rCon ?? throw new ArgumentNullException("RCon");
  90.  
  91.             set => _rCon = value;
  92.         }
  93.  
  94.         #endregion
  95.  
  96.         #region Properties
  97.  
  98.         public byte[] Key
  99.         {
  100.             private get => _key;
  101.  
  102.             set
  103.             {
  104.                 if (value == null)
  105.                 {
  106.                     throw new ArgumentNullException("Key");
  107.                 }
  108.                 if (!(new[] { 16, 24, 32 }).Contains(value.Length))
  109.                 {
  110.                     throw new ArgumentException("Key");
  111.                 }
  112.                 _key = (byte[])value.Clone();
  113.                 CreateRoundKeys();
  114.             }
  115.         }
  116.  
  117.         private byte[][] RoundKeys
  118.         {
  119.             get => _roundKeys ?? throw new ArgumentNullException("RoundKeys");
  120.  
  121.             set => _roundKeys = value;
  122.         }
  123.  
  124.         private byte RoundsCount
  125.         {
  126.             get => _roundsCount;
  127.  
  128.             set => _roundsCount = value;
  129.         }
  130.  
  131.         #endregion
  132.  
  133.         #region Remainders, SBox, InversedSBox creation methods
  134.  
  135.         private static byte[,] CreateMultiplyByModulo283Remainders()
  136.         {
  137.             var result = new byte[256, 256];
  138.             var GF256 = new GF256();
  139.             foreach (byte i in Enumerable.Range(byte.MinValue, 256))
  140.             {
  141.                 foreach (byte j in Enumerable.Range(i, 256 - i))
  142.                 {
  143.                     result[i, j] = (byte)GF256.MultiplyByModulo(i, j, 283);
  144.                     if (i != j)
  145.                     {
  146.                         result[j, i] = result[i, j];
  147.                     }
  148.                 }
  149.             }
  150.             return result;
  151.         }
  152.  
  153.         private static byte[] CreateSBox()
  154.         {
  155.             var result = new byte[256];
  156.             var GF256 = new GF256();
  157.             foreach (byte i in Enumerable.Range(byte.MinValue, 256))
  158.             {
  159.                 foreach (byte j in Enumerable.Range(byte.MinValue, 256))
  160.                 {
  161.                     if (MultiplyByModulo283Remainders[i, j] == 1)
  162.                     {
  163.                         var MultiplicativeInversed = j;
  164.                         for (var k = 0; k < 5; k++)
  165.                         {
  166.                             result[i] ^= MultiplicativeInversed;
  167.                             MultiplicativeInversed = (byte)((MultiplicativeInversed << 1) | (MultiplicativeInversed >> 7));
  168.                         }
  169.                         result[i] ^= 99;
  170.                         break;
  171.                     }
  172.                 }
  173.             };
  174.             result[0] = 99;
  175.             return result;
  176.         }
  177.  
  178.         private static byte[] CreateInversedSBox(byte[] sBox)
  179.         {
  180.             var result = new byte[256];
  181.             foreach (byte i in Enumerable.Range(byte.MinValue, 256))
  182.             {
  183.                 foreach (byte j in Enumerable.Range(byte.MinValue, 256))
  184.                 {
  185.                     if (sBox[j] == i)
  186.                     {
  187.                         result[i] = j;
  188.                         break;
  189.                     }
  190.                 }
  191.             }
  192.             return result;
  193.         }
  194.  
  195.         #endregion
  196.  
  197.         #region Methods
  198.  
  199.         public byte[] Encrypt(byte[] dataBytes)
  200.         {
  201.             if (dataBytes.Length != 16)
  202.             {
  203.                 throw new ArgumentException("dataBytes");
  204.             }
  205.             var state = (byte[])dataBytes.Clone();
  206.             AddRoundKey(state, Key);
  207.             for (var round = 0; round < RoundsCount - 1; round++)
  208.             {
  209.                 SubBytes(state);
  210.                 ShiftRows(state);
  211.                 MixColumns(state);
  212.                 AddRoundKey(state, RoundKeys[round]);
  213.             }
  214.             SubBytes(state);
  215.             ShiftRows(state);
  216.             AddRoundKey(state, RoundKeys[RoundsCount - 1]);
  217.             return state;
  218.         }
  219.  
  220.         public byte[] Decrypt(byte[] dataBytes)
  221.         {
  222.             if (dataBytes.Length != 16)
  223.             {
  224.                 throw new ArgumentException("dataBytes");
  225.             }
  226.             var state = (byte[])dataBytes.Clone();
  227.             AddRoundKey(state, RoundKeys.Last());
  228.             for (var round = 0; round < RoundsCount - 1; round++)
  229.             {
  230.                 InversedShiftRows(state);
  231.                 InversedSubBytes(state);
  232.                 AddRoundKey(state, RoundKeys[RoundsCount - round - 2]);
  233.                 InversedMixColumns(state);
  234.             }
  235.             InversedShiftRows(state);
  236.             InversedSubBytes(state);
  237.             AddRoundKey(state, Key);
  238.             return state;
  239.         }
  240.  
  241.         #endregion
  242.  
  243.         #region Secondary methods
  244.  
  245.         private void CreateRoundKeys()
  246.         {
  247.             RoundsCount = (byte)(Key.Length / 4 + 6);
  248.             RoundKeys = new byte[RoundsCount][];
  249.             for (var i = 0; i < RoundsCount; i++)
  250.             {
  251.                 RoundKeys[i] = new byte[Key.Length];
  252.                 if (i == 0)
  253.                 {
  254.                     byte[] W = new byte[4]
  255.                     {
  256.                         Key[Key.Length - 3],
  257.                         Key[Key.Length - 2],
  258.                         Key[Key.Length - 1],
  259.                         Key[Key.Length - 4]
  260.                     };
  261.                     for (var j = 0; j < 4; j++)
  262.                     {
  263.                         RoundKeys[i][j] = (byte)(Key[j] ^ SBox[W[j]] ^ (j == 0 ? RCon[i % RCon.Length] : 0));
  264.                     }
  265.                     for (var j = 0; j < 3; j++)
  266.                     {
  267.                         for (var k = 0; k < 4; k++)
  268.                         {
  269.                             RoundKeys[i][(j + 1) * 4 + k] = (byte)(Key[(j + 1) * 4 + k] ^ RoundKeys[i][j * 4 + k]);
  270.                         }
  271.                     }
  272.                 }
  273.                 else
  274.                 {
  275.                     var W = new byte[4]
  276.                     {
  277.                         RoundKeys[i - 1][Key.Length - 3],
  278.                         RoundKeys[i - 1][Key.Length - 2],
  279.                         RoundKeys[i - 1][Key.Length - 1],
  280.                         RoundKeys[i - 1][Key.Length - 4]
  281.                     };
  282.                     for (var j = 0; j < 4; j++)
  283.                     {
  284.                         RoundKeys[i][j] = (byte)(RoundKeys[i - 1][j] ^ SBox[W[j]] ^ (j == 0 ? RCon[i % RCon.Length] : 0));
  285.                     }
  286.                     for (var j = 0; j < 3; j++)
  287.                     {
  288.                         for (var k = 0; k < 4; k++)
  289.                         {
  290.                             RoundKeys[i][(j + 1) * 4 + k] = (byte)(RoundKeys[i - 1][(j + 1) * 4 + k] ^ RoundKeys[i][j * 4 + k]);
  291.                         }
  292.                     }
  293.                 }
  294.             }
  295.         }
  296.  
  297.         private void AddRoundKey(byte[] state, byte[] roundkey)
  298.         {
  299.             for (var i = 0; i < state.Length; i++)
  300.             {
  301.                 state[i] ^= roundkey[i];
  302.             }
  303.         }
  304.  
  305.         #region Secondary encryption functions
  306.  
  307.         private void SubBytes(byte[] state)
  308.         {
  309.             for (var i = 0; i < state.Length; i++)
  310.             {
  311.                 state[i] = SBox[state[i]];
  312.             }
  313.         }
  314.  
  315.         private void ShiftRows(byte[] state)
  316.         {
  317.             var temporary = state[1];
  318.             state[1] = state[5];
  319.             state[5] = state[9];
  320.             state[9] = state[13];
  321.             state[13] = temporary;
  322.             temporary = state[2];
  323.             state[2] = state[10];
  324.             state[10] = temporary;
  325.             temporary = state[6];
  326.             state[6] = state[14];
  327.             state[14] = temporary;
  328.             temporary = state[3];
  329.             state[3] = state[15];
  330.             state[15] = state[11];
  331.             state[11] = state[7];
  332.             state[7] = temporary;
  333.         }
  334.  
  335.         private void MixColumns(byte[] state)
  336.         {
  337.             var temporaryState = new byte[state.Length];
  338.             for (var i = 0; i < 4; i++)
  339.             {
  340.                 for (var j = 0; j < 4; j++)
  341.                 {
  342.                     temporaryState[i * 4 + j] = MultiplyByModulo283Remainders[CPolynomial[j * 4], state[i * 4]];
  343.                     temporaryState[i * 4 + j] ^= MultiplyByModulo283Remainders[CPolynomial[j * 4 + 1], state[i * 4 + 1]];
  344.                     temporaryState[i * 4 + j] ^= MultiplyByModulo283Remainders[CPolynomial[j * 4 + 2], state[i * 4 + 2]];
  345.                     temporaryState[i * 4 + j] ^= MultiplyByModulo283Remainders[CPolynomial[j * 4 + 3], state[i * 4 + 3]];
  346.                 }
  347.             }
  348.             for (var i = 0; i < state.Length; i++)
  349.             {
  350.                 state[i] = temporaryState[i];
  351.             }
  352.         }
  353.  
  354.         #endregion
  355.  
  356.         #region Secondary decryption functions
  357.  
  358.         private void InversedSubBytes(byte[] state)
  359.         {
  360.             for (var i = 0; i < state.Length; i++)
  361.             {
  362.                 state[i] = InversedSBox[state[i]];
  363.             }
  364.         }
  365.  
  366.         private void InversedShiftRows(byte[] state)
  367.         {
  368.             var temporary = state[1];
  369.             state[1] = state[13];
  370.             state[13] = state[9];
  371.             state[9] = state[5];
  372.             state[5] = temporary;
  373.             temporary = state[2];
  374.             state[2] = state[10];
  375.             state[10] = temporary;
  376.             temporary = state[6];
  377.             state[6] = state[14];
  378.             state[14] = temporary;
  379.             temporary = state[3];
  380.             state[3] = state[7];
  381.             state[7] = state[11];
  382.             state[11] = state[15];
  383.             state[15] = temporary;
  384.         }
  385.  
  386.         private void InversedMixColumns(byte[] state)
  387.         {
  388.             var temporaryState = new byte[16];
  389.             for (var i = 0; i < 4; i++)
  390.             {
  391.                 for (var j = 0; j < 4; j++)
  392.                 {
  393.                     temporaryState[i * 4 + j] = MultiplyByModulo283Remainders[InversedCPolynomial[j * 4], state[i * 4]];
  394.                     temporaryState[i * 4 + j] ^= MultiplyByModulo283Remainders[InversedCPolynomial[j * 4 + 1], state[i * 4 + 1]];
  395.                     temporaryState[i * 4 + j] ^= MultiplyByModulo283Remainders[InversedCPolynomial[j * 4 + 2], state[i * 4 + 2]];
  396.                     temporaryState[i * 4 + j] ^= MultiplyByModulo283Remainders[InversedCPolynomial[j * 4 + 3], state[i * 4 + 3]];
  397.                 }
  398.             }
  399.             for (var i = 0; i < state.Length; i++)
  400.             {
  401.                 state[i] = temporaryState[i];
  402.             }
  403.         }
  404.  
  405.         #endregion
  406.  
  407.         #endregion
  408.  
  409.     }
  410.  
  411. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement