Шифрование данных с помощью алгоритма AES-256 (C#)

В текущей статье напишу два метода для шифрования потока байт с помощью алгоритма AES-256, и расшифровки обратно в массив байт.

Что такое AES-256

AES-256 представляет собой алгоритм шифрования с симметричным ключом. Это означает, что для шифрования и дешифрирования используется один и тот же криптографический ключ.

Symmetric key, симметричный ключ

Алгоритм может пригодиться где угодно — от шифрования файлов до защиты данных, передаваемых по открытым каналам.

Реализация алгоритма на C#

Для реализации алгоритма нужно подключить библиотеку System.Security.Cryptography и указать пространство имен:

using System.Security.Cryptography;

Далее напишем метод для шифрования данных:

/// <summary>
/// Шифрует исходное сообщение AES ключом (добавляет соль)
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
public static byte[] ToAes256(string src)
{
  //Объявляем объект класса AES
  Aes aes = Aes.Create();
  //Генерируем соль
  aes.GenerateIV();
  //Присваиваем ключ. aeskey - переменная (массив байт), сгенерированная методом GenerateKey() класса AES
  aes.Key = aeskey;
  byte[] encrypted;
  ICryptoTransform crypt = aes.CreateEncryptor(aes.Key, aes.IV);
  using (MemoryStream ms = new MemoryStream())
  {
    using (CryptoStream cs = new CryptoStream(ms, crypt, CryptoStreamMode.Write))
    {
      using (StreamWriter sw = new StreamWriter(cs))
      {
        sw.Write(src);
      }
    }
    //Записываем в переменную encrypted зашиврованный поток байтов
    encrypted = ms.ToArray();
  }
  //Возвращаем поток байт + крепим соль
  return encrypted.Concat(aes.IV).ToArray();
}

Метод, для дешифрирования потока байтов:

/// <summary>
/// Расшифровывает криптованного сообщения
/// </summary>
/// <param name="shifr">Шифротекст в байтах</param>
/// <returns>Возвращает исходную строку</returns>
public static string FromAes256(byte[] shifr)
{
  byte[] bytesIv = new byte[16];
  byte[] mess = new byte[shifr.Length - 16];

  //Списываем соль
  for (int i = shifr.Length - 16, j = 0; i < shifr.Length; i++, j++)
    bytesIv[j] = shifr[i];

  //Списываем оставшуюся часть сообщения
  for (int i = 0; i < shifr.Length - 16; i++)
    mess[i] = shifr[i];

  //Объект класса Aes
  Aes aes = Aes.Create();
  //Задаем тот же ключ, что и для шифрования
  aes.Key = aeskey;
  //Задаем соль
  aes.IV = bytesIv;
  //Строковая переменная для результата
  string text = "";
  byte[] data = mess;
  ICryptoTransform crypt = aes.CreateDecryptor(aes.Key, aes.IV);

  using (MemoryStream ms = new MemoryStream(data))
  {
    using (CryptoStream cs = new CryptoStream(ms, crypt, CryptoStreamMode.Read))
    {
      using (StreamReader sr = new StreamReader(cs))
      {
        //Результат записываем в переменную text в вие исходной строки
        text = sr.ReadToEnd();
      }
    }
  }
  return text;
}

Зашифрованное сообщение можно передавать в открытый канал. При перехвате злоумышленники обнаружат лишь шифр, с которым мало что смогут сделать.

Стоит отметить, что сам ключ стоит передавать по закрытому каналу либо используя алгоритмы шифрования с ассиметричным ключом. Например RSA.

Ключ AES шифруется открытым ключом RSA, передается в открытый канал, далее вторая сторона расшифровывает ключ AES закрытым ключом RSA.

Во время передачи шифра в открытый канал может произойти MITM атака — попытка подмены сообщения и т.п. злоумышленником.

Для проверки подлинности сообщения используйте цифровую подпись для каждого сообщения (вычисляется хеш, проверяемый получателем для проверки подлинности сообщения).

Данным методом можно воспользоваться, чтобы зашифровать данные другими алгоритмами с симметричным ключом, например TripleDes.

Как прочитать Excel с помощью OleDB (C#)

В этой статье опишу как прочитать Excel с помощью OleDB.

Иногда бывает нужно вытянуть таблицу из Excel документа, записать в DataTable для последующей обработки.

Не всегда это удобно делать с помощью циклов, поэтому будем считывать таблицы, содержащиеся в документе и запрашивать из них данные с помощью SQL запросов.

oledb C#

Определение строки подключения

Для разных версий Excel будут свои строки подключения.

Строка подключения для Excel 2007 и более новых версий

//Можно использовать, если количество строк менее 65536
Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=Yes'

//Если строк больше 65536
Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties="Excel 12.0 Xml;HDR=YES";

Для работы с данными версиями необходимо установить Microsoft Access Database Engine 2010 Redistributable.

Так же C# может выбрасывать исключения по поводу недостающих драйверов. В этом случае необходимо скачать соответствующие драйверы с сайта Microsoft.

Строка подключения для более ранних версий

Строка подключения для Excel версии 2003 может иметь такой вид:

Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 8.0;HDR=Yes'

Если C# выбросит исключение, скачайте недостающий драйвер, Visual Studio подскажет, какой.

Как сделать SQL запрос из таблицы Excel

Для выполнения SQL запроса нужно найти таблицу в документе и выполнить к ней запрос:

//Объявляем OleDB соединение
using(OleDbConnection conn = new OleDbConnection(conStr))
{
  //Открываем подключение
  conn.Open();
  //Запрашиваем таблицы
  DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
  DataRow schemaRow = schemaTable.Rows[0];
  //Получаеи имя таблицы
  string sheet = schemaRow["TABLE_NAME"].ToString();
  //Объявляем команду
  OleDbCommand com = conn.CreateCommand();
  //Создаем SQL запрос
  com.CommandText = "SELECT * FROM [" + sheet + "]";
  //Выполняем SQL запрос
  OleDbDataReader reader = com.ExecuteReader();
  //Записываем результат в DataTable
  DataTable table = new DataTable();
  table.Load(reader);
  //Выводим DataTable в таблицу на форму (если нужно)
  gridControl1.DataSource = table;
}

На этом шаге мы имеем считанные данные из Excel документа в DataTable.

После обработки данных можно сохранить данные в другой документ или оформить сводную таблицу.

Как работать с Excel с помощью C# обсуждалось ранее.

Так же можете посмотреть, как работать со сводными таблицами в Excel с помощью C# и редактора VBA, встроенного в Excel.

Создаем сводные таблицы на C# в Excel

Сегодня программируем сводные таблицы на C#. Для этого надо будет иметь заготовленную таблицу с данными (обычную).

Заготовленная таблица будет иметь данные о телефонных звонках.

Пример сводной таблицы:

Сводные таблицы на C#

Открываем документ и создаем диапазоны для сводной таблицы

Откроем Excel документ с таблицей:

ex.Workbooks.Open("Excel.xlsx",
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);

Далее создаем диапазон из одной ячейки, в которой указываем, куда будет помещаться сводная таблица:

Excel.Range pivotDestination = sheetPivot.get_Range("A1", "A1");

Объявляем диапазон сводной таблицы:

Excel.Range all = sheetPivot.get_Range("A1", "D1000");

Пишем код создания сводной таблицы

Код для создания сводной таблицы из обычной таблицы с данными имеет такой вид:

workBook.PivotTableWizard(
  Excel.XlPivotTableSourceType.xlDatabase,
all,                        //Таблица, на основе которой строим сводную
pivotDestination,              //Где сохранять
"NumberA",                        //Название таблицы
true,
true,
true,
true,
Type.Missing,
Type.Missing,
false,
false,
Excel.XlOrder.xlDownThenOver,
0,
Type.Missing,
Type.Missing
);

Распределяем поля сводной таблицы

Далее надо определить, какие поля будут отвечать за значения, за столбцы и строки.

Для этого создаем экземпляры полей на основе заголовков столбцов таблицы:

//Создаем поля таблицы
Excel.PivotTable pivotTable = (Excel.PivotTable)sheetPivot.PivotTables("Number");
Excel.PivotField Y = ((Excel.PivotField)pivotTable.PivotFields("Y"));
Excel.PivotField M = ((Excel.PivotField)pivotTable.PivotFields("M"));
Excel.PivotField Src_country = ((Excel.PivotField)pivotTable.PivotFields("Country"));
Excel.PivotField Operator_Name = ((Excel.PivotField)pivotTable.PivotFields("Operator"));
Excel.PivotField Minutes = ((Excel.PivotField)pivotTable.PivotFields("Minutes"));

Распределяем поля:

//Расставляем строки, столбцы и данные
Y.Orientation = Excel.XlPivotFieldOrientation.xlColumnField;
M.Orientation = Excel.XlPivotFieldOrientation.xlColumnField;
Src_country.Orientation = Excel.XlPivotFieldOrientation.xlRowField;
Operator_Name.Orientation = Excel.XlPivotFieldOrientation.xlRowField;
Minutes.Orientation = Excel.XlPivotFieldOrientation.xlDataField;
//Функция, применяемая к данным - есть еще количество, MAX, MIN и т.д.
Minutes.Function = Excel.XlConsolidationFunction.xlSum;

Создаем сводную таблицу без исходной таблицы с данными

Описываю, как создать сводную таблицу на основе SQL-запроса к БД.

Для этого понадобится библиотека ADODB (adodb.dll можно скачать в интернете).

Подключим adodb.dll к проекту:

using ADODB;

Объявим строку подключения (драйвер SQLOLEDB.1):

Provider=SQLOLEDB.1;Password=123456;Persist Security Info=True;User ID=sqlserver;Initial Catalog=DBName;Data Source=serverNameOrIp

Далее пишем код для работы со сводной таблицей:

//Создаем подключение и открываем его
ADODB.Connection sql = new Connection();
sql.CursorLocation = ADODB.CursorLocationEnum.adUseClient;
sql.ConnectionString = conString;
sql.Open();

//Объявляем команду. Здесь функция getQuery() возвращает SQL-запрос
ADODB.Command cmd = new Command();
cmd.CommandType = CommandTypeEnum.adCmdText;
cmd.CommandText = getQuery();
cmd.CommandTimeout = 5000;
cmd.ActiveConnection = sql;

//Объявляем Recordset и выполняем запрос, сохраняя в него данные
ADODB.Recordset rs = new Recordset();
rs.Open(cmd, Type.Missing, ADODB.CursorTypeEnum.adOpenForwardOnly, ADODB.LockTypeEnum.adLockReadOnly, 1);
//тут хранится результат запроса

Excel.PivotCache pc = wb.PivotCaches().Add(
Excel.XlPivotTableSourceType.xlExternal
, Type.Missing);

pc.Recordset = rs;
//Ссылка на все сводные таблицы на листе
Excel.PivotTables pts = (Excel.PivotTables)sheet.GetType().InvokeMember("PivotTables", System.Reflection.BindingFlags.GetProperty, null, sheet, null);
//Создаем новую сводную таблицу
Excel.PivotTable pt = pts.Add(pc, sheet.get_Range("A3", Type.Missing), "NumA", Type.Missing, Excel.XlPivotTableVersionList.xlPivotTableVersionCurrent);

//Распределяю поля и настраиваю форматы полей
((Excel.PivotField)pt.PivotFields("Year")).Orientation = Excel.XlPivotFieldOrientation.xlColumnField;
((Excel.PivotField)pt.PivotFields("Month")).Orientation = Excel.XlPivotFieldOrientation.xlColumnField;
((Excel.PivotField)pt.PivotFields("Country")).Orientation = Excel.XlPivotFieldOrientation.xlRowField;
((Excel.PivotField)pt.PivotFields("Operator")).Orientation = Excel.XlPivotFieldOrientation.xlRowField;
((Excel.PivotField)pt.PivotFields("Minutes")).Orientation = Excel.XlPivotFieldOrientation.xlDataField;
((Excel.PivotField)pt.PivotFields("Сумма по полю Minutes")).Function = Excel.XlConsolidationFunction.xlSum;
((Excel.PivotField)pt.PivotFields("Сумма по полю Minutes")).NumberFormat = "# ##0";
((Excel.PivotField)pt.PivotFields("Operator")).ShowDetail=false;
((Excel.PivotField)pt.PivotFields("Country")).ShowDetail = false;

pt.TableStyle2 = "PivotStyleMedium13";     //Стиль сводной таблицы. Взял через VBA

При работе со сводными таблицами так же окажет помощь встроенный в Excel редактор VBA, о котором речь шла в теме Работа с Excel с помощью C# (Microsoft.Office.Interop.Excel).

Работа с Excel с помощью C# (Microsoft.Office.Interop.Excel)

Оставляю заметку по работе с Excel с помощью C#.

Привожу фрагменты кода, которые искал когда-то сам для работы с Excel документами.

Наработки очень пригодились в работе для формирования отчетности.

Прежде всего нужно подключить библиотеку Microsoft.Office.Interop.Excel.

Подключение Microsoft.Office.Interop.Excel
Visual Studio здесь довольно старой версии. Если у вас версия новая, отличаться будет только вид окна.

Далее создаем псевдоним для работы с Excel:

using Excel = Microsoft.Office.Interop.Excel;

//Объявляем приложение
Excel.Application ex = new Microsoft.Office.Interop.Excel.Application();

//Отобразить Excel
ex.Visible = true;

//Количество листов в рабочей книге
ex.SheetsInNewWorkbook = 2;

//Добавить рабочую книгу
Excel.Workbook workBook = ex.Workbooks.Add(Type.Missing);

//Отключить отображение окон с сообщениями
ex.DisplayAlerts = false;                                       

//Получаем первый лист документа (счет начинается с 1)
Excel.Worksheet sheet = (Excel.Worksheet)ex.Worksheets.get_Item(1);

//Название листа (вкладки снизу)
sheet.Name = "Отчет за 13.12.2017";

//Пример заполнения ячеек
for (int i = 1; i <= 9; i++)
{
  for (int j = 1; j < 9; j++)
  sheet.Cells[i, j] = String.Format("Boom {0} {1}", i, j);
}

//Захватываем диапазон ячеек
Excel.Range range1 = sheet.get_Range(sheet.Cells[1, 1], sheet.Cells[9, 9]);

//Шрифт для диапазона
range1.Cells.Font.Name = "Tahoma";
//Размер шрифта для диапазона
range1.Cells.Font.Size = 10;

//Захватываем другой диапазон ячеек
Excel.Range range2 = sheet.get_Range(sheet.Cells[1, 1], sheet.Cells[9, 2]);
range2.Cells.Font.Name = "Times New Roman";

//Задаем цвет этого диапазона. Необходимо подключить System.Drawing
range2.Cells.Font.Color = ColorTranslator.ToOle(Color.Green);
//Фоновый цвет
range2.Interior.Color = ColorTranslator.ToOle(Color.FromArgb(0xFF, 0xFF, 0xCC));

Расстановка рамок.

Расставляем рамки со всех сторон:

range2.Borders.get_Item(Excel.XlBordersIndex.xlEdgeBottom).LineStyle = Excel.XlLineStyle.xlContinuous;
range2.Borders.get_Item(Excel.XlBordersIndex.xlEdgeRight).LineStyle = Excel.XlLineStyle.xlContinuous;
range2.Borders.get_Item(Excel.XlBordersIndex.xlInsideHorizontal).LineStyle = Excel.XlLineStyle.xlContinuous;
range2.Borders.get_Item(Excel.XlBordersIndex.xlInsideVertical).LineStyle = Excel.XlLineStyle.xlContinuous;
range2.Borders.get_Item(Excel.XlBordersIndex.xlEdgeTop).LineStyle = Excel.XlLineStyle.xlContinuous;

Цвет рамки можно установить так:

range2.Borders.Color = ColorTranslator.ToOle(Color.Red);

Выравнивания в диапазоне задаются так:

rangeDate.VerticalAlignment = Excel.XlVAlign.xlVAlignCenter;
rangeDate.HorizontalAlignment = Excel.XlHAlign.xlHAlignLeft;

Формулы

Определим задачу: получить сумму диапазона ячеек A4:A10.

Для начала снова получим диапазон ячеек:

Excel.Range formulaRange = sheet.get_Range(sheet.Cells[4, 1], sheet.Cells[9, 1]);

Далее получим диапазон вида A4:A10 по адресу ячейки ( [4,1]; [9;1] ) описанному выше:

string adder = formulaRange.get_Address(1, 1, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing);

Теперь в переменной adder у нас хранится строковое значение диапазона ( [4,1]; [9;1] ), то есть A4:A10.

Вычисляем формулу:

//Одна ячейка как диапазон
Excel.Range r = sheet.Cells[10, 1] as Excel.Range;
//Оформления
r.Font.Name = "Times New Roman";
r.Font.Bold = true;
r.Font.Color = ColorTranslator.ToOle(Color.Blue);
//Задаем формулу суммы
r.Formula = String.Format("=СУММ({0}", adder);

Выделение ячейки или диапазона ячеек

Так же можно выделить ячейку или диапазон, как если бы мы выделили их мышкой:

sheet.get_Range("J3", "J8").Activate();
//или
sheet.get_Range("J3", "J8").Select();
//Можно вписать одну и ту же ячейку, тогда будет выделена одна ячейка.
sheet.get_Range("J3", "J3").Activate();
sheet.get_Range("J3", "J3").Select();

Авто ширина и авто высота

Чтобы настроить авто ширину и высоту для диапазона, используем такие команды:

range.EntireColumn.AutoFit(); 
range.EntireRow.AutoFit();

Получаем значения из ячеек

Чтобы получить значение из ячейки, используем такой код:

//Получение одной ячейки как ранга
Excel.Range forYach = sheet.Cells[ob + 1, 1] as Excel.Range;
//Получаем значение из ячейки и преобразуем в строку
string yach = forYach.Value2.ToString();

Добавляем лист в рабочую книгу

Чтобы добавить лист и дать ему заголовок, используем следующее:

var sh = workBook.Sheets;
Excel.Worksheet sheetPivot = (Excel.Worksheet)sh.Add(Type.Missing, sh[1], Type.Missing, Type.Missing);
sheetPivot.Name = "Сводная таблица";

Добавление разрыва страницы

//Ячейка, с которой будет разрыв
Excel.Range razr = sheet.Cells[n, m] as Excel.Range;
//Добавить горизонтальный разрыв (sheet - текущий лист)
sheet.HPageBreaks.Add(razr); 
//VPageBreaks - Добавить вертикальный разрыв

Сохраняем документ

ex.Application.ActiveWorkbook.SaveAs("doc.xlsx", Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

Как открыть существующий документ Excel

ex.Workbooks.Open(@"C:\Users\Myuser\Documents\Excel.xlsx",
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing, Type.Missing, Type.Missing,
  Type.Missing, Type.Missing);

Комментарии

При работе с Excel с помощью C# большую помощь может оказать редактор Visual Basic, встроенный в Excel.

Для этого в настройках ленты надо добавить пункт «Разработчик». Далее начинаем запись макроса, производим действия и останавливаем запись.

Далее заходим в редактор Visual Basic и смотрим код, который туда записался:

Vusial Basic (VBA)

Например:

Sub Макрос1()
'
' Макрос1 Макрос
'

'
    Range("E88").Select
    ActiveSheet.ListObjects.Add(xlSrcRange, Range("$A$1:$F$118"), , xlYes).Name = _
        "Таблица1"
    Range("A1:F118").Select
    ActiveSheet.ListObjects("Таблица1").TableStyle = "TableStyleLight9"
    Range("E18").Select
    ActiveWindow.SmallScroll Down:=84
End Sub

В данном макросе записаны все действия, которые мы выполнили во время его записи. Эти методы и свойства можно использовать в C# коде.

Данный метод так же может оказать помощь в формировании относительных формул, например, выполнить сложение чисел, находящиеся слева от текущей ячейки на 4 столбца, и т.п. Пример:

//Складываем значения предыдущих 12 ячеек слева
rang.Formula = "=СУММ(RC[-12]:RC[-1])";

Так же во время работы может возникнуть ошибка: метод завершен неверно. Это может означать, что не выбран лист, с которым идет работа.

Чтобы выбрать лист, выполните sheetData.Select(Type.Missing); где sheetData это нужный лист.

Пишем класс, описывающий рациональные дроби (C#)

Рациональные дроби

Рациональные дроби — это числа, представляемые обыкновенной дробью с числителем и знаменателем.

Рациональные дроби

В данной статье выкладываю код, который я написал для реализации класса рациональных дробей. Это было одно из заданий для получения сертификата курса проектирования на C#.

В представленном листинге ниже реализован данный класс:

Показать текст ->

В классе описаны методы выполнения арифметический операций с рациональными дробями:

  • Сложение и вычитание дробей через НОЗ (наименьший общий знаменатель);
  • Умножение и деление дробей;
  • Умножение дроби на число;
  • Преобразование числа к рациональной дроби (любое число это рациональная дробь, где взятое число делится на 1);
  • Преобразование рациональной дроби к десятичной;
  • Описаны функции нахождения НОЗ и сокращения рациональной дроби.

Перегрузка операторов и преобразования типов (C#)

Примеры перегрузки операторов

В данной рассматриваем примеры перегрузки операторов + и — в языке C#. Таким же образом можно перегрузить другие операторы, которые принимают два параметра.

Так же показываю как задать инструкцию явного преобразования типов из одного созданного класса в другой.

В коде ниже создано 2 класса: Vector и Coord. В классе Vector перегружены два бинарных оператора + и -.

В классе Coord объявлены только конструктор и два свойства X, Y, обозначающие координату.

С помощью инструкции public static explicit operator Coord(Vector v)  мы можем задать правило преобразования объекта класса Vector в объект класса Coord:

using System.IO;
using System;
using System.Text;

class Coord
{
  public int X {get;set;}
  public int Y {get;set;}
  
  public Coord(int x, int y)
  {
      this.X = x;
      this.Y = y;
  }
  
  public override string ToString()
  {
      return String.Format("Coord: X = {0}, Y = {1}", this.X, this.Y);
  }
}

class Vector
{
    //Объвляем автосвойства, чтобы не использовать public поля
  public int X {get;set;}
  public int Y {get;set;}

  public Vector(int x, int y)
  {
    this.X = x;
    this.Y = y;
  }

    //Оператор + принимает на вход 2 параметра
  public static Vector operator+(Vector v1, Vector v2)
  {
    return new Vector(v1.X + v2.X, v1.Y + v2.Y);
  }

    //Оператор - принимает на вход 2 параметра
  public static Vector operator-(Vector v1, Vector v2)
  {
    return new Vector(v1.X - v2.X, v1.Y - v2.Y);
  }

    //Переопределение метода ToString()
    public override string ToString()
    {
        return String.Format("Vector: X = {0}, Y = {1}", this.X, this.Y);
    }
    
    //Инструкция по явному преобразованию класса Vector в класс Coord
    //Вместо explicit можно написать implicit, тогда преобразование можно
    //будет делать неявным
    public static explicit operator Coord(Vector v)
    {
        return new Coord(v.X, v.Y);
    }
  
}

class Program
{
  static void Main()
  {
    Console.WriteLine("Start program.");
    Vector v1 = new Vector(10,20);
    Vector v2 = new Vector(15,50);
    Console.WriteLine(v1+v2);
    Console.WriteLine(v1-v2);
    //----------------------
    Coord c1 = new Coord(100,200);
    Console.WriteLine(c1); //Явное преобразование Vector в Coord
    Coord c2 = (Coord)(v1+v2);
    Console.WriteLine(c2);
  }
}

Результат работы программы:

Подключаемся к серверу MySQL через SSH для выполнения запросов (C#)

В данной записи показываю, как подключаться в MySQL через SSH с помощью C# и библиотеки Renci.SshNet
В среде Visual Studio (старше 2008) через систему управления пакетами Nuget добавляем библиотеку SshNet.
Добавляем библиотеку mysql.dll (Можно скачать connector на www.mysql.com).
Переходим к написанию кода. Объявляем SshClient:

private static SshClient client = new SshClient("120.20.20.20", "login_ssh", "password_ssh");

Настраиваем строку подключения к MySQL

Объявим строку подключения connBuilderIMSoverSSH и настроим ее:

private static MySqlConnectionStringBuilder connBuilderIMSoverSSH = new MySqlConnectionStringBuilder();

connBuilderIMSoverSSH.Server = "127.0.0.1";     //Текуший ПК
connBuilderIMSoverSSH.Port = 12140;               //Порт, который пробрасываем (Не обязательно такой. Можно пробросить любой свободный)
connBuilderIMSoverSSH.UserID = "login_mysql";
connBuilderIMSoverSSH.Password = "pass_mysql ";
connBuilderIMSoverSSH.Database = "Database_Name";

Пробрасываем порт для SSH

Проверяем, открыто ли подключение к SSH. Если не открыто, открываем:

if (!client.IsConnected)
{
  client.Connect();
  //Объявляем и инициализируем пробрасываемый порт
  ForwardedPortLocal port = new ForwardedPortLocal("127.0.0.1", 12140, "10.247.250.100", 3306);	//3306 - порт MySQL
  client.AddForwardedPort(port);
  //Открываем порт
  port.Start();
}

Выполняем запрос к MySQL через SSH

/// <summary>
/// Выбирает данные из новой системы через SSH
/// </summary>
/// <param name="query">Запрос</param>
/// <returns></returns>
public DataTable ExecuteSqlOverSSH(string query)
{
  DataTable table = new DataTable();
  //Открываем соединение с MySQL
  using (var sql = new MySqlConnection(connBuilderIMSoverSSH.ConnectionString))
  {
    sql.Open();
    var cmd = sql.CreateCommand();
    cmd.CommandTimeout = 600;
    cmd.CommandText = query;
    var rdr = cmd.ExecuteReader();
    table.Load(rdr);
  }

  return table;
}

В итоге мы получили функцию, которая возвращает результат запроса в БД MySQL через SSH в виде DataTable.