不对称算法比对称算法计算的花费多、速度慢。因此我们不希望在线对话中使用不对称算法加密所有信息。相反,我们使用对称算法。下面的例子中我们使用不对称加密来加密对称密钥。接着就使用对称算法加密了。实际上安全接口层(SSL)建立服务器和浏览器之间的安全对话使用的就是这种工作方式。
示例是一个TCP程序,分为服务器端和客户端。服务器端的工作流程是:
从客户端接收公共密钥。
使用公共密钥加密未来使用的对称密钥。
将加密了的对称密钥发送给客户端。
给客户端发送使用该对称密钥加密的信息。
代码如下:
复制代码 代码如下:
namespace com.billdawson.crypto
{
public class CryptoServer
{
private const int RSA_KEY_SIZE_BITS = 1024;
private const int RSA_KEY_SIZE_BYTES = 252;
private const int TDES_KEY_SIZE_BITS = 192;
public static void Main(string[] args)
{
int port;
string msg;
TcpListener listener;
TcpClient client;
SymmetricAlgorithm symm;
RSACryptoServiceProvider rsa;
//获取端口
try
{
port = Int32.Parse(args[0]);
msg = args[1];
}
catch
{
Console.WriteLine(USAGE);
return;
}
//建立监听
try
{
listener = new TcpListener(port);
listener.Start();
Console.WriteLine("Listening on port {0}",port);
client = listener.AcceptTcpClient();
Console.WriteLine("connection.");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
return;
}
try
{
rsa = new RSACryptoServiceProvider();
rsa.KeySize = RSA_KEY_SIZE_BITS;
// 获取客户端公共密钥
rsa.ImportParameters(getClientPublicKey(client));
symm = new TripleDESCryptoServiceProvider();
symm.KeySize = TDES_KEY_SIZE_BITS;
//使用客户端的公共密钥加密对称密钥并发送给客。
encryptAndSendSymmetricKey(client, rsa, symm);
//使用对称密钥加密信息并发送
encryptAndSendSecretMessage(client, symm, msg);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
finally
{
try
{
client.Close();
listener.Stop();
}
catch
{
//错误
}
Console.WriteLine("Server exiting");
}
}
private static RSAParameters getClientPublicKey(TcpClient client)
{
// 从字节流获取串行化的公共密钥,通过串并转换写入类的实例
byte[] buffer = new byte[RSA_KEY_SIZE_BYTES];
NetworkStream ns = client.GetStream();
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
RSAParameters result;
int len = 0;
int totalLen = 0;
while(totalLen
(len = ns.Read(buffer,0,buffer.Length))>0)
{
totalLen+=len;
ms.Write(buffer, 0, len);
}
ms.Position=0;
result = (RSAParameters)bf.Deserialize(ms);
ms.Close();
return result;
}
private static void encryptAndSendSymmetricKey(
TcpClient client,
RSACryptoServiceProvider rsa,
SymmetricAlgorithm symm)
{
// 使用客户端的公共密钥加密对称密钥
byte[] symKeyEncrypted;
byte[] symIVEncrypted;
NetworkStream ns = client.GetStream();
symKeyEncrypted = rsa.Encrypt(symm.Key, false);
symIVEncrypted = rsa.Encrypt(symm.IV, false);
ns.Write(symKeyEncrypted, 0, symKeyEncrypted.Length);
ns.Write(symIVEncrypted, 0, symIVEncrypted.Length);
}
private static void encryptAndSendSecretMessage(TcpClient client,
SymmetricAlgorithm symm,
string secretMsg)
{
// 使用对称密钥和初始化矢量加密信息并发送给客户端
byte[] msgAsBytes;
NetworkStream ns = client.GetStream();
ICryptoTransform transform =
symm.CreateEncryptor(symm.Key,symm.IV);
CryptoStream cstream =
new CryptoStream(ns, transform, CryptoStreamMode.Write);
msgAsBytes = Encoding.ASCII.GetBytes(secretMsg);
cstream.Write(msgAsBytes, 0, msgAsBytes.Length);
cstream.FlushFinalBlock();
}
}
客户端的工作流程是:
建立和发送公共密钥给服务器。
从服务器接收被加密的对称密钥。
解密该对称密钥并将它作为私有的不对称密钥。
接收并使用不对称密钥解密信息。
代码如下:
复制代码 代码如下:
namespace com.billdawson.crypto
{
public class CryptoClient
{
private const int RSA_KEY_SIZE_BITS = 1024;
private const int RSA_KEY_SIZE_BYTES = 252;
private const int TDES_KEY_SIZE_BITS = 192;
private const int TDES_KEY_SIZE_BYTES = 128;
private const int TDES_IV_SIZE_BYTES = 128;
public static void Main(string[] args)
{
int port;
string host;
TcpClient client;
SymmetricAlgorithm symm;
RSACryptoServiceProvider rsa;
if (args.Length!=2)
{
Console.WriteLine(USAGE);
return;
}
try
{
host = args[0];
port = Int32.Parse(args[1]);
}
catch
{
Console.WriteLine(USAGE);
return;
}
try //连接
{
client = new TcpClient();
client.Connect(host,port);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
Console.Write(e.StackTrace);
return;
}