Добавлен: 22.11.2023
Просмотров: 58
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
3 Общий алгоритм работы AES
Рисунок 3 - Общий алгоритм работы AES
Общий алгоритм работы AES представлен на рисунке 3. Число раундов Round определяется длиной ключа. На вход поступает открытый текст, на выходе имеется совокупность зашифрованных блоков (Ciphertext).
Код программы, разработанной исходя из общих определений и процедур, представлен в приложении Б.
4. Используемые математические операции
Все математические операции производятся в поле Галуа .
В процедурах AddRoyndKey и KeyExpansion в основе лежат операции сложения байт по модулю 2 (XOR).
В AddRoyndKey в сложении участвуют только текущий блок и ключ раунда, а в KeyExpansion в сложении участвуют результат SubWord(RotWord(temp)), предыдущий ключ раунда и Round Constant.
На языке C# для 256 битного ключа данный алгоритм (KeyExpansion) запишется следующим образом:
AKey = new byte[4, 60];ch = 0;(int i = 0; i < 4; i++)
{(int q = 0; q < 8; q++)
{[i, q] = key[ch];++;
}
}(int i = 8; i < 60; i++)
{[] temp = new byte[4];(int q = 0; q < 4; q++)
{[q] = AKey[q, i - 1];
}((i % 8) == 0)
{= SubWord(RotWord(temp), SBox);(int q = 0; q < 4; q++)
{[q] ^= RCon[q];
}
}if (i % 8 == 4)
{= SubWord(temp,SBox);
}(int q=0; q<4; q++)[q,i] = Convert.ToByte(AKey[q,i - 8] ^ temp[q]);
}
В процедурах SubBytes и MixColumn при умножении байтов используется неприводимый многочлен
Вычисление произведения М байтов {b1} на {b2} здесь выполняется согласно следующему алгоритму
В этом случае обратная величина байта равна:
Как уже было сказано выше, в процедуре SubBytes используется следующая формула умножения и сложения байт , где A - двоичная матрица 8х8, а b - 8-битный вектор, как показано на рисунке 4.
Рисунок 4 - Формула в преобразовании SubBytes.
Для умножения полубайтов (коды длиной 4 бита) используется неприводимый полином
Вычисление произведения М полубайтов {a} на {b} здесь выполняется следующим образом
M представляет собой полубайт d. Операцию умножения полубайтов {a} на {b} можно записать в матричном виде
В процедуре MixColumn общую формулу умножения можно представить в виде
В обратной процедуре InvMixColumn общая формула имеет вид
Заключение
В результате работы над данным проектом были освоены современные методы шифрования, а в частности Rijndael, написана программа, позволяющая шифровать текстовую информацию различными длинами ключей (128, 192, 256 бит).
Приобретенные навыки активно использовались для оценки эффективности и скорости работы других симметричных алгоритмов шифрования.
Все поставленные цели и задачи выполнены.
Для реализации поставленной задачи использовалась среда программирования Microsoft Visual Studio 2010. Программа реализована в виде Windows Forms Application на языке C#.
Рекомендации по развитию программы
В данной программной реализации каждый блок шифруется независимо от остальных, то есть используется простейший режим работы ELECTRONIC CODEBOOK (ECB), что упрощает криптоанализ полученного шифра. Поэтому рекомендуется реализовать остальные режимы работ алгоритма для повышения криптостойкости. Особенно важно реализовать поддержку русского языка. Также можно было бы сделать поддержку шифрования файлов различного формата.
Список используемых источников
1. С.Г. Баричев, В.В. Гончаров, Р.Е. Серов, Основы современной криптографии, 2-е издание, Москва, "Горячая линия - Телеком", 2002.
2. Осипенко Л. П., Васильченко А. А. Математические основы криптологии. Методические указания для выполнения курсовой работы. - Краснодар: Изд-во КубГТУ, 2009.
. Кнут Д. Искусство программирования. Т. 2. Получисленные алгоритмы. третье издание. М.: МЦНМО, 1999.
Приложение А
Рисунок 5 - Скриншот программы
Приложение Б
Листинг программы
using System;System.Collections.Generic;System.ComponentModel;System.Data;System.Drawing;System.Linq;System.Text;System.Windows.Forms;
CryptoAES
{partial class Form1 : Form
{Form1()
{();
}
//public static string[,] Tabl;static string ByteToHex(byte a)
{hex="";b = a / 16;c = a % 16;(b)
{0:+= '0';;1:+= '1';;2:+= '2';;3:+= '3';;4:+= '4';;5:+= '5';;6:+= '6';;7:+= '7';;8:+= '8';;9:+= '9';;10:+= 'A';;11:+= 'B';;12:+= 'C';;13:+= 'D';;14:+= 'E';;15:+= 'F';;
}(c)
{0:+= '0';;1:+= '1';;2:+= '2';;3:+= '3';;4:+= '4';;5:+= '5';;6:+= '6';;7:+= '7';;8:+= '8';;9:+= '9';;10:+= 'A';;11:+= 'B';;12:+= 'C';;13:+= 'D';;14:+= 'E';;15:+= 'F';;
}hex;
}static byte HexToByte(string hex)
{a=0;(hex[1])
{'0':= 0;;'1':= 1;;'2':= 2;;'3':= 3;;'4':= 4;;'5':= 5;;'6':= 6;;'7':= 7;;'8':= 8;;'9':= 9;;'A':= 10;;'B':= 11;;'C':= 12;;'D':= 13;;'E':= 14;;'F':= 15;;
}(hex[0])
{'0':+= 0;;'1':+= 16;;'2':+= 32;;'3':+= 48;;'4':+= 64;;'5':+= 80;;'6':+= 96;;'7':+= 112;;'8':+= 128;;'9':+= 144;;'A':+= 160;;'B':+= 176;;'C':+= 192;;'D':+= 208;;'E':+= 224;;'F':+= 240;;
}a;
}void button1_Click(object sender, EventArgs e)
{[] input;(richTextBox1.Text.Length%16==0)= new byte[richTextBox1.Text.Length];= new byte[((richTextBox1.Text.Length/16)+1)*16];(int i = 0; i < richTextBox1.Text.Length; i++)[i] = Convert.ToByte(richTextBox1.Text[i]);(int i = richTextBox1.Text.Length; i < input.Length; i++)[i] = 0;
//------------------------------------[] key = new byte[1];(textBox1.Text.Length <= 16)= new byte[16];(textBox1.Text.Length > 16 && textBox1.Text.Length <=24)= new byte[24];(textBox1.Text.Length > 24)= new byte[32];
(int i = 0; i < textBox1.Text.Length; i++)[i] = Convert.ToByte(textBox1.Text[i]);(int i = textBox1.Text.Length; i < key.Length; i++)[i] = 0;
//------------------------------------.Encrypt(ref input, key);
/*TablLeng.ColumnCount = 16;.RowCount = 16;(int q = 0; q <= 15; q++)
{.Columns[q].Width = 40;.Columns[q].Name = Convert.ToString(q);
}oi = 0;(int l = 0; l < 16; l++)
{(int q = 0; q < 16; q++)
{[q, l].Value = Tabl[q, l];++;
}
}*/txt="";[] HexTable = new string[256];(int i = 0; i < 256; i++)
{[i] = ByteToHex(Convert.ToByte(i));
}(int i = 0; i < input.Length; i++)
{+= HexTable[input[i]];
}.Text = txt;
}
void button2_Click(object sender, EventArgs e)
{[] input = new byte[richTextBox2.Text.Length/2];txt="";(int i = 0; i < richTextBox2.Text.Length; i+=2)
{=Convert.ToString(richTextBox2.Text[i])+Convert.ToString(richTextBox2.Text[i+1]);[i/2] = HexToByte(txt);
}
//------------------------------------[] key = new byte[1];(textBox1.Text.Length <= 16)= new byte[16];(textBox1.Text.Length > 16 && textBox1.Text.Length <= 24)= new byte[24];(textBox1.Text.Length > 24)= new byte[32];
(int i = 0; i < textBox1.Text.Length; i++)[i] = Convert.ToByte(textBox1.Text[i]);(int i = textBox1.Text.Length; i < key.Length; i++)[i] = 0;
//------------------------------------
.Decrypt(ref input, key);
/*TablLeng.ColumnCount = 16;.RowCount = 16;(int q = 0; q <= 15; q++)
{.Columns[q].Width = 40;.Columns[q].Name = Convert.ToString(q);
}oi = 0;(int l = 0; l < 16; l++)
{(int q = 0; q < 16; q++)
{[q, l].Value = Tabl[q, l];++;
}
}*/= "";(int i = 0; i < input.Length; i++)+= Convert.ToChar(input[i]);.Text = txt;
}
void textBox1_TextChanged(object sender, EventArgs e)
{(textBox1.Text.Length <= 16).Text = "- 128 бит";(textBox1.Text.Length > 16 && textBox1.Text.Length <= 24).Text = "- 192 бит";(textBox1.Text.Length > 24).Text = "- 256 бит";
}
}AES
{
#region Create S-Box or InvS-Boxstatic void Create_InvSBox(ref byte[] InvSBox)
{[] SBox = new byte[256];(int i = 0; i <= 255; i++)
{result = Convert.ToByte(i);(int q = 1; q < 7; q++)= AES.PolynomsMult(AES.PolynomsMult(result, result, 0x11b), Convert.ToByte(i), 0x11b);= AES.PolynomsMult(result, result, 0x11b);= AES.PolynomsMult(0x1f, result, 0x101);[i] = Convert.ToByte(result ^ 0x63);
}(int i = 0; i <= 255; i++)
{[SBox[i]] = Convert.ToByte(i);
}
}static void Create_SBox(ref byte[] SBox)
{(int i = 0; i <= 255; i++)
{result = Convert.ToByte(i);(int q = 1; q < 7; q++)= AES.PolynomsMult(AES.PolynomsMult(result, result, 0x11b), Convert.ToByte(i), 0x11b);= AES.PolynomsMult(result, result, 0x11b);= AES.PolynomsMult(0x1f, result, 0x101);[i] = Convert.ToByte(result ^ 0x63);
}
}
#endregion
#region Multiply Polynomsstatic byte PolynomsMult(byte a, byte b, ushort mod)
{mult = 0;temp = b;(a > 0)
{((a & 0x01) == 1) mult ^= temp;>>= 1;<<= 1;
}(byte i = 14; i >= 8; i--)((mult >> i) == 1) mult = Convert.ToUInt16(mult ^ (mod << (i - 8)));Convert.ToByte(mult);
}
#endregion
#region Key schedule
static byte[,] KeyExpansion(byte[] key, byte[] SBox)
{[] RCon= new byte[] { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };[,] AKey = new byte[4,60];(int i = 0; i < 60; i++ )
{(int q = 0; q < 4; q++)[q, i] = 0;
}(key.Length == 16)
{= new byte[4, 44];ch = 0;(int i = 0; i < 4; i++)
{(int q = 0; q < 4; q++)
{[i, q] = key[ch];++;
}
}(int i = 4; i < 44; i++)
{[] temp = new byte[4];(int q = 0; q < 4; q++)
{[q] = AKey[q, i - 1];
}((i % 4) == 0)
{= SubWord(RotWord(temp), SBox);[0] ^= RCon[(i / 4) - 1];
}(int q = 0; q < 4; q++)[q, i] = Convert.ToByte(AKey[q, i - 4] ^ temp[q]);
}
}(key.Length == 24)
{= new byte[4, 52];ch = 0;(int i = 0; i < 4; i++)
{(int q = 0; q < 6; q++)
{[i, q] = key[ch];++;
}
}(int i = 6; i < 52; i++)
{[] temp = new byte[4];(int q = 0; q < 4; q++)
{[q] = AKey[q, i - 1];
}((i % 6) == 0)
{= SubWord(RotWord(temp), SBox);(int q = 0; q < 4; q++)
{[q] ^= RCon[q];
}
}if (i % 6 == 3)
{= SubWord(temp, SBox);
}(int q = 0; q < 4; q++)[q, i] = Convert.ToByte(AKey[q, i - 6] ^ temp[q]);
}
}(key.Length == 32)
{= new byte[4, 60];ch = 0;(int i = 0; i < 4; i++)
{(int q = 0; q < 8; q++)
{[i, q] = key[ch];++;
}
}(int i = 8; i < 60; i++)
{[] temp = new byte[4];(int q = 0; q < 4; q++)
{[q] = AKey[q, i - 1];
}((i % 8) == 0)
{= SubWord(RotWord(temp), SBox);(int q = 0; q < 4; q++)
{[q] ^= RCon[q];
}
}if (i % 8 == 4)
{= SubWord(temp,SBox);
}(int q=0; q<4; q++)[q,i] = Convert.ToByte(AKey[q,i - 8] ^ temp[q]);
}
}AKey;
}
static byte[] SubWord(byte[] W, byte[] SBox)
{[] temp = new byte[4];(int i = 0; i < 4; i++)[i] = SBox[W[i]];temp;
}
static byte[] RotWord(byte[] W)
{[] temp = new byte[4];(int i = 0; i < 4; i++)[i] = W[(i + 1)%4];temp;
}
#endregion
#region Block_Encrypt or Block_Decryptstatic void Cipher(ref byte[,] state, byte[,] AKey, byte[] SBox, byte length)
{(ref state, AKey, 0);(int round = 1; round <= 9+length*2; round++)
{(ref state, SBox);(ref state);(ref state);(ref state, AKey, round*4);
}
(ref state,SBox);(ref state);(ref state, AKey, 40+length*8);
}static void InvCipher(ref byte[,] state, byte[,] AKey, byte[] InvSBox, byte length)
{(ref state, AKey, 40 + length * 8);(ref state);(ref state, InvSBox);(int round = 9 + length * 2; round >= 1; round--)
{(ref state, AKey, round * 4);(ref state);(ref state);(ref state, InvSBox);
}(ref state, AKey, 0);
}static void MixColumns(ref byte[,] state)
{[,] new_state = new byte[4, 4];(int c = 0; c < 4; c++)
{_state[0, c] = (byte)(PolynomsMult(2, state[0, c], 283) ^ PolynomsMult(3, state[1, c], 283) ^ state[2, c] ^ state[3, c]);_state[1, c] = (byte)(state[0, c] ^ PolynomsMult(2, state[1, c],283) ^ PolynomsMult(3, state[2, c], 283) ^ state[3, c]);_state[2, c] = (byte)(state[0, c] ^ state[1, c] ^ PolynomsMult(2, state[2, c],283) ^ PolynomsMult(3, state[3, c],283));_state[3, c] = (byte)(PolynomsMult(3, state[0, c],283) ^ state[1, c] ^ state[2, c] ^ PolynomsMult(2, state[3, c],283));
}= new_state;;
}static void InvMixColumns(ref byte[,] state)
{[,] new_state = new byte[4, 4];(int c = 0; c < 4; c++)
{_state[0, c] = (byte)(AES.PolynomsMult(14, state[0, c], 283) ^ AES.PolynomsMult(11, state[1, c], 283) ^ AES.PolynomsMult(13, state[2, c], 283) ^ AES.PolynomsMult(9, state[3, c], 283));_state[1, c] = (byte)(AES.PolynomsMult(9, state[0, c], 283) ^ AES.PolynomsMult(14, state[1, c], 283) ^ AES.PolynomsMult(11, state[2, c], 283) ^ AES.PolynomsMult(13, state[3, c], 283));_state[2, c] = (byte)(AES.PolynomsMult(13, state[0, c], 283) ^ AES.PolynomsMult(9, state[1, c], 283) ^ AES.PolynomsMult(14, state[2, c], 283) ^ AES.PolynomsMult(11, state[3, c], 283));_state[3, c] = (byte)(AES.PolynomsMult(11, state[0, c], 283) ^ AES.PolynomsMult(13, state[1, c], 283) ^ AES.PolynomsMult(9, state[2, c], 283) ^ AES.PolynomsMult(14, state[3, c], 283));
}= new_state;
}
static void ShiftRows(ref byte[,] state)
{[,] temp = new byte[4,4];(int i = 0; i < 4; i++)
{(int q = 0; q < 4; q++)[i, q] = state[i, (q + i) % 4];
}= temp;
}static void InvShiftRows(ref byte[,] state)
{[,] temp = new byte[4, 4];(int i = 0; i < 4; i++)
{(int q = 0; q < 4; q++)[i, q] = state[i, (q + 4 - i) % 4];
}= temp;
}
static void SubBytes(ref byte[,] state, byte[] SBox)
{(int i = 0; i < 4; i++)
{(int q = 0; q < 4; q++)
{[i, q] = SBox[state[i,q]];
}
}
}
static void AddRoundKey(ref byte[,] state, byte[,] AKey, int round)
{(int i = 0; i < 4; i++)
{(int q = 0; q < 4; q++)
{[i, q] ^= AKey[i,q+round];
}
}
}
#endregion
#region Encrypt or Decrypt text
static void Encrypt(ref byte[] array, byte[] key)
{[,] temp = new byte[4,4];[] SBox = new byte[256];_SBox(ref SBox);
/*Form1.Tabl = new string[16, 16];oi = 0;(int l = 0; l < 16; l++)
{(int q = 0; q < 16; q++)
{.Tabl[q, l] = Form1.ByteToHex(SBox[oi]);++;
}
}*/[,] AKey = KeyExpansion(key,SBox);len = (uint)(array.Length / 16);[] output = new byte[len*16];j = 0;(int i = 0; i < len; i++)
{(int k = 0; k < 4; k++)
{(int q = 0; q < 4; q++)
{[k, q] = array[16 * i + j];++;
}
}= 0;(ref temp, AKey, SBox, Convert.ToByte((key.Length - 16) / 8));(int k = 0; k < 4; k++)
{(int q = 0; q < 4; q++)
{[16 * i + j] = temp[k,q];++;
}
}= 0;
}= output;.Clear(AKey, 0, AKey.Length);
}
static void Decrypt(ref byte[] array, byte[] key)
{[,] temp = new byte[4,4];[] InvSBox = new byte[256];[] SBox = new byte[256];_SBox(ref SBox);_InvSBox(ref InvSBox);
/*Form1.Tabl = new string[16, 16];oi = 0;(int l = 0; l < 16; l++)
{(int q = 0; q < 16; q++)
{.Tabl[q, l] = Form1.ByteToHex(InvSBox[oi]);++;
}
}*/[,] AKey = KeyExpansion(key, SBox);len = (uint)(array.Length / 16);[] output = new byte[len * 16];j = 0;(int i = 0; i < len; i++)
{(int k = 0; k < 4; k++)
{(int q = 0; q < 4; q++)
{[k, q] = array[16 * i + j];++;
}
}= 0;(ref temp, AKey, InvSBox, Convert.ToByte((key.Length - 16) / 8));(int k = 0; k < 4; k++)
{(int q = 0; q < 4; q++)
{[16 * i + j] = temp[k, q];++;
}
}= 0;
}= output;.Clear(AKey, 0, AKey.Length);
}
#endregion
#region Teststatic void test()
{[,] state = new byte[4, 4];[0, 0] = 0x32;[0, 1] = 0x88;[0, 2] = 0x31;[0, 3] = 0xe0;[1, 0] = 0x43;[1, 1] = 0x5a;[1, 2] = 0x31;[1, 3] = 0x37;[2, 0] = 0xf6;[2, 1] = 0x30;[2, 2] = 0x98;[2, 3] = 0x07;[3, 0] = 0xa8;[3, 1] = 0x8d;[3, 2] = 0xa2;[3, 3] = 0x34;[] key = new byte[16];[0] = 0x2b;[1] = 0x28;[2] = 0xab;[3] = 0x09;[4] = 0x7e;[5] = 0xae;[6] = 0xf7;[7] = 0xcf;[8] = 0x15;[9] = 0xd2;[10] = 0x15;[11] = 0x4f;[12] = 0x16;[13] = 0xa6;[14] = 0x88;[15] = 0x3c;[] SBox = new byte[256];[] InvSBox = new byte[256];.Create_SBox(ref SBox);.Create_InvSBox(ref InvSBox);[,] AKey = AES.KeyExpansion(key, SBox);.Cipher(ref state, AKey, SBox, 0);.InvCipher(ref state, AKey, InvSBox, 0);
}
#endregion
}
}