首页 > 解决方案 > 使用 .NET (VB) 验证 OpenSSL RSA 签名 (PHP)

问题描述

我想实现一些我认为非常简单的事情:

A) 我的 VB.NET 客户端(理想情况下以 Framework 4.0 为目标)通过 HTTPS POST 请求向我的 Apache/PHP 服务器发送一个文本字符串。

B) 我的服务器以该文本字符串的签名响应。服务器使用的私钥始终相同,客户端使用的公钥已经嵌入源代码中。

在调查和阅读了大量文档后,我想出了以下策略,并有两个问题:

  1. 我的策略有效吗?
  2. 下面提供的代码不起作用(.VerifyData 返回 FALSE)。我错过了什么?

战略

服务器端

客户端

源代码

服务器端(生成 .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) 得到解决,我希望我们可以让这段代码发展,以便它提供一个很好但简单的示例,说明如何实现 OpenSSL 服务器签名的 .NET 客户端验证。我无法在 Internet 上找到一个简单明了的示例。

这通常可用于许可目的,其中服务器将提供包含到期日期以及该日期签名的文件,以便客户端应用程序确认此到期日期未被更改,例如客户端所有者计算机。

标签: php.netvb.netopensslcryptography

解决方案


推荐阅读