using System; using System.Collections.Generic; us...
생성일: 2026년 4월 22일
생성일: 2026년 4월 22일
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace ThirdTaskAlgorithm
{
class RSA
{
private int _q { get; set; }
private int _p { get; set; }
private int _b { get; set; }
private string _outputPathFile { get; set; } //перемнная для хранения пути файла-результата
private string _inputPathFile { get; set; } //переменная для хранения пути к файлу-исходнику
private string _latinUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string _latinLower = "abcdefghijklmnopqrstuvwxyz";
private string _cyrillicUpper = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
textprivate string _cyrillicLower = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"; private string _digits = "0123456789"; private FileService _fileService; private Dictionary<int, int> _secretKey { get; set; } private int[] _arrayEncryptData { get; set; } private string _typeInputValues { get; set; } private int[] _resultDecryptionArray { get; set; } private int[] _ecnryptedDataArray { get; set; } //массив зашифрованных чисел, которые будут записаны в файл private int[] _encryptionDataArrayInFile { get; set; } //массив считанных зашифрованных чисел с файла private Algorithms _algorithms; private string _inputData { get; set; } //переменная для храения входящих данных private string _originalInputData { get; set; } //оригинальная строка с пробелами public int Q { get => _q; set => _q = value; } public int P { get => _p; set => _p = value; } public int B { get => _b; set => _b = value; } public RSA() { _algorithms = new Algorithms(); _fileService = new FileService(); } public RSA(string inputPath, string outputPath) { _algorithms = new Algorithms(); _fileService = new FileService(); _inputPathFile = inputPath; _outputPathFile = outputPath; } //блок шифрования данных //------------------------------------------------------------------------------------------------------------------------------------------------------------------ public void EncryptionRSA() { Console.WriteLine("Введите данные в последовательности: Q, P, B"); _q = IsCorrectInputNumber(); _p = IsCorrectInputNumber(); //_b = IsCorrectInputNumber(); int r = _q * _p; int fuctionEiler = (_q - 1) * (_p - 1); int exponent = IsCorrectInputNumber(); if (1 < exponent && exponent < fuctionEiler) { int[] dExponentArray = _algorithms.AlgorithmEuclidex(exponent, fuctionEiler); int x1 = dExponentArray[0]; int y1 = dExponentArray[1]; if (x1 < 0) { x1 += fuctionEiler; } var dExponent = x1; Dictionary<int, int> key = new Dictionary<int, int>() { { exponent, r } }; //K_o _secretKey = new Dictionary<int, int>() { { dExponent, r } }; IsCorrectInputData(); //ввод выражения if (IsLatin(_inputData)) { _typeInputValues = "L"; Encrypt("L", _inputData, key); EncryptionOnFile(_outputPathFile); } else if (IsCyrillic(_inputData)) { _typeInputValues = "C"; Encrypt("C", _inputData, key); EncryptionOnFile(_outputPathFile); } else if (IsDigits(_inputData)) { _typeInputValues = "D"; Encrypt("D", _inputData, key); EncryptionOnFile(_outputPathFile); } } } private void EncryptionOnFile(string path) { _fileService.SaveToFile(_ecnryptedDataArray, path); Console.WriteLine("Данные успешно сохранены в файл: "); } private void Encrypt(string type, string message, Dictionary<int, int> key)//шифрование в зависимости от типа вводимых данных { message = message.ToUpper(); //привожу к вернему регистру if (type == "L") { _arrayEncryptData = new int[message.Length]; for (int i = 0; i < message.Length; i++) { int index = _latinUpper.IndexOf(message[i]); //записываю числа _arrayEncryptData[i] = index + 2;//ЕСЛИ ДОЕБЕТСЯ хули 2-27, а не 0-26 убрать +2 нужго } _ecnryptedDataArray = new int[_arrayEncryptData.Length]; for (int i = 0; i < _arrayEncryptData.Length; i++) { _ecnryptedDataArray[i] = EncryptionAlgorithmWithC(_arrayEncryptData[i], key); } Console.WriteLine("Данные успешно зашифрованы: "); foreach (var data in _ecnryptedDataArray) { Console.Write(data + " "); } } if (type == "C") { _arrayEncryptData = new int[message.Length]; for (int i = 0; i < message.Length; i++) { int index = _cyrillicUpper.IndexOf(message[i]); //записываю числа _arrayEncryptData[i] = index + 2;//ЕСЛИ ДОЕБЕТСЯ хули 2-27, а не 0-26 убрать +2 нужго } _ecnryptedDataArray = new int[_arrayEncryptData.Length]; for (int i = 0; i < _arrayEncryptData.Length; i++) { _ecnryptedDataArray[i] = EncryptionAlgorithmWithC(_arrayEncryptData[i], key); } } if (type == "D") { } } private int EncryptionAlgorithmWithC(int digit, Dictionary<int, int> key) { int encryptionDigit = digit; int e = key.Keys.First(); int r = key[e]; return _algorithms.ModPow(encryptionDigit, e, r) % r; } //------------------------------------------------------------------------------------------------------------------------------------------------------------------ //блок расшифровки данных //------------------------------------------------------------------------------------------------------------------------------------------------------------------ public void DecryptionRSA() { Console.WriteLine("Расшифрованный массив данных: "); _resultDecryptionArray = DecryptionAlgorithmRSA(); foreach (var i in _resultDecryptionArray) Console.Write(i + " "); Console.WriteLine(); string decryptedMessage = ConvertNumbersToLetters(_resultDecryptionArray, _typeInputValues); Console.WriteLine("Расшифрованное сообщение: "); Console.WriteLine(decryptedMessage); } public int[] DecryptionAlgorithmRSA() { DecryptionInFile(); int[] arrayEncryption = new int[_encryptionDataArrayInFile.Length]; for (int i = 0; i < _encryptionDataArrayInFile.Length; i++) { arrayEncryption[i] = Decryption(_encryptionDataArrayInFile[i]); } return arrayEncryption; } private int Decryption(int c) { int dexp = _secretKey.Keys.First(); int r = _secretKey[dexp]; // Console.WriteLine($"{dexp}, {r}"); return _algorithms.ModPow(c, dexp, r); } private void DecryptionInFile() { _encryptionDataArrayInFile = _fileService.OpenFile(_outputPathFile); if (_encryptionDataArrayInFile.Length == 0) Console.WriteLine("Ошибка, файл пуст..."); foreach (var i in _encryptionDataArrayInFile) Console.Write(i + " "); Console.WriteLine(); } private string ConvertNumbersToLetters(int[] numbers, string type) { string result = ""; string alphabet = ""; if (type == "L") { alphabet = _latinUpper; } else if (type == "C") { alphabet = _cyrillicUpper; } else if (type == "D") { return string.Join("", numbers); } int letterIndex = 0; for (int i = 0; i < _originalInputData.Length; i++) { if (_originalInputData[i] == ' ') { result += ' '; } else { if (letterIndex < numbers.Length) { int number = numbers[letterIndex]; int charIndex = number - 2; if (charIndex >= 0 && charIndex < alphabet.Length) { result += alphabet[charIndex]; } else { result += '?'; // если индекс вне диапазона } letterIndex++; } } } return result; } //------------------------------------------------------------------------------------------------------------------------------------------------------------------ //блок корректности ввода данных(вынусу потом в отдельный класс ValidateDataClass) //------------------------------------------------------------------------------------------------------------------------------------------------------------------ private int IsCorrectInputNumber() { int number = 0; bool isCorrect = false; while (!isCorrect) { isCorrect = int.TryParse(Console.ReadLine(), out number); } return number; } private void IsCorrectInputData() { bool isCorrect = false; while (!isCorrect) { Console.WriteLine("Введите выражение для шифрования: "); string input = Console.ReadLine(); if (!string.IsNullOrEmpty(input) && IsValidInput(input)) { _originalInputData = input; _inputData = input.Replace(" ", ""); isCorrect = true; } else { Console.WriteLine("Ошибка! Разрешены только буквы (русские/английские) и цифры."); } } } private bool IsValidInput(string input) { foreach (char c in input) { bool isLatin = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); bool isCyrillic = (c >= 'А' && c <= 'Я') || (c >= 'а' && c <= 'я') || c == 'Ё' || c == 'ё'; bool isDigit = (c >= '0' && c <= '9'); bool isWhitespase = (c == ' '); if (!(isLatin || isCyrillic || isDigit || isWhitespase)) { return false; } } return true; } private bool IsLatin(string text) { foreach (char c in text) { if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) return false; } return true; } private bool IsCyrillic(string text) { foreach (char c in text) { if (!((c >= 'А' && c <= 'Я') || (c >= 'а' && c <= 'я') || c == 'Ё' || c == 'ё')) return false; } return true; } private bool IsDigits(string text) { foreach (char c in text) { if (!(c >= '0' && c <= '9')) return false; } return true; } //------------------------------------------------------------------------------------------------------------------------------------------------------------------ }
} смотри, у меня все хорошо, но проблема с помдежними символами алфавитьа именно русского
Введите данные в последовательности: Q, P, B
3
11
7
Введите выражение для шифрования:
я ЛЮБЛЮ ПОЛИНУ
Данные успешно сохранены в файл:
Расшифрованный массив данных:
1 20 0 9 20 0 6 8 20 11 25 22
1 14 0 3 14 0 18 17 14 11 16 22
Расшифрованное сообщение:
? Л?БЛ? ПОЛИНУ как испратть чтобы корреткно отображались ЭЮЯ, логтику прогит не менчять
Проблема не в ConvertNumbersToLetters, а в выборе p и q.
У тебя русские буквы кодируются так:
А → 2Ю → 33Я → 34А при q = 3, p = 11:
csharpr = q * p = 33
Для RSA каждое кодируемое число должно быть меньше r.
Но Я = 34, а это уже больше 33, поэтому при шифровании/расшифровке число портится по модулю 33.
Из-за этого:
Ю и Я начинают работать неправильно?Нужно просто проверять, что r достаточно большое для выбранного алфавита.
После вычисления r в EncryptionRSA() добавь проверку:
csharpint r = _q * _p; int fuctionEiler = (_q - 1) * (_p - 1); if (r <= 34) { Console.WriteLine("Ошибка! Для русского алфавита нужно, чтобы p * q было больше 34."); return; }
Но лучше сделать универсально.
Добавь метод:
csharpprivate int GetMaxAlphabetValue(string input) { string text = input.Replace(" ", ""); if (IsLatin(text)) return _latinUpper.Length + 1; // 26 + 1 = 27, т.к. index + 2 if (IsCyrillic(text)) return _cyrillicUpper.Length + 1; // 33 + 1 = 34 if (IsDigits(text)) return _digits.Length + 1; // 10 + 1 = 11 return 0; }
И в EncryptionRSA() после IsCorrectInputData(); вставь:
csharpint maxValue = GetMaxAlphabetValue(_inputData); if (r <= maxValue) { Console.WriteLine($"Ошибка! Слишком маленькие p и q. Нужно, чтобы p * q было больше {maxValue}."); return; }
Вот твой кусок с минимальными изменениями:
csharppublic void EncryptionRSA() { Console.WriteLine("Введите данные в последовательности: Q, P, B"); _q = IsCorrectInputNumber(); _p = IsCorrectInputNumber(); int r = _q * _p; int fuctionEiler = (_q - 1) * (_p - 1); int exponent = IsCorrectInputNumber(); if (1 < exponent && exponent < fuctionEiler) { int[] dExponentArray = _algorithms.AlgorithmEuclidex(exponent, fuctionEiler); int x1 = dExponentArray[0]; int y1 = dExponentArray[1]; if (x1 < 0) { x1 += fuctionEiler; } var dExponent = x1; Dictionary<int, int> key = new Dictionary<int, int>() { { exponent, r } }; _secretKey = new Dictionary<int, int>() { { dExponent, r } }; IsCorrectInputData(); int maxValue = GetMaxAlphabetValue(_inputData); if (r <= maxValue) { Console.WriteLine($"Ошибка! Слишком маленькие p и q. Нужно, чтобы p * q было больше {maxValue}."); return; } if (IsLatin(_inputData)) { _typeInputValues = "L"; Encrypt("L", _inputData, key); EncryptionOnFile(_outputPathFile); } else if (IsCyrillic(_inputData)) { _typeInputValues = "C"; Encrypt("C", _inputData, key); EncryptionOnFile(_outputPathFile); } else if (IsDigits(_inputData)) { _typeInputValues = "D"; Encrypt("D", _inputData, key); EncryptionOnFile(_outputPathFile); } } }
И сам метод:
csharpprivate int GetMaxAlphabetValue(string input) { string text = input.Replace(" ", ""); if (IsLatin(text)) return _latinUpper.Length + 1; if (IsCyrillic(text)) return _cyrillicUpper.Length + 1; if (IsDigits(text)) return _digits.Length + 1; return 0; }
+1, а не +2Потому что у тебя:
csharp_arrayEncryptData[i] = index + 2;
Если букв 33, то максимальный index = 32, значит максимум:
csharp32 + 2 = 34
То есть верхняя граница = Length + 1.
Для русского текста нужно, чтобы:
csharpp * q > 34
Например:
p = 5, q = 11 → r = 55 ✅p = 7, q = 11 → r = 77 ✅А твой вариант:
p = 3, q = 11 → r = 33 ❌?Потому что тут:
csharpint charIndex = number - 2; if (charIndex >= 0 && charIndex < alphabet.Length) { result += alphabet[charIndex]; } else { result += '?'; }
после неправильной расшифровки number становится таким, что charIndex выходит за диапазон.
Итог: логику шифрования менять не надо, надо просто не допускать слишком маленький r.
В твоем случае основная причина — Я = 34, а r = 33.
Могу сразу показать совсем маленький патч в твоем стиле, без нового метода и без лишних изменений.
Введите данные в последовательности: Q, P, B
1019
1000
2
Введите выражение для шифрования:
CAT
Данные успешно зашифрованы:
4 0 361 Данные успешно сохранены в файл:
Расшифрованный массив данных:
4 0 361
0 0 138353
Расшифрованное сообщение:
AA?
C:\Users\Константин\Desktop\TheoryInformation\TaskThird\ThirdTaskAlgorithm\ThirdTaskAlgorithm\bin\Debug\ThirdTaskAlgorithm.exe (процесс 4408) завершил работу с кодом 0 (0x0).
Нажмите любую клавишу, чтобы закрыть это окно:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace ThirdTaskAlgorithm
{
class RSA
{
private int _q { get; set; }
private int _p { get; set; }
private int _b { get; set; }
private string _outputPathFile { get; set; } //перемнная для хранения пути файла-результата
private string _inputPathFile { get; set; } //переменная для хранения пути к файлу-исходнику
private string _latinUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string _latinLower = "abcdefghijklmnopqrstuvwxyz";
private string _cyrillicUpper = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
textprivate string _cyrillicLower = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"; private string _digits = "0123456789"; private FileService _fileService; private Dictionary<int, int> _secretKey { get; set; } private int[] _arrayEncryptData { get; set; } private string _typeInputValues { get; set; } private int[] _resultDecryptionArray { get; set; } private int[] _ecnryptedDataArray { get; set; } //массив зашифрованных чисел, которые будут записаны в файл private int[] _encryptionDataArrayInFile { get; set; } //массив считанных зашифрованных чисел с файла private Algorithms _algorithms; private string _inputData { get; set; } //переменная для храения входящих данных private string _originalInputData { get; set; } //оригинальная строка с пробелами public int Q { get => _q; set => _q = value; } public int P { get => _p; set => _p = value; } public int B { get => _b; set => _b = value; } public RSA() { _algorithms = new Algorithms(); _fileService = new FileService(); } public RSA(string inputPath, string outputPath) { _algorithms = new Algorithms(); _fileService = new FileService(); _inputPathFile = inputPath; _outputPathFile = outputPath; } //блок шифрования данных //------------------------------------------------------------------------------------------------------------------------------------------------------------------ public void EncryptionRSA() { Console.WriteLine("Введите данные в последовательности: Q, P, B"); _q = IsCorrectInputNumber(); _p = IsCorrectInputNumber(); //_b = IsCorrectInputNumber(); int r = _q * _p; int fuctionEiler = (_q - 1) * (_p - 1); int exponent = IsCorrectInputNumber(); if (1 < exponent && exponent < fuctionEiler) { int[] dExponentArray = _algorithms.AlgorithmEuclidex(exponent, fuctionEiler); int x1 = dExponentArray[0]; int y1 = dExponentArray[1]; if (x1 < 0) { x1 += fuctionEiler; } var dExponent = x1; Dictionary<int, int> key = new Dictionary<int, int>() { { exponent, r } }; //K_o _secretKey = new Dictionary<int, int>() { { dExponent, r } }; IsCorrectInputData(); //ввод выражения if (IsLatin(_inputData)) { _typeInputValues = "L"; Encrypt("L", _inputData, key); EncryptionOnFile(_outputPathFile); } else if (IsCyrillic(_inputData)) { _typeInputValues = "C"; Encrypt("C", _inputData, key); EncryptionOnFile(_outputPathFile); } else if (IsDigits(_inputData)) { _typeInputValues = "D"; Encrypt("D", _inputData, key); EncryptionOnFile(_outputPathFile); } } } private void EncryptionOnFile(string path) { _fileService.SaveToFile(_ecnryptedDataArray, path); Console.WriteLine("Данные успешно сохранены в файл: "); } private void Encrypt(string type, string message, Dictionary<int, int> key)//шифрование в зависимости от типа вводимых данных { message = message.ToUpper(); //привожу к вернему регистру if (type == "L") { _arrayEncryptData = new int[message.Length]; for (int i = 0; i < message.Length; i++) { int index = _latinUpper.IndexOf(message[i]); //записываю числа _arrayEncryptData[i] = index;//ЕСЛИ ДОЕБЕТСЯ хули 2-27, а не 0-26 убрать +2 нужго } _ecnryptedDataArray = new int[_arrayEncryptData.Length]; for (int i = 0; i < _arrayEncryptData.Length; i++) { _ecnryptedDataArray[i] = EncryptionAlgorithmWithC(_arrayEncryptData[i], key); } Console.WriteLine("Данные успешно зашифрованы: "); foreach (var data in _ecnryptedDataArray) { Console.Write(data + " "); } } if (type == "C") { _arrayEncryptData = new int[message.Length]; for (int i = 0; i < message.Length; i++) { int index = _cyrillicUpper.IndexOf(message[i]); //записываю числа _arrayEncryptData[i] = index;//ЕСЛИ ДОЕБЕТСЯ хули 2-27, а не 0-26 убрать +2 нужго } _ecnryptedDataArray = new int[_arrayEncryptData.Length]; for (int i = 0; i < _arrayEncryptData.Length; i++) { _ecnryptedDataArray[i] = EncryptionAlgorithmWithC(_arrayEncryptData[i], key); } } if (type == "D") { } } private int EncryptionAlgorithmWithC(int digit, Dictionary<int, int> key) { int encryptionDigit = digit; int e = key.Keys.First(); int r = key[e]; return _algorithms.ModPow(encryptionDigit, e, r) % r; } //------------------------------------------------------------------------------------------------------------------------------------------------------------------ //блок расшифровки данных //------------------------------------------------------------------------------------------------------------------------------------------------------------------ public void DecryptionRSA() { Console.WriteLine("Расшифрованный массив данных: "); _resultDecryptionArray = DecryptionAlgorithmRSA(); foreach (var i in _resultDecryptionArray) Console.Write(i + " "); Console.WriteLine(); string decryptedMessage = ConvertNumbersToLetters(_resultDecryptionArray, _typeInputValues); Console.WriteLine("Расшифрованное сообщение: "); Console.WriteLine(decryptedMessage); } public int[] DecryptionAlgorithmRSA() { DecryptionInFile(); int[] arrayEncryption = new int[_encryptionDataArrayInFile.Length]; for (int i = 0; i < _encryptionDataArrayInFile.Length; i++) { arrayEncryption[i] = Decryption(_encryptionDataArrayInFile[i]); } return arrayEncryption; } private int Decryption(int c) { int dexp = _secretKey.Keys.First(); int r = _secretKey[dexp]; // Console.WriteLine($"{dexp}, {r}"); return _algorithms.ModPow(c, dexp, r); } private void DecryptionInFile() { _encryptionDataArrayInFile = _fileService.OpenFile(_outputPathFile); if (_encryptionDataArrayInFile.Length == 0) Console.WriteLine("Ошибка, файл пуст..."); foreach (var i in _encryptionDataArrayInFile) Console.Write(i + " "); Console.WriteLine(); } private string ConvertNumbersToLetters(int[] numbers, string type) { string result = ""; string alphabet = ""; if (type == "L") { alphabet = _latinUpper; } else if (type == "C") { alphabet = _cyrillicUpper; } else if (type == "D") { return string.Join("", numbers); } int letterIndex = 0; for (int i = 0; i < _originalInputData.Length; i++) { if (_originalInputData[i] == ' ') { result += ' '; } else { if (letterIndex < numbers.Length) { int number = numbers[letterIndex]; int charIndex = number; if (charIndex >= 0 && charIndex < alphabet.Length) { result += alphabet[charIndex]; } else { result += '?'; // если индекс вне диапазона } letterIndex++; } } } return result; } //------------------------------------------------------------------------------------------------------------------------------------------------------------------ //блок корректности ввода данных(вынусу потом в отдельный класс ValidateDataClass) //------------------------------------------------------------------------------------------------------------------------------------------------------------------ private int IsCorrectInputNumber() { int number = 0; bool isCorrect = false; while (!isCorrect) { isCorrect = int.TryParse(Console.ReadLine(), out number); } return number; } private void IsCorrectInputData() { bool isCorrect = false; while (!isCorrect) { Console.WriteLine("Введите выражение для шифрования: "); string input = Console.ReadLine(); if (!string.IsNullOrEmpty(input) && IsValidInput(input)) { _originalInputData = input; _inputData = input.Replace(" ", ""); isCorrect = true; } else { Console.WriteLine("Ошибка! Разрешены только буквы (русские/английские) и цифры."); } } } private bool IsValidInput(string input) { foreach (char c in input) { bool isLatin = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); bool isCyrillic = (c >= 'А' && c <= 'Я') || (c >= 'а' && c <= 'я') || c == 'Ё' || c == 'ё'; bool isDigit = (c >= '0' && c <= '9'); bool isWhitespase = (c == ' '); if (!(isLatin || isCyrillic || isDigit || isWhitespase)) { return false; } } return true; } private bool IsLatin(string text) { foreach (char c in text) { if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) return false; } return true; } private bool IsCyrillic(string text) { foreach (char c in text) { if (!((c >= 'А' && c <= 'Я') || (c >= 'а' && c <= 'я') || c == 'Ё' || c == 'ё')) return false; } return true; } private bool IsDigits(string text) { foreach (char c in text) { if (!(c >= '0' && c <= '9')) return false; } return true; } //------------------------------------------------------------------------------------------------------------------------------------------------------------------ }
} с большими числами не расшифровывает, если нужно пришли мне код с long и добавиь исправдения, но мою логиу не меняй
Да — тут уже не одна, а сразу три проблемы:
CAT -> AA?Ты ввёл:
q = 1019p = 1000e = 2А для RSA это плохо по двум причинам:
p = 1000 не простое числоRSA требует, чтобы p и q были простыми.
У тебя:
csharpp = 1000
это составное число. Тогда формула
csharpfuctionEiler = (_q - 1) * (_p - 1);
уже неверна для RSA.
e = 2 не взаимно просто с φ(n)У тебя:
csharpφ(n) = (1019 - 1) * (1000 - 1) = 1018 * 999
1018 * 999 — чётное число, значит оно делится на 2.
Следовательно:
csharpgcd(2, φ(n)) != 1
А в RSA обязательно нужно:
csharpgcd(e, φ(n)) == 1
Иначе обратной степени d нормально не существует.
intВот это уже похоже на твою главную жалобу:
“с большими числами не расшифровывает”
Даже если n ещё помещается в int, при быстром возведении в степень внутри ModPow почти наверняка происходит переполнение при умножении:
csharpa * a result * a
если всё на int.
Я не буду менять твою структуру класса и общую логику.
Нужно сделать только это:
int на long там, где работают ключи и шифротекстp и q простыеgcd(e, φ(n)) == 1ModPow на longНиже версия максимально близкая к твоей, без перелома логики.
csharpusing System; using System.Collections.Generic; using System.Linq; namespace ThirdTaskAlgorithm { class RSA { private long _q { get; set; } private long _p { get; set; } private long _b { get; set; } private string _outputPathFile { get; set; } private string _inputPathFile { get; set; } private string _latinUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private string _latinLower = "abcdefghijklmnopqrstuvwxyz"; private string _cyrillicUpper = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; private string _cyrillicLower = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"; private string _digits = "0123456789"; private FileService _fileService; private Dictionary<long, long> _secretKey { get; set; } private long[] _arrayEncryptData { get; set; } private string _typeInputValues { get; set; } private long[] _resultDecryptionArray { get; set; } private long[] _ecnryptedDataArray { get; set; } private long[] _encryptionDataArrayInFile { get; set; } private Algorithms _algorithms; private string _inputData { get; set; } private string _originalInputData { get; set; } public long Q { get => _q; set => _q = value; } public long P { get => _p; set => _p = value; } public long B { get => _b; set => _b = value; } public RSA() { _algorithms = new Algorithms(); _fileService = new FileService(); } public RSA(string inputPath, string outputPath) { _algorithms = new Algorithms(); _fileService = new FileService(); _inputPathFile = inputPath; _outputPathFile = outputPath; } public void EncryptionRSA() { Console.WriteLine("Введите данные в последовательности: Q, P, B"); _q = IsCorrectInputNumber(); _p = IsCorrectInputNumber(); if (!IsPrime(_q) || !IsPrime(_p)) { Console.WriteLine("Ошибка! Q и P должны быть простыми числами."); return; } long r = _q * _p; long fuctionEiler = (_q - 1) * (_p - 1); long exponent = IsCorrectInputNumber(); if (!(1 < exponent && exponent < fuctionEiler)) { Console.WriteLine("Ошибка! Некорректное значение открытой экспоненты."); return; } if (Gcd(exponent, fuctionEiler) != 1) { Console.WriteLine("Ошибка! Экспонента должна быть взаимно простой с функцией Эйлера."); return; } long[] dExponentArray = _algorithms.AlgorithmEuclidex(exponent, fuctionEiler); long x1 = dExponentArray[0]; if (x1 < 0) { x1 += fuctionEiler; } long dExponent = x1; Dictionary<long, long> key = new Dictionary<long, long>() { { exponent, r } }; _secretKey = new Dictionary<long, long>() { { dExponent, r } }; IsCorrectInputData(); if (IsLatin(_inputData)) { _typeInputValues = "L"; Encrypt("L", _inputData, key); EncryptionOnFile(_outputPathFile); } else if (IsCyrillic(_inputData)) { _typeInputValues = "C"; Encrypt("C", _inputData, key); EncryptionOnFile(_outputPathFile); } else if (IsDigits(_inputData)) { _typeInputValues = "D"; Encrypt("D", _inputData, key); EncryptionOnFile(_outputPathFile); } } private void EncryptionOnFile(string path) { _fileService.SaveToFile(_ecnryptedDataArray, path); Console.WriteLine("Данные успешно сохранены в файл: "); } private void Encrypt(string type, string message, Dictionary<long, long> key) { message = message.ToUpper(); if (type == "L") { _arrayEncryptData = new long[message.Length]; for (int i = 0; i < message.Length; i++) { int index = _latinUpper.IndexOf(message[i]); _arrayEncryptData[i] = index; } _ecnryptedDataArray = new long[_arrayEncryptData.Length]; for (int i = 0; i < _arrayEncryptData.Length; i++) { _ecnryptedDataArray[i] = EncryptionAlgorithmWithC(_arrayEncryptData[i], key); } Console.WriteLine("Данные успешно зашифрованы: "); foreach (var data in _ecnryptedDataArray) { Console.Write(data + " "); } Console.WriteLine(); } if (type == "C") { _arrayEncryptData = new long[message.Length]; for (int i = 0; i < message.Length; i++) { int index = _cyrillicUpper.IndexOf(message[i]); _arrayEncryptData[i] = index; } _ecnryptedDataArray = new long[_arrayEncryptData.Length]; for (int i = 0; i < _arrayEncryptData.Length; i++) { _ecnryptedDataArray[i] = EncryptionAlgorithmWithC(_arrayEncryptData[i], key); } Console.WriteLine("Данные успешно зашифрованы: "); foreach (var data in _ecnryptedDataArray) { Console.Write(data + " "); } Console.WriteLine(); } if (type == "D") { } } private long EncryptionAlgorithmWithC(long digit, Dictionary<long, long> key) { long e = key.Keys.First(); long r = key[e]; return _algorithms.ModPow(digit, e, r); } public void DecryptionRSA() { Console.WriteLine("Расшифрованный массив данных: "); _resultDecryptionArray = DecryptionAlgorithmRSA(); foreach (var i in _resultDecryptionArray) Console.Write(i + " "); Console.WriteLine(); string decryptedMessage = ConvertNumbersToLetters(_resultDecryptionArray, _typeInputValues); Console.WriteLine("Расшифрованное сообщение: "); Console.WriteLine(decryptedMessage); } public long[] DecryptionAlgorithmRSA() { DecryptionInFile(); long[] arrayEncryption = new long[_encryptionDataArrayInFile.Length]; for (int i = 0; i < _encryptionDataArrayInFile.Length; i++) { arrayEncryption[i] = Decryption(_encryptionDataArrayInFile[i]); } return arrayEncryption; } private long Decryption(long c) { long dexp = _secretKey.Keys.First(); long r = _secretKey[dexp]; return _algorithms.ModPow(c, dexp, r); } private void DecryptionInFile() { _encryptionDataArrayInFile = _fileService.OpenFile(_outputPathFile); if (_encryptionDataArrayInFile.Length == 0) Console.WriteLine("Ошибка, файл пуст..."); foreach (var i in _encryptionDataArrayInFile) Console.Write(i + " "); Console.WriteLine(); } private string ConvertNumbersToLetters(long[] numbers, string type) { string result = ""; string alphabet = ""; if (type == "L") { alphabet = _latinUpper; } else if (type == "C") { alphabet = _cyrillicUpper; } else if (type == "D") { return string.Join("", numbers); } int letterIndex = 0; for (int i = 0; i < _originalInputData.Length; i++) { if (_originalInputData[i] == ' ') { result += ' '; } else { if (letterIndex < numbers.Length) { long number = numbers[letterIndex]; int charIndex = (int)number; if (charIndex >= 0 && charIndex < alphabet.Length) { result += alphabet[charIndex]; } else { result += '?'; } letterIndex++; } } } return result; } private long IsCorrectInputNumber() { long number = 0; bool isCorrect = false; while (!isCorrect) { isCorrect = long.TryParse(Console.ReadLine(), out number); } return number; } private void IsCorrectInputData() { bool isCorrect = false; while (!isCorrect) { Console.WriteLine("Введите выражение для шифрования: "); string input = Console.ReadLine(); if (!string.IsNullOrEmpty(input) && IsValidInput(input)) { _originalInputData = input; _inputData = input.Replace(" ", ""); isCorrect = true; } else { Console.WriteLine("Ошибка! Разрешены только буквы (русские/английские) и цифры."); } } } private bool IsValidInput(string input) { foreach (char c in input) { bool isLatin = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); bool isCyrillic = (c >= 'А' && c <= 'Я') || (c >= 'а' && c <= 'я') || c == 'Ё' || c == 'ё'; bool isDigit = (c >= '0' && c <= '9'); bool isWhitespase = (c == ' '); if (!(isLatin || isCyrillic || isDigit || isWhitespase)) { return false; } } return true; } private bool IsLatin(string text) { foreach (char c in text) { if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) return false; } return true; } private bool IsCyrillic(string text) { foreach (char c in text) { if (!((c >= 'А' && c <= 'Я') || (c >= 'а' && c <= 'я') || c == 'Ё' || c == 'ё')) return false; } return true; } private bool IsDigits(string text) { foreach (char c in text) { if (!(c >= '0' && c <= '9')) return false; } return true; } private bool IsPrime(long n) { if (n < 2) return false; if (n == 2) return true; if (n % 2 == 0) return false; for (long i = 3; i * i <= n; i += 2) { if (n % i == 0) return false; } return true; } private long Gcd(long a, long b) { while (b != 0) { long t = a % b; a = b; b = t; } return a; } } }
AlgorithmsЕсли у тебя ModPow до сих пор на int, то проблема останется.
Сделай так:
csharpclass Algorithms { public long ModPow(long value, long power, long mod) { long result = 1; value %= mod; while (power > 0) { if ((power & 1) == 1) result = (result * value) % mod; value = (value * value) % mod; power >>= 1; } return result; } public long[] AlgorithmEuclidex(long a, long b) { long x0 = 1, y0 = 0; long x1 = 0, y1 = 1; while (b != 0) { long q = a / b; long temp = a % b; a = b; b = temp; long newX = x0 - q * x1; long newY = y0 - q * y1; x0 = x1; y0 = y1; x1 = newX; y1 = newY; } return new long[] { x0, y0 }; } }
long[]Если сейчас там int[], поменяй на long[].
Например:
csharppublic void SaveToFile(long[] data, string path) { File.WriteAllText(path, string.Join(" ", data)); } public long[] OpenFile(string path) { if (!File.Exists(path)) return new long[0]; string content = File.ReadAllText(path); if (string.IsNullOrWhiteSpace(content)) return new long[0]; return content .Split(new[] { ' ', '\r', '\n', '\t' }, StringSplitOptions.RemoveEmptyEntries) .Select(long.Parse) .ToArray(); }
Например, для CAT:
q = 1019p = 1013e = 17Это нормальный вариант.
А вот так — нельзя:
p = 1000 ❌ не простоеe = 2 ❌ не взаимно просто с φ(n)4 0 361, а потом 0 0 138353Это уже явный сигнал, что:
d найден некорректно из-за плохого eModPow переполнениеЕсли совсем коротко:
text1019 1000 2
text1019 1013 17
И обязательно:
int для RSA заменить на longModPow сделать на longIsPrime(p)IsPrime(q)Gcd(e, phi) == 1Если хочешь, я следующим сообщением могу тебе дать готовый FileService.cs и Algorithms.cs целиком, чтобы ты просто вставил без ручной переделки.