Алгоритм шифрования ГОСТ 28147-89. Режим простой замены - C#
Формулировка задачи:
Реализовывал алгоритм по wiki. Но что то не то получилось.Вот код:
Возможно я неверно понял алгоритм?
P.S. Если возникли не понимания в коде спрашивайте разъясню: что делает, почему и как
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace InformationSecurity1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
byte[,] Sblocks = {
{4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3},
{14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9},
{5, 8,1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11},
{7, 13, 10, 1, 0, 8 ,9 ,15, 14, 4, 6, 12, 11, 2, 5, 3},
{6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2},
{4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14},
{13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12},
{1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12}
};//Блок замен
List<byte[]> lsKey = new List<byte[]>();//Список подключей размером в 4 байта
List<byte[]> lsData = new List<byte[]>();//Список блоков открытого текста размером 8 байт
byte[] fillingArrayData(List<byte[]> list)
{
byte[] array = new byte[list.Count * 8];
int index = 0;
for (int i = 0; i < list.Count; ++i)
{
for (int j = 0; j < list[i].Length; ++j)
{
array[index] = list[i][j];
index++;
}
}
return array;
}
void fillingListData(string data)
{
byte[] temp = Encoding.Default.GetBytes(data);
int count = 0;
byte[] k = new byte[8];
for (int i = 0; i < temp.Length; ++i)
{
if (count != 8)
{
k[count] = temp[i];
count++;
}
else
{
lsData.Add(k);
--i;
count = 0;
k = new byte[8];
}
}
lsData.Add(k);
}
void fillingListKey(string key)
{
byte[] temp = Encoding.Default.GetBytes(key);
int count = 0;
byte[] k = new byte[4];
for (int i = 0; i < temp.Length; ++i)
{
if (count != 4)
{
k[count] = temp[i];
count++;
}
else
{
lsKey.Add(k);
--i;
count = 0;
k = new byte[4];
}
}
lsKey.Add(k);
}
int lengthKey(string key)
{
byte[] temp = Encoding.Default.GetBytes(key);
return temp.Length;
}
byte[] retL(byte[] data)
{
byte[] temp = new byte[4];
for (int i = 0; i < 4; ++i)
{
temp[i] = data[i];
}
return temp;
}//Возвращает старшую часть 8 байтового блока данных
byte[] retR(byte[] data)
{
byte[] temp = new byte[4];
int count = 4;
for (int i = 0; i < 4; ++i)
{
temp[i] = data[count];
count++;
}
return temp;
}//Возвращает младшую часть 8 байтового блока данных
byte[] mod2_32(byte[] a, byte[] b)
{
byte[] res;
UInt32 A = BitConverter.ToUInt32(a, 0);
UInt32 B = BitConverter.ToUInt32(b, 0);
A += B;
res = BitConverter.GetBytes(A);
return res;
}// Сложение по модулю 2^32
UInt32 func(byte[] R, byte[] Ki)
{
byte[] s8 = new byte[8];
int count = 0;
byte[] s = mod2_32(R, Ki);
for (int j = 0; j < s.Length; ++j)
{
byte e = (byte)((s[j] >> 4));
s8[count] = e;
++count;
byte f = (byte)((s[j] & 15));
s8[count] = f;
++count;
}
for (int i = 0; i < 8; ++i)
{
s8[i] = Sblocks[i, (int)s8[i]];
}
UInt32 result = BitConverter.ToUInt32(s8, 0);
result = result << 11;
return result;
}
byte[] encode(byte[] data)
{
byte[] L = retL(data);
byte[] R = retR(data);
byte[] block = new byte[4];
UInt32 temp = 0;
int index = 0;
bool flag = true;
for (int i = 0; i < 32; ++i)
{
if (i == 24)
{
flag = false;
}
if (flag)
{
if (index == 8)
{
index = 0;
}
temp = func(R, lsKey[index]);
index++;
}
else
{
if (index == 8)
{
--index;
}
temp = func(R, lsKey[index]);
--index;
}
temp = BitConverter.ToUInt32(L, 0) ^ temp;
L = R;
R = BitConverter.GetBytes(temp);
}
byte[] result = new byte[8];
index = 0;
for (int i = 0; i < 8; ++i)
{
if (i < 4)
{
result[i] = L[i];
}
else
{
result[i] = R[index];
index++;
}
}
return result;
}
byte[] decode(byte[] data)
{
byte[] L = retL(data);
byte[] R = retR(data);
byte[] block = new byte[4];
UInt64 temp = 0;
int index = 0;
bool flag = false;
for (int i = 0; i < 32; ++i)
{
if (i == 24)
{
flag = true;
}
if (flag)
{
if (index == 8)
{
index = 0;
}
temp = func(R, lsKey[index]);
index++;
}
else
{
if (index == 0)
{
index=7;
}
temp = func(R, lsKey[index]); //index выходит за рамки равен -1
--index;
}
temp = BitConverter.ToUInt32(L, 0) ^ temp;
L = R;
R = BitConverter.GetBytes(temp);
//++index;
}
byte[] result = new byte[8];
index = 0;
for (int i = 0; i < 8; ++i)
{
if (i < 4)
{
result[i] = L[i];
}
else
{
result[i] = R[index];
index++;
}
}
return result;
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
if (lengthKey(textBox2.Text) < 32)
{
textBox2.BackColor = Color.Red;
button1.Enabled = false;
}
else
{
if (lengthKey(textBox2.Text) > 32)
{
textBox2.BackColor = Color.Red;
button1.Enabled = false;
}
else
{
textBox2.BackColor = Color.Green;
button1.Enabled = true;
textBox2.MaxLength = textBox2.TextLength;
}
}
}
private void button1_Click(object sender, EventArgs e)
{
fillingListKey(textBox2.Text);
fillingListData(textBox1.Text);
// byte[] temp = Encoding.Default.GetBytes(textBox1.Text);
byte[] t = new byte[8];
List<byte[]> result = new List<byte[]>();
for (int i = 0; i < lsData.Count; ++i)
{
t = encode(lsData[i]);
result.Add(t);
}
byte[] res = fillingArrayData(result);
textBox3.Text = Encoding.Default.GetString(res);
}
private void button2_Click(object sender, EventArgs e)
{
fillingListKey(textBox2.Text);
fillingListData(textBox3.Text);
byte[] temp = Encoding.Default.GetBytes(textBox3.Text);
byte[] t = new byte[8];
List<byte[]> result = new List<byte[]>();
for (int i = 0; i < lsData.Count; ++i)
{
t = decode(lsData[i]);
result.Add(t);
}
byte[] res = fillingArrayData(result);
textBox4.Text = Encoding.Default.GetString(res);
}
}
}Решение задачи: «Алгоритм шифрования ГОСТ 28147-89. Режим простой замены»
textual
Листинг программы
byte[] bKey = {
0x33, 0x20, 0x6d, 0x54,
0x32, 0x6c, 0x65, 0x68,
0x20, 0x65, 0x73, 0x69,
0x62, 0x6e, 0x73, 0x73,
0x79, 0x67, 0x61, 0x20,
0x74, 0x74, 0x67, 0x69,
0x65, 0x68, 0x65, 0x73,
0x73, 0x3d, 0x2C, 0x20
};