МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
З В І Т
до лабораторної роботи №4
з навчальної дисципліни: «Криптографія і стеганографія»
Львів – 2013
Завдання
Скласти блок-схему алгоритму та програму мовою C# для реалізації шифру RSA в межах символів таблиці ASCII.
Короткі теоретичні відомості
Генерування ключів. Вибирають два досить великі прості числа p і q. Для їх добутку n=pq значення функції Ейлера дорівнює φ(n)=(p-1)(q-1) = n-p-q+1. Далі випадковим чином вибирають елемент e, що не перевищує значення φ(n) і взаємно простий з ним. Для eза алгоритмом Евкліда знаходять елемент d, обернений до e, такий, що d<φ(n) і:
ed= 1(mod φ(n)).
Як результат покладають: відкритий ключ e,n. Таємний ключ: d. Шифрування відбувається блоками. Для цього повідомлення записують у цифровій формі і розбивають на блоки так, що кожен блок позначає число, яке не перевищує n.
Алгоритм шифрування E у системі RSA полягає у піднесенні блока M до степеня e. В результаті отримується блок криптотексту C=E(M).
Алгоритм дешофрування D блоку криптотексту C полягає у піднесенні C до степеня d. Блок–схема шифру
Етап шифрування
Етап розшифрування
Лістинг програми
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
namespace Lab1__AutoKey_
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
FileStream fs = null;
OpenFileDialog ofd = new OpenFileDialog();
ofd.InitialDirectory = "c:\\";
ofd.Filter = "txt (*.txt)|*.txt|All files (*.*)|*.*";
ofd.FilterIndex = 1;
ofd.RestoreDirectory = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
fs = new FileStream(ofd.FileName, FileMode.Open);
}
catch (FileNotFoundException ex)
{
MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
fs.Close();
textBox_input.Text = File.ReadAllText(ofd.FileName, Encoding.ASCII);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
ArrayList all = new ArrayList();
// пошук НСД
public double NSDil(double a, double b)
{
double bp;
int q;
q = 1;
for (int i = 1; ; i++)
{
if (b > 0)
{
bp = b;
b = a % bp;
q = (int)(a / bp);
all.Add(q);
a = bp;
}
else
break;
}
return a;
}
//пошук оберненого числа, розширений Евкліда
public double ReverseNum(double a, double b)
{
double u, un, up, v, vn, vp;
up = 1;
u = 0;
vp = 0;
v = 1;
vn = 0;
if (NSDil(a, b) != 1)
return 0;
else
{
double[] q = new double[all.Count];
for (int i = 0; i < all.Count; i++)
q[i] = Convert.ToDouble(all[i]);
for (int k = 0; k < q.Length - 1; k++)
{
un = up - q[k] * u;
vn = vp - q[k] * v;
up = u;
u = un;
vp = v;
v = vn;
}
return vn;
}
}
// бінарний метод
public double PowerUpBin(double num, double e, double n)
{
double rezult;
int ex;
rezult = 1;
ex = (int)e;
while (ex > 0)
{
if ((ex & 1) == 1)
rezult = (rezult * num) % n;
ex >>= 1;
num = (num * num) % n;
}
return rezult;
}
public string[] ConvertCharsToStringOfDigits(char[] a, int enordecr)
{
int[] digits = new int[a.Length];
string[] str_from_digit = new string[a.Length];
if (enordecr == 0)
{
for (int i = 0; i < a.Length; i++)
{
digits[i] = (int)a[i];
if (digits[i] < 10)
{
str_from_digit[i] = "00" + digits[i];
}
else if (digits[i] < 100 && digits[i] > 9)
{
str_from_digit[i] = "0" + digits[i];
}
else
str_from_digit[i] = digits[i].ToString();
}
}
else if (enordecr == 1)
{
for (int i = 0; i < a.Length; i++)
{
digits[i] = (int)a[i];
if (digits[i] < 10)
{
str_from_digit[i] = "0" + digits[i];
}
else
str_from_digit[i] = digits[i].ToString();
}
}
return str_from_digit;
}
// поділ на частини
public double[] DivideByParts(char[] a, int leng, int num)
{
string part;
int k = 0;
double[] digit_parts = new double[num];
for (int i = 0; i < a.Length; )
{
part = a[i].ToString();
for (int j = 0; j < leng - 1; j++)
{
if (i == a.Length - 1)
break;
part = string.Concat(part, a[i + 1]);
i++;
}
i++;
digit_parts[k] = Convert.ToDouble(part);
k++;
}
return digit_parts;
}
public string ConvertDigitsToString(double[] a)
{
string text;
char[] encr_text_chars = new char[a.Length];
for (int i = 0; i < a.Length; i++)
{
encr_text_chars[i] = (char)a[i];
}
text = new string(encr_text_chars);
return text;
}
private void saveOutputToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
saveFileDialog1.FilterIndex = 1;
saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
StreamWriter myStream = new StreamWriter(saveFileDialog1.FileName, false, Encoding.ASCII);
myStream.Write(textBox_output.Text);
myStream.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void cleanAllFieldsToolStripMenuItem_Click(object sender, EventArgs e)
{
textBox_input.Text = "";
textBox_p.Text = "";
textBox_q.Text = "";
textBox_output.Text = "";
textBox_e.Text = "";
textBox_n.Text = "";
textBox_d.Text = "";
}
}
}
Метод, який здійснює шифрування тексту
private void encryptToolStripMenuItem_Click(object sender, EventArgs e)
{
double p, qu, n,tn,en,d;
p = Convert.ToDouble(textBox_p.Text);
qu = Convert.ToDouble(textBox_q.Text);
n = p * qu;
tn = n - p - qu + 1;
Random rand = new Random();
en = rand.Next(0, (int)tn - 1);
while ((d = ReverseNum(tn, en)) == 0)
{
en = rand.Next(0, (int)tn - 1);
}
if (d < 0)
while (d < 0)
d += tn;
else if (d > tn)
while (d > tn)
d -= tn;
string text = textBox_input.Text;
char[] open_txt_chars = text.ToCharArray();
string [] open_txt_str = new string [open_txt_chars.Length];
open_txt_str = ConvertCharsToStringOfDigits(open_txt_chars, 0);
string digits_line = string.Concat(open_txt_str);
char[] open_dig_chars = digits_line.ToCharArray();
int nums_of_n, m;
nums_of_n = 0;
m = (int)n;
while (m > 0)
{
nums_of_n++;
m/=10;
}
int parts;
parts = open_dig_chars.Length / (nums_of_n-1);
if ((open_dig_chars.Length % (nums_of_n-1))!= 0)
{
parts++;
}
double[] num_parts = new double[parts];
num_parts = DivideByParts(open_dig_chars, nums_of_n-1, parts);
double[] num_parts_encr = new double[parts];
string[] encr_txt_str = new string[parts];
for (int i = 0; i < num_parts.Length; i++)
{
num_parts_encr[i] = PowerUpBin(num_parts[i], en, n);
}
for (int j = 0; j < parts; j++)
{
encr_txt_str[j] = num_parts_encr[j].ToString();
while (encr_txt_str[j].Length != nums_of_n)
{
if (j == parts)
break;
encr_txt_str[j] = "0" + encr_txt_str[j];
}
}
digits_line = string.Concat(encr_txt_str);
textBox_e.Text = en.ToString();
textBox_n.Text = n.ToString();
textBox_d.Text = d.ToString();
textBox_output.Text = digits_line;
}
Метод, який здійснює розшифрування тексту
private void decryptToolStripMenuItem_Click(object sender, EventArgs e)
{
double en, n, d;
en = Convert.ToDouble(textBox_e.Text);
n = Convert.ToDouble(textBox_n.Text);
d = Convert.ToDouble(textBox_d.Text);
string text = textBox_input.Text;
string digits_line = textBox_input.Text;
char[] decr_dig_chars = digits_line.ToCharArray();
int nums_of_n, m;
nums_of_n = 0;
m = (int)n;
while (m > 0)
{
nums_of_n++;
m /= 10;
}
int parts;
parts = decr_dig_chars.Length / nums_of_n;
if ((decr_dig_chars.Length % nums_of_n) != 0)
{
parts++;
}
double[] decrnum_parts = new double[parts];
decrnum_parts = DivideByParts(decr_dig_chars, nums_of_n, parts);
double[] num_parts_decr = new double[parts];
for (int i = 0; i < decrnum_parts.Length; i++)
{
num_parts_decr[i] = PowerUpBin(decrnum_parts[i], d, n);
}
string[] open_string = new string[num_parts_decr.Length];
for (int j = 0; j < num_parts_decr.Length; j++)
{
open_string[j] = num_parts_decr[j].ToString();
while (open_string[j].Length != nums_of_n-1)
{
if (j == parts)
break;
open_string[j] = "0" + open_string[j];
}
}
digits_line = string.Concat(open_string);
char[] encr_dig_chars = digits_line.ToCharArray();
parts = encr_dig_chars.Length / 3;
if ((encr_dig_chars.Length % 3) != 0)
{
parts++;
}
double[] digits_of_decr = new double[parts];
digits_of_decr = DivideByParts(encr_dig_chars, 3, parts);
textBox_e.Text = en.ToString();
textBox_n.Text = n.ToString();
textBox_d.Text = d.ToString();
textBox_output.Text = ConvertDigitsToString(digits_of_decr);
}
Результат роботи програми
/ /
Висновок
На даній лабораторній роботі, я написала програму мовою C#, яка здійснює шифрування і розшифрування тексту алгоритмом RSA. Алфавітом тексту є таблиця символів ASCII. Алгоритм RSA полягає в тому, що до вихідний текст розбивають на частини і підносять до степеня за заданим модулем.
Задача розкриття RSA є дослівно задачею добування із заданого цілого числа кореня e-го степеня за модулем n=pq. На сьогодні для цієї задачі невідомо ніякого ефективного алгоритму. Однак не доведено, що такого алгоритму не існує.