.NET中加密和解密---加密网络数据

    如果我有一个只想自己看到的文档,我不会简单的通过e-mail发送给你。我将使用对称算法加密它;如果有人截取了它,他们也不能阅读该文档,因 为他们没有用于加密的唯一密钥。但是你也没有密钥。我需要使用某种方式将密钥给你,这样你才能解密文档,但是不能冒密钥和文档被截取的风险。     非对称算法就是一种解决方案。这类算法使用的两个密钥有如下关系:使用公共密钥加密的信息只能被相应的私有密钥解密。因此,我首要求你给我发送 你的公共密钥。在发送给我的途中可能有人会截取它,但是没有关系,因为他们只能使用该密钥给你的信息加密。我使用你的公共密钥加密文档并发送给你。你使用 私有密钥解密该文档,这是唯一可以解密的密钥,并且没有通过网络传递。  
    不对称算法比对称算法计算的花费多、速度慢。因此我们不希望在线对话中使用不对称算法加密所有信息。相反,我们使用对称算法。下面的例子中我们使用不对称加密来加密对称密钥。接着就使用对称算法加密了。实际上安全接口层(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

    
//建立监听
    try
    
{
    listener 
= new TcpListener(port);
    listener.Start();
    Console.WriteLine(
"Listening on port ...",port);

    client 
= listener.AcceptTcpClient();
    Console.WriteLine(
"connection....");
    }

    
catch (Exception e)


    
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)

    
finally

    
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)


    
try
    
{
    host 
= args[0];
    port 
= Int32.Parse(args[1]);
    }

    
catch


    
try //连接
    {
    client 
= new TcpClient();
    client.Connect(host,port);
    }

    
catch(Exception e)


    
try
    
{
    Console.WriteLine(
"Connected. Sending public key.");
    rsa 
= new RSACryptoServiceProvider();
    rsa.KeySize 
= RSA_KEY_SIZE_BITS;
    sendPublicKey(rsa.ExportParameters(
false),client);
    symm 
= new TripleDESCryptoServiceProvider();
    symm.KeySize 
= TDES_KEY_SIZE_BITS;

    MemoryStream ms 
= getRestOfMessage(client);
    extractSymmetricKeyInfo(rsa, symm, ms);
    showSecretMessage(symm, ms);
    }

    
catch(Exception e)

    
finally

    
catch //错误
    }

    }

    }


    
private static void sendPublicKey(
    RSAParameters key,
    TcpClient client)
    
{
    NetworkStream ns 
= client.GetStream();
    BinaryFormatter bf 
= new BinaryFormatter();
    bf.Serialize(ns,key);
    }


    
private static MemoryStream getRestOfMessage(TcpClient client)
    
{
    
//获取加密的对称密钥、初始化矢量、秘密信息。对称密钥用公共RSA密钥
    
//加密,秘密信息用对称密钥加密
    MemoryStream ms = new MemoryStream();
    NetworkStream ns 
= client.GetStream();
    
byte[] buffer = new byte[1024];

    
int len=0;

    
// 将NetStream 的数据写入内存流
    while((len = ns.Read(buffer, 0, buffer.Length))>0)
    
{
    ms.Write(buffer, 
0, len);
    }

    ms.Position 
= 0;
    
return ms;
    }


    
private static void extractSymmetricKeyInfo(
    RSACryptoServiceProvider rsa,
    SymmetricAlgorithm symm,
    MemoryStream msOrig)
    
{
    MemoryStream ms 
= new MemoryStream();

    
// 获取TDES密钥--它被公共RSA密钥加密,使用私有密钥解密
    byte[] buffer = new byte[TDES_KEY_SIZE_BYTES];
    msOrig.Read(buffer,
0,buffer.Length);
    symm.Key 
= rsa.Decrypt(buffer,false);

    
// 获取TDES初始化矢量
    buffer = new byte[TDES_IV_SIZE_BYTES];
    msOrig.Read(buffer, 
0, buffer.Length);
    symm.IV 
= rsa.Decrypt(buffer,false);
    }


    
private static void showSecretMessage(
    SymmetricAlgorithm symm,
    MemoryStream msOrig)
    
{
    
//内存流中的所有数据都被加密了
    byte[] buffer = new byte[1024];
    
int len = msOrig.Read(buffer,0,buffer.Length);

    MemoryStream ms 
= new MemoryStream();
    ICryptoTransform transform 
=
    symm.CreateDecryptor(symm.Key,symm.IV);
    CryptoStream cstream 
=new CryptoStream(ms, transform,
    CryptoStreamMode.Write);
    cstream.Write(buffer, 
0, len);
    cstream.FlushFinalBlock();

    
// 内存流现在是解密信息,是字节的形式,将它转换为字符串
    ms.Position = 0;
    len 
= ms.Read(buffer,0,(int) ms.Length);
    ms.Close();

    
string msg = Encoding.ASCII.GetString(buffer,0,len);
    Console.WriteLine(
"The host sent me this secret message:");
    Console.WriteLine(msg);
    }

    }

    }
结论

  使用对称算法加密本地数据时比较适合。在保持代码通用时我们可以选择多种算法,当数据通过特定的CryptoStream时算法使用转换对象加密该数据。需要将数据通过网络发送时,首先使用接收的公共不对称密钥加密对称密钥。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值