如果您没有具备保护服务器之间通信信道的 IPSec 策略的安全数据中心,另一种替代策略是实现一个自定义的加密接收器。如果您需要保护的只是从客户端传递到服务器的消息的敏感部分,而非整个负载,也可以考虑这种选择。此方法如图 4 所示。
所谓加密接收器,就是一个可以在结合使用自定义宿主和 TcpChannel 时使用的自定义信道接收器。在客户端,接收器在请求数据发送给服务器之前将其加密,并解密任何从服务器接收到的加密响应数据。在服务器端,接收器将请求数据解密,然后加密响应数据。
实现自定义加密接收器
接收器应该使用不对称加密来交换会话级加密密钥。在交换了会话密钥之后,客户端和服务器将保留密钥的一个副本,任何一方也可以选择在信道接收器生命期的任何时候创建新的密钥。服务器应该为它所通信的每个客户端保留不同的密钥。
以下步骤概述了实现自定义加密接收器的基本方法:
-
为解决方案创建公钥/私钥对。
const int AT_KEYEXCHANGE = 1; CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = ""; cspParams.KeyNumber = AT_KEYEXCHANGE; cspParams.ProviderName = "Microsoft Base Cryptographic Provider v1.0"; cspParams.ProviderType = PROV_RSA_FULL; RSACryptoServiceProvider rsaServerSide = new RSACryptoServiceProvider(cspParams); rsaServerSide.PersistKeyInCsp = true; Console.WriteLine(rsaServerSide.ToXmlString(true)); // Writes the public key
-
公开公钥供客户端使用。
客户端在文件中保留公钥的副本。
-
初始化客户端信道接收器,创建随机密钥进行加密。
byte[] randomKey = new byte[size]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(randomKey);
-
用服务器的公钥加密随机密钥。使用 IClientChannelSink.ProcessMessage 将加密的密钥发送到服务器。
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(csp); rsa.FromXmlString(""); AsymmetricKeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter(rsa); byte[] encryptedSessionKey = formatter.CreateKeyExchange(_sessionKey);
-
初始化服务器信道接收器,使用特定的密钥容器名称创建 RSA 对象。
const int AT_KEYEXCHANGE = 1; CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = ""; cspParams.KeyNumber = AT_KEYEXCHANGE; cspParams.ProviderName = "Microsoft Base Cryptographic Provider v1.0"; cspParams.ProviderType = PROV_RSA_FULL; RSACryptoServiceProvider rsaServerSide = new RSACryptoServiceProvider(cspParams);
-
检索从客户端加密的密钥。这个密钥通常在请求头中发送。 使用服务器的私钥解密会话加密密钥。
AsymmetricKeyExchangeDeformatter asymDeformatter = new RSAPKCS1KeyExchangeDeformatter(_rsa); byte[] decryptedSessionKey = asymDeformatter.DecryptKeyExchange( );
-
使用一种机制将客户端与加密密钥对应起来,例如,通过使用散列表。
此时,客户端和服务器都共享了加密密钥,而且可以加密和解密方法调用。在对象生存期中,可以而且应该周期性地创建新的密钥。