你的位置:首页 > ASP.net教程

[ASP.net教程]clickonce部署的 winform保护连接字符串进行加密的一个简单方案 可有效防止被反编译暴露数据库地址


手里在做的一个自用的多用户进销存项目,碰到了以下使用场景:

1、为了每个店铺/仓库的用户都能及时获得更新,软件采用了clickOnce部署方式,这就导致了只要知道发布地址,任何人都可以进行下载了。

2、现在只购买了一个SQL数据库空间,并没有购买虚拟主机之类的web空间(部署用的空间是用3322解析到自己的电脑上的),所以也没办法采用websevices来进行中间层操作了,只能用客户端直接连接。

客户端连接数据库最大的隐患就是如果被反编译的话会直接暴露数据库地址,非常不安全,通常情况下采用的加密和解密都需要写到程序里,如果被反编译的话也会一并暴露,达不到加密目的。

项目中我采用了一个取巧的方法:利用文件的数字签名作为密钥来进行加密,具体的做法就是:

1、在系统指定位置放一个KEY文件,软件读取该文件的MD5值作为密钥,对连接字符串进行AES/DES加密,将加密后的字符串放到软件的配置文件中。

2、把该KEY文件会直接发放给使用的用户(内部系统,使用人员可控),放到指定的系统路径中,软件读取该文件的MD5值作为密钥然后进行DES/AES解密。

好处就是:即使程序被反编译,看到的也是加密后的字符串,拿不到key文件就无法进行解密。

而key文件则是通过另外的方式进行分发,并不随软件一起发布,即使下载了程序,也还是拿不到key文件。

 

思路有了 实现起来也是非常的简单:

第一步:准备一个KEY文件,可以是任意文件,一张图片,一个文档,或者一首歌曲,注意:该文件一旦被作为KEY文件将不能在有任何修改,否则MD5值就改变了,也就无法再解密。

第二部:读取改文件的MD5值,核心代码:(因为加密密钥需要是8位,所以任意截取结果中的8位即可)

FileStream file = new FileStream(“filePath“, System.IO.FileMode.Open); //filepath为你的key文件路径,建议放到C盘中        MD5 md5 = new MD5CryptoServiceProvider();        byte[] retVal = md5.ComputeHash(file);        file.Close();        StringBuilder sb = new StringBuilder();        for (int i = 0; i < retVal.Length; i++)        {          sb.Append(retVal[i].ToString("x2"));        }        return sb.ToString().Substring(10, 8);

第三部:加密:核心代码(用了DES,AES方法等同)(加密方法无需写到程序中,只需要把加密结果写到程序配置文件中即可)

public static string DESEncrypt(string plainStr)    {      byte[] bKey = Encoding.UTF8.GetBytes(Key); //key为第二部的返回值      byte[] bIV = Encoding.UTF8.GetBytes(@"L%n67}G\Mk@k%:~Y"); //加密向量,可以自己设置      byte[] byteArray = Encoding.UTF8.GetBytes(plainStr);      string encrypt = null;      DESCryptoServiceProvider des = new DESCryptoServiceProvider();      using (MemoryStream mStream = new MemoryStream())      {        using (CryptoStream cStream = new CryptoStream(mStream, des.CreateEncryptor(bKey, bIV), CryptoStreamMode.Write))        {          cStream.Write(byteArray, 0, byteArray.Length);          cStream.FlushFinalBlock();          encrypt = Convert.ToBase64String(mStream.ToArray());        }      }      des.Clear();      return encrypt;    }

  

 第四部:解密:核心代码(利用解密后的字符串进行连接即可)

 public static string DESDecrypt(string encryptStr)    {      byte[] bKey = Encoding.UTF8.GetBytes(Key); //key为第二部的返回值      byte[] bIV = Encoding.UTF8.GetBytes(@"L%n67}G\Mk@k%:~Y"); //向量应等同于第三部中的向量      byte[] byteArray = Convert.FromBase64String(encryptStr);      string decrypt = null;      DESCryptoServiceProvider des = new DESCryptoServiceProvider();      try      {        using (MemoryStream mStream = new MemoryStream())        {          using (CryptoStream cStream = new CryptoStream(mStream, des.CreateDecryptor(bKey, bIV), CryptoStreamMode.Write))          {            cStream.Write(byteArray, 0, byteArray.Length);            cStream.FlushFinalBlock();            decrypt = Encoding.UTF8.GetString(mStream.ToArray());          }        }      }      catch { }      des.Clear();      return decrypt;    }

  

好了,是不是很简单,现在即使你的程序被别人下载反编译了,他想到你的电脑中把key文件拿走也不是一件容易的事。只要key文件不丢,基本就很难解密。

 

运行实例:使用哪个key文件进行加密,则只能使用其进行解密,一旦替换或者丢失则无法在解密。原理类似与绑定机器MAC地址,只是用一个文件来代替更为灵活。