Заключение
В ходе лабораторной работы были изучены шифр RSA, криптосистема Эль-Гамаля и ранцевая криптосистема, алгоритм быстрого возведения в степень по модулю, тест Ферма и создана программная реализация алгоритмов, код программы приведен в приложении А.
9
Приложение А
(обязательное)
Код программы
using static System.Runtime.InteropServices.JavaScript.JSType; using System.Numerics;
internal class Program
{
private static void Main(string[] args)
{
BigInteger longPowerWithMod(BigInteger a, BigInteger pow, BigInteger
module)
{
if (module == 1) return 0;
BigInteger result = 1;
while (pow > 0)
{
if ((pow & 1) == 1)
{
result = result * a % module;
}
pow = pow >> 1;
a = a * a % module;
}
return result;
}
bool testFerma(long number)
{
bool testFermaPassed = false; int iterations = 10;
for (int i = 0; i < iterations; i++)
{
Console.WriteLine($"Итерация {i + 1}:"); long a = Random.Shared.NextInt64(2, number); while (a % 2 == 0)
{
10
a = Random.Shared.NextInt64(2, number);
}
long aPow = (long)longPowerWithMod(a, number - 1, number); if (aPow == 1)
{
Console.WriteLine($"Число {number} – псевдопростое,
ура!"); |
|
testFermaPassed = true; |
|
} |
|
else |
|
{ |
|
Console.WriteLine($"Число {number} – точно |
|
составное, попробуй другое число..."); |
|
testFermaPassed = false; |
|
} |
|
} |
|
Console.WriteLine("----------------------------------------- |
"); |
return testFermaPassed; |
|
} |
|
BigInteger NOD(BigInteger a, BigInteger b) |
|
{ |
|
while (b != 0) |
|
{ |
|
BigInteger temp = b; |
|
b = a % b; |
|
a = temp; |
|
} |
|
return a; |
|
} |
|
BigInteger inverseNumberMod(BigInteger a, BigInteger module) |
|
{ |
|
BigInteger m0 = module; |
|
BigInteger y2 = 0, y1 = 1; |
|
if (module == 1) return 0; |
|
while (a > 1) |
|
{ |
|
BigInteger q = a / module; |
|
BigInteger r = module; |
|
module = a % module; |
|
11
a = r; r = y2;
y2 = y1 - q * y2;
y1 = r;
}
if (y1 < 0) y1 += m0;
return y1;
}
long Mod(long a, long n)
{
while (a > n)
{
a -= n;
}
return a;
}
bool isPrimitiveRoot(long g, long p, List<long> primeFactors)
{
if (longPowerWithMod(g, p - 1, p) != 1) return false;
foreach (long q in primeFactors)
{
if (longPowerWithMod(g, (p - 1) / q, p) == 1)
{
return false;
}
}
return true;
}
List<long> getPrimeFactors(long n)
{
List<long> factors = new List<long>();
if (n % 2 == 0)
{
factors.Add(2);
while (n % 2 == 0) n /= 2;
}
12
for (long i = 3; i * i <= n; i += 2)
{
if (n % i == 0)
{
factors.Add(i);
while (n % i == 0) n /= i;
}
}
if (n > 1) factors.Add(n);
return factors;
}
int fastPower(int a, int b, int mod)
{
string binaryB = Convert.ToString(b, 2); List<char> inverseBinaryB =
binaryB.AsEnumerable().Reverse().ToList();
if (inverseBinaryB[0] == '1')
{
b = a;
}
else
{
b = 1;
}
inverseBinaryB.RemoveAt(0);
foreach (char x in inverseBinaryB)
{
long aNext = Mod(a*a, mod);
if (x == '1')
{
b = (int)Mod(aNext * b, mod); a = (int)aNext;
}
else
{
13
a = (int)aNext; continue;
}
}
return b;
}
void RSA(BigInteger q, BigInteger p, BigInteger m)
{
BigInteger d = 0; BigInteger n = p * q;
BigInteger fi = (p - 1) * (q - 1);
BigInteger exp = Random.Shared.NextInt64(2, (long)p); while (NOD(exp, fi) != 1)
{
exp = Random.Shared.NextInt64(2, (long)p);
}
Console.WriteLine($"Сгенерированное значение е: {exp}");
d = inverseNumberMod(exp, fi);
BigInteger y = longPowerWithMod(m, exp, n);
Console.WriteLine($"Зашифрованное сообщение E(m): {y}"); Console.WriteLine($"Расшифрованное сообщение D(y):
{longPowerWithMod(y, d, n)}"); Console.WriteLine();
}
void Knapsack(long q, List<long> w, string m)
{
long wSum = 0; foreach (long x in w)
{
wSum += x;
}
long r = Random.Shared.NextInt64(2, q); Console.WriteLine($"Сгенерированное значение r: {r}");
List<long> eps = new List<long>(); for (int i = 0; i < w.Count; i++)
{
14
eps.Add(Mod(w[i]*r, q));
}
long knapsackE = 0;
for(int i = 0; i < m.Length; i++)
{
if (m[i] == '1')
{
knapsackE += eps[i];
}
}
Console.WriteLine($"Зашифрованное сообщение E(m): {knapsackE}");
long rInverse = (long)inverseNumberMod(r, q);
long l = Mod(rInverse * knapsackE, q);
List<long> wInverse = w.AsEnumerable().Reverse().ToList();
string result = "";
foreach (long x in wInverse)
{
if (l - x >= 0)
{
l = l - x; result += "1";
}
else
{
l = l;
result += "0";
}
}
result = new string(result.Reverse().ToArray());
Console.WriteLine($"Расшифрованное сообщение D(y): {result}");
}
void Elgamal(long p, long m)
{
List<long> factors = getPrimeFactors(p - 1);
long g = Random.Shared.NextInt64(2, p);
15
while (!isPrimitiveRoot(g, p, factors))
{
g = Random.Shared.NextInt64(2, p);
}
Console.WriteLine($"Сгенерированное значение g: {g}");
long x = Random.Shared.NextInt64(2, p); Console.WriteLine($"Сгенерированное значение x: {x}");
long y = (long)longPowerWithMod(g, x, p);
long k = Random.Shared.NextInt64(2, p); Console.WriteLine($"Сгенерированное значение k: {k}");
long a = (long)longPowerWithMod(g, k, p);
long b = Mod(m * (long)longPowerWithMod(y, k, p),p);
Console.WriteLine($"Зашифрованное сообщение E(m): {a} {b}");
BigInteger Dy = Mod((long)(b * inverseNumberMod(longPowerWithMod(a, x, p), p)), p);
Console.WriteLine($"Расшифрованное сообщение D(y): {Dy}");
}
Console.WriteLine("Введите значение q, p, m для RSA через пробел:"); try
{
string[] RSAparam = Console.ReadLine().Split(new char[] {' '}); for (int i = 0; i < RSAparam.Length; i++)
{
if (Convert.ToInt64(RSAparam[i]) <= 0)
{
throw new FormatException();
}
}
long qRSA = Convert.ToInt64(RSAparam[0]); long pRSA = Convert.ToInt64(RSAparam[1]); long mRSA = Convert.ToInt64(RSAparam[2]);
Console.WriteLine("\nВведите значения w для задачи ранца через
пробел:");
16
string[] knapsackWParam = Console.ReadLine().Split(new char[] {'
'});
List<long> knapsackW = new List<long>();
for (int i = 0; i < knapsackWParam.Length; i++)
{
if (Convert.ToInt64(knapsackWParam[i]) <= 0)
{
throw new FormatException();
}
else
{
knapsackW.Add(Convert.ToInt64(knapsackWParam[i]));
}
}
Console.WriteLine("\nВведите значение q, m для задачи ранца
через пробел:");
string[] knapsackParam = Console.ReadLine().Split(new char[] {'
'});
for (int i = 0; i < knapsackParam.Length; i++)
{
if (Convert.ToInt64(RSAparam[i]) <= 0)
{
throw new FormatException();
}
}
long qKnapsack = Convert.ToInt64(knapsackParam[0]); string mKnapsack = knapsackParam[1];
Console.WriteLine("\nВведите значение p, m для Эль-Гамаля через
пробел:");
string[] elgamalParam = Console.ReadLine().Split(new char[] { '
' });
for (int i = 0; i < elgamalParam.Length; i++)
{
if (Convert.ToInt64(elgamalParam[i]) <= 0)
{
throw new FormatException();
}
}
long pElgamal = Convert.ToInt64(elgamalParam[0]); long mElgamal = Convert.ToInt64(elgamalParam[1]);
17
Console.WriteLine("\nПроверка введенных значений тестом
Ферма:");
if (testFerma(qRSA) == false || testFerma(pRSA) == false || testFerma(qKnapsack) == false || testFerma(pElgamal) == false)
{
Console.WriteLine("Одно из введенных значений не является
простым числом :(");
return;
}
Console.WriteLine("\nПроверка введенных значений w:"); for (int i = 2; i < knapsackW.Count; i++)
{
if (knapsackW[i - 2] + knapsackW[i - 1] >= knapsackW[i])
{
Console.WriteLine("Введенные значения не образуют резко возрастающую последовательность :(");
return;
}
else
{
Console.WriteLine("Резко возрастает...");
}
}
Console.WriteLine("Это и правда резко возрастающая последовательность! Продолжаем...");
Console.WriteLine("\nПроверка значения q для задачи ранца:"); long wSum = 0;
foreach (long x in knapsackW)
{
wSum += x;
}
if (qKnapsack <= wSum)
{
Console.WriteLine("Введенное значение q меньше или равно
сумме значений w :(");
return;
}
else
{
Console.WriteLine("Значение подходит, продолжаем...");
}
18
Console.WriteLine("\nПроверка сообщения m для задачи ранца:"); if (mKnapsack.Length < 5 && knapsackW.Count != mKnapsack.Length)
{
Console.WriteLine("Сообщение не подходит по размеру :("); return;
}
foreach (char x in mKnapsack)
{
if (x == '0' || x == '1')
{
continue;
}
else
{
Console.WriteLine("Сообщение не является двочиным
числом :(");
return;
}
}
Console.WriteLine("Сообщение нужного размера и является двочиным числом, продолжаем...");
Console.WriteLine("\nПроверка значения p для Эль-Гамаля:"); if (pElgamal < 100 || pElgamal > 999)
{
Console.WriteLine("Значение p не подходит по размеру :("); return;
}
else
{
Console.WriteLine("Значение подходит, продолжаем...");
}
Console.WriteLine("\nRSA");
RSA(qRSA, pRSA, mRSA);
Console.WriteLine("\nЗадача ранца");
Knapsack(qKnapsack, knapsackW, mKnapsack);
Console.WriteLine("\nЭль-Гамаль");
Elgamal(pElgamal, mElgamal);
19
Console.WriteLine($"\nРезультат возведения 12^11 mod 481 = {fastPower(12, 11, 481)}");
Console.WriteLine($"Результат возведения 181^275 mod 481 =
{fastPower(181, 275, 481)}");
Console.WriteLine($"Результат возведения 17^131 mod 2201 =
{fastPower(17, 131, 2201)}");
}
catch (FormatException)
{
Console.WriteLine("Введите целые положительные числа в качестве
значений >:(");
}
}
}
20
