Проверьте подпись OpenSSL RSA (PHP) с помощью .NET (VB) - PullRequest
0 голосов
/ 28 января 2019

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

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

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

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

  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Подпись сервера.Мне не удалось найти простой и понятный пример в Интернете.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...