(一)简介
 最早、最著名的保密密钥或对称密钥加密算法DES(Data Encryption Standard)是由IBM公司在70年代发展起来的,并经政府的加密标准筛选后,于197611月被美国政府采用,DES随后被美国国家标准局和美国国家标准协会(American National Standard InstituteANSI)承认。    DES使用56位密钥对64位的数据块进行加密,并对64位的数据块进行16轮编码。与每轮编码时,一个48位的"每轮"密钥值由56位的完整密钥得出来。DES用软件进行解码需用很长时间,而用硬件解码速度非常快。幸运的是,当时大多数黑客并没有足够的设备制造出这种硬件设备。在1977年,人们估计要耗资两千万美元才能建成一个专门计算机用于DES的解密,而且需要12个小时的破解才能得到结果。当时DES被认为是一种十分强大的加密方法。

    
随着计算机硬件的速度越来越快,制造一台这样特殊的机器的花费已经降到了十万美元左右,而用它来保护十亿美元的银行,那显然是不够保险了。另一方面,如果只用它来保护一台普通服务器,那么DES确实是一种好的办法,因为黑客绝不会仅仅为入侵一个服务器而花那么多的钱破解DES密文。

    
另一种非常著名的加密算法就是RSA了,RSA(Rivest-Shamir-Adleman)算法是基于大数不可能被质因数分解假设的公钥体系。简单地说就是找两个很大的质数。一个对外公开的为公钥Public key ,另一个不告诉任何人,称为"私钥Private key)。这两个密钥是互补的,也就是说用公钥加密的密文可以用私钥解密,反过来也一样。

    
假设用户甲要寄信给用户乙,他们互相知道对方的公钥。甲就用乙的公钥加密邮件寄出,乙收到后就可以用自己的私钥解密出甲的原文。由于别人不知道乙的私钥,所以即使是甲本人也无法解密那封信,这就解决了信件保密的问题。另一方面,由于每个人都知道乙的公钥,他们都可以给乙发信,那么乙怎么确信是不是甲的来信呢?那就要用到基于加密技术的数字签名了。
    
甲用自己的私钥将签名内容加密,附加在邮件后,再用乙的公钥将整个邮件加密(注意这里的次序,如果先加密再签名的话,别人可以将签名去掉后签上自己的签名,从而篡改了签名)。这样这份密文被乙收到以后,乙用自己的私钥将邮件解密,得到甲的原文和数字签名,然后用甲的公钥解密签名,这样一来就可以确保两方面的安全了。
(二)实施

加密

//////////////////////////

         //加密函数

         public string EncryptData(String strKey, String strData)

         {

              string strResult;      //返回值

 

              //1. 字符串长度不能超过90kb,否则,内存将溢出,看3就知道原因

              if (strData.Length > 92160)

              {

                   strResult="Error. Data String too large. Keep within 90Kb.";

                   return strResult;

              }

        

              //2. 发生密码

              if (!InitKey(strKey))

              {

                   strResult="Error. Fail to generate key for encryption";

                   return strResult;

              }

 

              //3. 准备字符串

              //   字符串的头5个字符将被格式化后存储数据的实际长度.

              //   这是最简单的方法来记住数据的初始长度,不借助于复杂的计算.

              strData = String.Format("{0,5:00000}"+strData, strData.Length);

 

 

              //4. 加密数据

              byte[] rbData = new byte[strData.Length];

              ASCIIEncoding aEnc = new ASCIIEncoding();

              aEnc.GetBytes(strData, 0, strData.Length, rbData, 0);

             

              DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();

             

              ICryptoTransform desEncrypt = descsp.CreateEncryptor(m_Key, m_IV);

 

 

              //5. 流:

              //   mOut 是输出流.

              //   mStream 是输入流.

              //   cs 是转换流

              MemoryStream mStream = new MemoryStream(rbData);

              CryptoStream cs = new CryptoStream(mStream, desEncrypt, CryptoStreamMode.Read);       

              MemoryStream mOut = new MemoryStream();

             

              //6. 开始实施加密

              int bytesRead;

              byte[] output = new byte[1024];

              do

              {

                   bytesRead = cs.Read(output,0,1024);

                   if (bytesRead != 0)

                       mOut.Write(output,0,bytesRead);

              } while (bytesRead > 0);

             

              //7. 返回加密结果在base64编码之后

              //   在这种情况,实际结果是转换成base64编码以至它能被HTTP协议传输而不发生损坏.

              if (mOut.Length == 0)      

                   strResult = "";

              else

                   strResult = Convert.ToBase64String(mOut.GetBuffer(), 0, (int)mOut.Length);

        

              return strResult;

         } 

 

