使用.NET(VB)验证OpenSSL RSA签名(PHP)

时间:2019-01-28 15:42:19

标签: php .net vb.net openssl cryptography

我想实现一些我认为很简单的东西:

A)我的VB.NET客户端(理想情况下是针对Framework 4.0)通过HTTPS POST请求将文本字符串发送到我的Apache / PHP服务器。

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
  • 通过XML字符串加载的PEM公钥信息
  • 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)一旦解决,我希望我们可以让这段代码发展,以便为如何实现OpenSSL Server签名的.NET客户端验证提供一个很好而又简单的示例。我无法在Internet上找到一个简单清晰的示例。

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

0 个答案:

没有答案