用.NET(VB)验证OpenSSL RSA签名(PHP)
我想实现一些我认为非常艰难的目标: A) 我的VB.NET客户端(理想的目标是Framework 4.0)通过HTTPS POST请求向Apache/PHP服务器发送文本字符串 B) 我的服务器用该文本字符串的签名进行响应。 服务器使用的私钥总是相同的,客户端使用的公钥已经嵌入到源代码中 在调查和阅读了大量文档后,我提出了以下策略,并提出了两个问题:用.NET(VB)验证OpenSSL RSA签名(PHP),php,.net,vb.net,openssl,cryptography,Php,.net,Vb.net,Openssl,Cryptography,我想实现一些我认为非常艰难的目标: A) 我的VB.NET客户端(理想的目标是Framework 4.0)通过HTTPS POST请求向Apache/PHP服务器发送文本字符串 B) 我的服务器用该文本字符串的签名进行响应。 服务器使用的私钥总是相同的,客户端使用的公钥已经嵌入到源代码中 在调查和阅读了大量文档后,我提出了以下策略,并提出了两个问题: 我的策略有效吗 下面提供的代码不起作用(.VerifyData返回FALSE)。我错过了什么 策略 服务器端 Apache/PHP:因为这是我唯
- 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)
服务器端(POST请求的目标)
客户端
导入系统诊断
Sub-mySignatureTest()
作为Uri的Dim oURI=新Uri(“https://www.example.com/targetpage.php")
将sData设置为String=“myStringToSign”
暗响应为字符串
“#获取POST请求响应
将oWeb用作新系统.Net.WebClient()
尝试
System.Net.ServicePointManager.SecurityProtocol=System.Net.ServicePointManager.SecurityProtocol而非System.Net.ServicePointManager.SecurityProtocol.Ssl3'覆盖默认安全协议:禁止Ssl3
oWeb.Encoding=Encoding.UTF8
Print(“SSL版本为”&System.Net.ServicePointManager.SecurityProtocol.ToString)
Debug.Print(“发送”和sData)
Debug.Print(“To”&oURI.ToString)
Print(“Encoding is”&oWeb.Encoding.ToString)
sResponse=oWeb.UploadString(oURI,“POST”,Convert.ToBase64String(Encoding.UTF8.GetBytes(sData)))
Debug.Print(“服务器响应=”&sResponse)
特例
MsgBox(“与服务器的连接失败:&ex.ToString,vbCritical+vbOKOnly,“加载项”)
结束尝试
终端使用
“#验证RSA SHA256签名
Dim sDataToSign As String=sData
Dim sSignatureToVerify As String=s响应
将myRSA用作新的System.Security.Cryptography.RSACryptoServiceProvider
'手动从PEM文件中获取XML格式复制/粘贴到此处:https://superdry.apphb.com/tools/online-rsa-key-converter
myRSA.FromXmlString(“SomeLongBase64StringHereSomeShortBase64StringHere”)
Debug.Print(“签名验证=“&myRSA.VerifyData(Encoding.UTF8.GetBytes(sDataToSign))_
System.Security.Cryptography.CryptoConfig.MapNameToOID(“SHA256”)_
转换.FromBase64String(sSignatureToVerify)).ToString)
终端使用
端接头
一旦问题2)得到解决,我希望我们可以让这段代码不断发展,从而为如何实现OpenSSL服务器签名的.NET客户端验证提供一个很好但简单的示例。我在网上找不到一个简单明了的例子
这通常可用于授权目的,其中服务器将提供一个包含过期日期以及该日期签名的文件,以便客户端应用程序确认该过期日期未被更改(例如客户端计算机的所有者)。问题2)已解决:无论出于何种原因,通过base64编码字符串传递POST响应可以解决此问题。我不确定为什么,因为我使用哈希值运行了类似的测试,而不需要base64编码。该问题已被编辑以包含此修复。问题2)在堆栈溢出中与主题无关,因此移至此处的代码审阅:
<?
// 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);
?>
<?
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);
?>