解密


         //////////////////////////

         //解密函数

         public string DecryptData(String strKey, String strData)

         {

              string strResult;

 

              //1. 用来解密的密钥

              if (!InitKey(strKey))

              {

                   strResult="Error. Fail to generate key for decryption";

                   return strResult;

              }

 

              //2. 提供初始化服务

              int nReturn = 0;

              DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();

              ICryptoTransform desDecrypt = descsp.CreateDecryptor(m_Key, m_IV);

             

              //3. 预备流:

              //   mOut 是输出流.

              //   cs 是转换流.

              MemoryStream mOut = new MemoryStream();

              CryptoStream cs = new CryptoStream(mOut, desDecrypt, CryptoStreamMode.Write);       

             

              //4. 记着将base64编码恢复到到字节数组存在最初的数据流

              byte[] bPlain = new byte[strData.Length];

              try

              {

                   bPlain = Convert.FromBase64CharArray(strData.ToCharArray(), 0, strData.Length);

              }

              catch (Exception)

              {

                   strResult = "Error. Input Data is not base64 encoded.";

                   return strResult;

              }

             

              long lRead = 0;

              long lTotal = strData.Length;

             

              try

              {

                   //5. 实施解码

                   while (lTotal >= lRead)

                   {

                       cs.Write(bPlain,0,(int)bPlain.Length);

                       //descsp.BlockSize=64

                       lRead = mOut.Length + Convert.ToUInt32(((bPlain.Length / descsp.BlockSize) * descsp.BlockSize));

                   };

                  

                   ASCIIEncoding aEnc = new ASCIIEncoding();

                   strResult = aEnc.GetString(mOut.GetBuffer(), 0, (int)mOut.Length);

                  

                   //6. 将字符串整齐化,返回成只含有有实际意义的数据

                   //   记着在加密函数中,头5个字符指示了实际数据的长度

                   //   这是最简单的方法来记着最初数据的长度,不用借助任何复杂的计算

                   String strLen = strResult.Substring(0,5);

                   int nLen = Convert.ToInt32(strLen);

                   strResult = strResult.Substring(5, nLen);

                   nReturn = (int)mOut.Length;

                  

                   return strResult;

              }

              catch (Exception)

              {

                   strResult = "Error. Decryption Failed. Possibly due to incorrect Key or corrputed data";

                   return strResult;

              }

         }


KEY

         /////////////////////////////////////////////////////////////

         //私有函数将生成keys成为成员变量

         static private bool InitKey(String strKey)

         {

              try

              {

                   // 将key转换成字节数组

                   byte[] bp = new byte[strKey.Length];

                   ASCIIEncoding aEnc = new ASCIIEncoding();

                   aEnc.GetBytes(strKey, 0, strKey.Length, bp, 0);

                  

                   //用SHA1来哈希key

                   SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();

                   byte[] bpHash = sha.ComputeHash(bp);

                  

                   int i;

                   // 使用低64位作为key值

                   for (i=0; i<8; i++)

                       m_Key[i] = bpHash[i];

                      

                   for (i=8; i<16; i++)

                       m_IV[i-8] = bpHash[i];

                  

                   return true;

              }

              catch (Exception)

              {

                   //错误操作

                   return false;

              }

         }


调用

FE_Symmetric Crypt;

              Crypt = new FE_Symmetric();

              string tempAddress =textBox1.Text;

             

             this.textBox2.Text = Crypt.EncryptData("42", tempAddress);    

//提供服务方加密过程,得到sn,显示在textBox2中


             this.textBox2.Text = Crypt. DecryptData("42", tempAddress);

           


一定要先加密再解密,而且加密和解密的密码要一样!

posted on 2004-07-22 14:45  apple  阅读(1324)  评论(1编辑  收藏  举报