Шифрование строки функцией Эйлера. Перевод решения из Pascal на C#
Помогите перевести правильно из Pascal в C# пробовал сам но возникли проблемы
Код на Pascal
var
p, q, r, fr, e, d, m, c, s: int64;
z:string;
i:longint; // Затрудняюсь перевести тут
a:array of int64;
function TPower(a,b,n: int64):int64; // Затрудняюсь перевести тут
Var i,k: int64;
begin
k:=1; for i:=1 to b do k:=(k*a) mod n;
TPower:=k; // Затрудняюсь перевести тут
end;
function Inverse(a, n: int64): int64;
var
i: int64;
begin
for i := 1 to N - 1 do if (a * i) mod N = 1 then break;
Inverse := i; // Затрудняюсь перевести тут
writeln('Закрытый ключ - ', i);
end;
begin
Writeln('Введите p = ');
Readln(p);
Writeln('Введите q = ');
Readln(q);
r := p * q;
Writeln('Произведение двух простых чисел p и q равно r = ', r);
fr := (p - 1) * (q - 1);
Writeln('функция Эйлера f(r) = ', fr);
Writeln('Введите открытый ключ e < fr, e = ');
Readln(e);
d := Inverse(e, fr);
Writeln('Введите строку: ');readln(z);
SetLength(a,length(z));
Writeln('Зашифрованное сообщение: ');
for i:=1 to length(z) do begin
m:=ord(z[i]); // Затрудняюсь перевести тут
a[i-1] := TPower(m,e,r); // Затрудняюсь перевести тут
Write(a[i-1],' '); // Затрудняюсь перевести тут
end;
writeln;
z:='';
for i:=0 to length(a)-1 do
z:=z+chr(TPower(a[i],d,r));
writeln('Расшифрованное сообщение: ',z)
end.
Код на С# не рабочий, так как не смог правильно перевести
static int TPower(int a, int b,int n)
{
int k = 1;
for (int i = 1; i < b; i++)
{
k = (k * a) % n;
}
return k;
}
static int Inverse(int a, int n)
{
for (int i = 1; i < n-1; i++)
{
if ((a*i)% n ==1)
{
break;
}
}
Console.WriteLine($" Закрытый ключ { i }");
return i;
}
static void Main(string[] args)
{
int p, q, n, fr, e, d, m, c, s;
string z;
int[] Myarr;
Console.WriteLine("Введите p");
p = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Введите q");
q = Convert.ToInt32(Console.ReadLine());
n = p * q;
Console.WriteLine($" Произведение двух простых чисел равно { n }");
fr = (p - 1) * (q - 1);
Console.WriteLine($"Фукция эелера равна {fr} ");
Console.WriteLine("Введите открытый ключ");
e = Convert.ToInt32(Console.ReadLine());
d = Inverse(e, fr);
Console.WriteLine("Введите строку");
z = Console.ReadLine();// НЕ ЗНАЮ ПРАВИЛЬНО ИЛИ НЕТ
char[] Myarr = z.ToCharArray(); // НЕ ЗНАЮ ПРАВИЛЬНО ИЛИ НЕТ
Console.WriteLine("Зашифрованное сообщение");
for (int i = 1; i < z.Length; i++)
{
m = z.IndexOfAny[i];
a[i - 1] = TPower(m, e, n);
Console.Write(a[i-1]+" ");
}
z = "";
for (int i = 0; i < length; i++)
{
}
Console.WriteLine("Расшифреванное сообщение"+z);
Console.ReadLine()
}
Ответы (1 шт):
Самое важное отличие Pascal от C# здесь - это то что индексация массивов начинается не с 1, а с 0.
Далее вам не хватило знания о том, что есть неяное и явное преобразование между char и int. Например получение кода символа.
char c = 'A';
int a = (int)c; // явное преобразование
int a = c; // неявное преобразование
В обратном направлении существует только явное преобразование.
При этом зашифрованный массив в Pascal и C# могут отличаться, потому что просто используются разные таблицы символов. В Pascal используется DOS кодировка CP866 (ASCII с руссифицированным шрифтом), в C# для строк и символов используется UTF-16. При желании вы можете в C# использовать и ASCII, но потеряете возможность использовать кириллицу.
Можно использовать и более приближенную к ASCII кодировку, поддерживающую русский - UTF-8 (коды латинских символов в ASCII и UTF-8 совпадают). string при этом можно преобразовать в последовательность байт так.
string text = "Привет, мир!";
byte[] array = Encoding.UTF8.GetBytes(text);
И далее работать с байтовым массивом немного доработав методы шифрования. Обратно преобразовать можно вот так:
string result = Encoding.UTF8.GetString(array);
Так как P, N и отрытый ключ - простые числа, я написал простой генератор простых числел, чтобы вам можно было проще поэкспериментировать.
private static IEnumerable<int> GetPrimeNumbers(int length)
{
bool[] states = new bool[length];
for (int i = 2; i < length; i++)
{
if (!states[i])
{
for (int j = i * 2; j < length; j += i)
states[j] = true;
yield return i;
}
}
}
static int TPower(int a, int b, int n)
{
int k = 1;
for (int i = 0; i < b; i++)
{
k = k * a % n;
}
return k;
}
static int Inverse(int a, int n)
{
int i;
for (i = 1; i < n; i++)
{
if (a * i % n == 1)
{
break;
}
}
Console.WriteLine($"Закрытый ключ: i = {i}");
return i;
}
static void Main(string[] args)
{
Console.WriteLine("Простые числа");
Console.WriteLine(string.Join(", ", GetPrimeNumbers(100)));
Console.Write("Введите p (простое число): ");
int p = int.Parse(Console.ReadLine());
Console.Write("Введите n (простое число): ");
int n = int.Parse(Console.ReadLine());
int r = p * n;
Console.WriteLine($"Произведение двух простых чисел p и n: r = {r}");
int fr = (p - 1) * (n - 1);
Console.WriteLine($"Функция Эйлера: f(r) = {fr}");
Console.Write("Введите открытый ключ (простое число): ");
int e = int.Parse(Console.ReadLine());
int d = Inverse(e, fr);
Console.Write("Введите строку: ");
string z = Console.ReadLine();
byte[] bytes = Encoding.UTF8.GetBytes(z);
int[] a = new int[bytes.Length];
Console.WriteLine("Зашифрованное сообщение");
for (int i = 0; i < bytes.Length; i++)
{
int m = bytes[i];
a[i] = TPower(m, e, r);
Console.Write(a[i] + " ");
}
Console.WriteLine();
byte[] s = new byte[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
{
s[i] = (byte)TPower(a[i], d, r);
}
string result = Encoding.UTF8.GetString(s);
Console.WriteLine("Расшифрованное сообщение: " + result);
Console.ReadLine();
}
Вывод в консоль
Простые числа
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
Введите p (простое число): 29
Введите n (простое число): 67
Произведение двух простых чисел p и n: r = 1943
Функция Эйлера: f(r) = 1848
Введите открытый ключ (простое число): 73
Закрытый ключ: i = 481
Введите строку: Привет, мир!
Зашифрованное сообщение
850 1751 1057 1665 850 1755 850 586 850 227 1057 98 1323 1336 850 1606 850 1755 1057 1665 1195
Расшифрованное сообщение: Привет, мир!