Проверка подписи OpenSSL RSA (PHP) с помощью .NET (VB)

Я хотел бы добиться чего-то, что я считал довольно простым:

A) Мой клиент VB.NET (в идеале ориентированный на Framework 4.0) отправляет текстовую строку на мой сервер Apache/PHP через HTTPS-запрос POST.

Б) Мой сервер отвечает подписью этой текстовой строки. Закрытый ключ, используемый Сервером, всегда один и тот же, а открытый ключ, используемый Клиентом, уже встроен в исходный код.

После изучения и прочтения большого количества документации я пришел к следующей стратегии и задал два вопроса:

  1. Эффективна ли моя стратегия?
  2. Приведенный ниже код не работает (.VerifyData возвращает FALSE). Что мне не хватает?

Стратегия

Сторона сервера

  • Apache/PHP: потому что это единственный серверный язык, с которым я знаком. с, но я мог бы переключиться, если бы это было рекомендовано.
  • OpenSSL: потому что я использую PHP
  • Файлы PEM: потому что я использую OpenSSL
  • Размер ключа RSA — 2048 бит: рекомендуемый минимум в 2019 г.
  • Алгоритм SHA256: потому что все используют его.
  • Заголовок текстовый/обычный, UTF8: почему бы и нет?

Сторона клиента

  • Профиль клиента VB.Net Framework 4.0: потому что я хочу максимально использовать наследие (VSTO 2013)
  • System.Security.Cryptography.RSACryptoServiceProvider
  • Информация об открытом ключе PEM загружается через строку XML
  • HTTPS должен быть TLS1.0 или выше: поскольку я ориентируюсь на .Net Framework 4.0 (если возможно, рекомендуется TLS1.1)

Исходный код

Сторона сервера (генерировать файлы ключей .pem, только один раз)

<?

// Create new Keys Pair
$new_key_pair = openssl_pkey_new(array(
    "private_key_bits" => 2048,
    "private_key_type" => OPENSSL_KEYTYPE_RSA,
));

//Save Private Key
openssl_pkey_export($new_key_pair, $private_key_pem, "my passphrase to protect my private key; add random characters like $, ?, #, & or ! for improved security");
file_put_contents('private_key.pem', $private_key_pem);

//Save Public Key
$details = openssl_pkey_get_details($new_key_pair);
$public_key_pem = $details['key'];
file_put_contents('public_key.pem', $public_key_pem);

?>

Сторона сервера (цель запросов POST)

<?

header('Content-Type: text/plain; charset=utf-8');

// Verify connection is secure
if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS']= = "off")
{
    echo "Unauthorized Access";
    exit;
}

// Data to Sign
$data = base64_decode(file_get_contents('php://input'));

//Load Private Key
$private_key_pem = openssl_pkey_get_private('file:///path/protected/by/dotHtaccess/private_key.pem', "my passphrase to protect my private key; add random characters like $, ?, #, & or ! for improved security");

//Create Signature
openssl_sign($data, $signature, $private_key_pem, OPENSSL_ALGO_SHA256);
echo base64_encode($signature);

?>

Сторона клиента

imports System.Diagnostics

Sub mySignatureTest()

    Dim oURI As Uri = New Uri("https://www.example.com/targetpage.php")
    Dim sData As String = "myStringToSign"
    Dim sResponse As String


    '# Get POST request Response

    Using oWeb As New System.Net.WebClient()

        Try

            System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol And Not System.Net.ServicePointManager.SecurityProtocol.Ssl3 'Override defautl Security Protocols: Prohibit SSL3
            oWeb.Encoding = Encoding.UTF8
            Debug.Print("SSL version is " & System.Net.ServicePointManager.SecurityProtocol.ToString)
            Debug.Print("Sending " & sData)
            Debug.Print("To " & oURI.ToString)
            Debug.Print("Encoding is " & oWeb.Encoding.ToString)
            sResponse = oWeb.UploadString(oURI, "POST", Convert.ToBase64String(Encoding.UTF8.GetBytes(sData)))
            Debug.Print("Server reponse = " & sResponse)

        Catch ex As Exception
            MsgBox("Connection with server failed: " & ex.ToString, vbCritical + vbOKOnly, "Add-In")
        End Try

    End Using


    '#Verify RSA SHA256 Signature

    Dim sDataToSign As String = sData
    Dim sSignatureToVerify As String = sResponse

    Using myRSA As New System.Security.Cryptography.RSACryptoServiceProvider
        'XML format obtain from PEM file by hand copy/paste here: https://superdry.apphb.com/tools/online-rsa-key-converter
        myRSA.FromXmlString("<RSAKeyValue><Modulus>SomeLongBase64StringHere</Modulus><Exponent>SomeShortBase64StringHere</Exponent></RSAKeyValue>") 

        Debug.Print("Signature verification = " & myRSA.VerifyData(Encoding.UTF8.GetBytes(sDataToSign), _
                                                                   System.Security.Cryptography.CryptoConfig.MapNameToOID("SHA256"), _
                                                                   Convert.FromBase64String(sSignatureToVerify)).ToString)

    End Using

End Sub

После того, как вопрос 2) будет решен, я надеюсь, что мы сможем доработать этот код, чтобы он стал хорошим, но все же простым примером того, как реализовать .NET Client проверку подписи OpenSSL Server. Я не смог найти простой и понятный пример в Интернете.

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

Вопрос 2) решен: по какой-либо причине передача ответа POST через строку в кодировке base64 решает проблему. Я не уверен, почему, поскольку я проводил аналогичные тесты с хеш-значениями без необходимости кодирования base64. Вопрос был отредактирован, чтобы включить это исправление.

Ama 29.01.2019 16:29

Вопрос 2) не относится к теме переполнения стека, поэтому перемещен в обзор кода здесь: codereview.stackexchange.com/questions/212989/…

Ama 06.02.2019 17:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
2
670
0

Другие вопросы по теме