我正在尝试使用C#客户端和服务器之间进行通信SslStream
。但是,我的服务器的证书是自签名的。
客户端拥有服务器证书的公共部分的副本,假定该副本是通过防篡改(但不是侦听)通道传输的。
我可以安全地使用它来对服务器进行身份验证吗,并且要这样做,我应该在客户端SslStream
或其服务器中放置什么RemoteCertificateValidationCallback
?到目前为止,由于缺乏信任,我使用验证的所有尝试均以失败告终,而我的回调函数现在所做的只是比较名称和指纹。
如果可以接受,我如何让客户“信任”其公共证书副本以进行验证?
第一个解决方案很简单,但仍然存在漏洞。那只是检查密钥指纹是否匹配。但是,任何中间人都可以建立中间连接并创建自己的密钥交换,然后制作与之匹配的密钥,然后共享加密密钥。
根本问题是您没有适当的基础架构。这并不是您在使用本身的自签名证书,而是在使用来自同一“ CA”的自签名证书。您需要为您的证书颁发机构(您自己)创建一个根证书,然后从该密钥中批准要使用的软件的CSR。这意味着所有远程计算机都需要信任您的根证书,并将其作为证书颁发机构安装在其计算机中。通过这样做,可以避免应用程序使用的证书在中游或类似情况下受到损害的问题。但这仅适用于您可以以保证防篡改的方式将该根CA证书提供给用户的情况。
解决您的问题的另一种方法却更为严格,实际上是放弃SSL或对该证书的有效性进行带外身份验证。客户端可以验证证书,因为服务器能够解密客户端的消息并做出适当的响应。这样的质询响应方案可以用数学/密码学方法证明服务器具有预期的证书,或者至少一方具有对应的私钥:
Client generates a 256 bit random nonce (RNGCryptoServiceProvider), K_C
Server generates a 256 bit random nonce, K_S
Client encrypts K_C with server's assumed public key, now K_B
Server digitally signs K_S, K_A
Server transmits K_A to client
Client transmits K_B to server
Server decrypts K_B, now N_S
Client verifies K_A using server's assumed public key, if invalid disconnect
Client computes K_A XOR K_C, now Z_C
Server computes N_S XOR K_A, now Z_S
Server transmits Z_S to client
Client verifies Z_S matches Z_C
Client transmits Z_C to server, encrypted using the server's public key
Server decrypts Z_C and verifies that it matches Z_S
如果一切都完成了,那么挑战就完成了,您可以保证服务器拥有您拥有的公钥的私钥。您也不能只是通过快捷方式将此快捷方式并将服务器的公共密钥的数字签名副本发送给客户端,因为任何中间人都可以在任一侧创建两个会话。该方案可防止中间人建立两个会话,因为客户端已经拥有了公钥,并通过使用服务器的公钥对他们的现时进行加密直接挑战了有效性。对此的最佳攻击是中间观察者中的一个人,他可以在不利用所使用的非对称算法的弱点的情况下篡改数据。
此方案的另一个好处是,由于您已独立进行身份验证,因此此时您可以完全避免使用SSL。现在,您实际上可以利用Z_S == Z_C
自己的优势,并考虑将Z_S
或Z_C
(它们相同)作为您同意的对称密钥进行进一步的通信。
不久前,我就类似的计划写了一篇论文,并在一些地方发表。您可能会以“具有挑战性的身份验证协议协议(CAAP)”的名称找到它,该名称是2007年或2010年修订的,以我的名字命名。有代码示例。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句