Покорение RSA на C#

Ранее я разработал компоненту на C# для подключения терминала с биометрией Anviz к 1С. Но я сделал ее для единственного клиента. А для того, чтобы ее можно было использовать для большого количества клиентов, нужно сделать проверку серийного номера.

Для проверки я ранее использовал RSA, но это было на Visual Basic. Код проверки выглядел примерно так:

Function CheckLicense(Serial)
    Dim i As Long
    Dim CurrLic As String
    Dim CurrSerial As String
    Dim CurrMask As String
    Dim strDeCrypt As String
 
 
    CheckLicense = False 'By default
    On Error GoTo errtrap
 
    For i = LBound(SerialsLicens) To UBound(SerialsLicens)
        CurrLic = SerialsLicens(i)
        CurrSerial = Left(CurrLic, 16)
        'Seek for serial
        'MsgBox "Curr serial: " & CurrSerial
        If CurrSerial = Serial Then
            CurrMask = Mid(CurrLic, 18)
            'MsgBox "Curr mask: " & CurrMask
            'if already checked before
            If CurrMask = "+" Then
                CheckLicense = True
                Exit Function
            Else
                strDeCrypt = mpModExp(CurrMask, PublicKeyExp, PublicKeyModulus)
                'MsgBox "Decrypt: " & strDeCrypt
                If Val(strDeCrypt) = Val(CurrSerial) Then
                    CheckLicense = True
                    SerialsLicens(i) = CurrSerial & ":+"
                    'MsgBox "Memory for serial: " & SerialsLicens(i)
                    Exit Function
                Else
                    Exit Function
                End If
 
            End If
 
        End If
    Next
 
    Exit Function
 
errtrap:
    MsgBox "Error CheckLicense:" & err.Description & " " & err.HelpContext
End Function

Публичный ключ состоял из степени PublicKeyExp и модуля PublicKeyModulus. Предварительно я проверял корректность самого публичного ключа. И потом восстанавливал публичным ключом зашифрованную лицензию. Если восстанавливался серийный номер, равный текущему, значит проверка прошла.

Мои первые шаги в C# в RSA были неуклюжими.

Конечно в Microsoft есть готовый RSA-класс для шифрования, но он очень усложнен, я не понял, как им пользоваться.

Поэтому я нашел готовый пример программы RSA-шифрования, использующую класс Biginteger.

Сначала я перенес свой проект в другой каталог и не мог найти, где указать, какой из двух проектов сборки должен запускаться (один проект — библиотека, другой — тестовая форма). В итоге нашел:

Следующей проблемой оказалось то, что C# ругался на Biginteger. Я нашел, что нужно подключить библиотеку Numeric. Но она не подключалась. Нашел, что потому, что у меня сборка под Net 2.0, а надо под Net 4.0. Поменял целевую платформу, все заработало:

Возникла очередная проблема — я не знал, как в C# добавлять модули для библиотечных функций. Но примерно понимал, что их можно заменить static-классами. Нашел пример static-классов. Сделал по аналогии:

using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text;
 
namespace AnvizCCH
{
    static public class myRSA
    {
 
        static public string RSA_Decode(string input, long d, long n)
        {
 
            string result = "";
 
            //About hex: https://stackoverflow.com/questions/30119174/converting-a-hex-string-to-its-biginteger-equivalent-negates-the-value
            BigInteger bi = BigInteger.Parse("0" + input, System.Globalization.NumberStyles.AllowHexSpecifier);
            bi = BigInteger.Pow(bi, (int) d);
 
            BigInteger n_ = new BigInteger((int)n);
 
            bi = bi % n_;
 
            result = bi.ToString();
 
            return result;
        }
    }
}
 

Нашел один небольшой нюанс, что в начало числа надо добавлять ноль, чтобы не получать отрицательных значений Biginteger.

У меня еще была особенность в том, что я использую шестнадцатеричные значения чисел. Поэтому пришлось решать и эту проблему.

В итоге у меня получилось сделать первые шаги в декодировании закодированного ключа и я наполнился оптимизмом, что смогу решить эту задачу — основные препоны остались позади.

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

комментариев 12

  1. fajij28770:

    >Конечно в Microsoft есть готовый RSA-класс для шифрования, но он очень усложнен, я не понял, как им пользоваться.
    >Поэтому я нашел готовый пример программы RSA-шифрования, использующую класс Biginteger.

    как всегда глобально и надежно 🙂

    • У тебя есть способ решения проблемы? Я читал про Микрософтовский RSA, что он не умеет шифровать открытым ключом, например. Просто подумали, что это не нужно.

      • fajij28770:

        google://.net rsa example
        вторая ссылка на stackoverflow с подробным примером

        • Я, кстати, видел этот пост, вы же про этот?
          Только мне он ничего не подсказал по теме, почему RSA не расшифровывает.
          У Микрософт, как всегда, плохо с диагностикой ошибок.

  2. Zuko:

    В смысле «он не умеет шифровать открытым ключом»?
    RSA (аббревиатура от фамилий Rivest, Shamir и Adleman) — криптографический алгоритм с открытым ключом

    • Я не про RSA в целом, а про его реализацию от Microsoft в NET.
      Видел где-то в обсуждениях, была проблема шифровать открытым ключом. Закрытым — проблем нет. Но иногда надо наоборот.

      • fajij28770:

        но ведь закрытый ключ используется только для дешифрации ))))

        • нет. Бывают разные ситуации.
          Например, если нужно проверить корректность подписи, то шифруем закрытым.
          если нужно передать в целостности, то открытым.

  1. 06.07.2021

    […] прошлой статье про RSA я написал, как реализовал на C# базовый математический алгоритм […]

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *