您的位置:首页 > 理论基础 > 计算机网络

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

2008-04-23 17:16 337 查看
    如果我有一个只想自己看到的文档,我不会简单的通过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时算法使用转换对象加密该数据。需要将数据通过网络发送时,首先使用接收的公共不对称密钥加密对称密钥。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息