NHibernate 加密数据库连接字符串以及部署安装碰到的问题
今天有个需求是需要加密下NHibernate的连接字符串;
1、先去下了网络的DES加密类;NET好像有自带的,没认真找。
代码
public class DESEncrypt
{
private string KEY = "123321";//密钥
private byte[] sKey;
private byte[] sIV;
public DESEncrypt()
{
}
/// <summary>
/// 加密方法
/// </summary>
/// <param name="pToEncrypt">加密字符串</param>
/// <param name="keyStr">密钥可以为空,默认密钥为"123321"</param>
/// <returns></returns>
public string Encrypt(string pToEncrypt, string keyStr)
{
MemoryStream ms = null;
CryptoStream cs = null;
StringBuilder ret = null;
try
{
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
if (keyStr==null||keyStr == "")
keyStr = this.KEY;
//把字符串放到byte数组中
//原来使用的UTF8编码,我改成Unicode编码了,不行
byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
sKey = new byte[8];
sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
des.Key = sKey;
des.IV = sIV;
ms = new MemoryStream();
cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
ret = new StringBuilder();
foreach (byte b in ms.ToArray())
{
ret.AppendFormat("{0:X2}", b);
}
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
finally
{
if (null != cs) cs.Close();
if (null != ms) ms.Close();
}
return ret.ToString();
}
/// <summary>
/// 解密方法
/// </summary>
/// <param name="pToDecrypt">解密字符串</param>
/// <param name="keyStr">密钥可以为空,默认密钥为"123321"</param>
/// <returns></returns>
public string Decrypt(string pToDecrypt, string keyStr)
{
MemoryStream ms = null;
CryptoStream cs = null;
sKey = new byte[8];
sIV = new byte[8];
string values = "";
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
if (keyStr == null || keyStr == "")
keyStr = this.KEY;
byte[] inputByteArray = new byte[pToDecrypt.Length / 2];
for (int x = 0; x < pToDecrypt.Length / 2; x++)
{
int i = (Convert.ToInt32(pToDecrypt.Substring(x * 2, 2), 16));
inputByteArray[x] = (byte)i;
}
try
{
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
des.Key = sKey;
des.IV = sIV;
ms = new MemoryStream();
cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
//建立StringBuild对象,CreateDecrypt使用的是流对象,必须把解密后的文本变成流对象
values = System.Text.Encoding.Default.GetString(ms.ToArray());
}
catch (Exception ex)
{
throw new Exception("文件格式出错");
}
finally
{
cs.Close();
ms.Close();
}
return values;
}
}
2、看了下NHibernate配置文件
代码
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" requirePermission="false" />
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<!-- properties -->
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver </property>
<property name="connection.connection_string">Server=;database=;user id=;password=</property> <property name="show_sql">true </property>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect </property>
<property name="use_outer_join">true </property>
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N' </property>
<property name="proxyfactory.factory_class">
NHibernate.ByteCode.Castle.ProxyFactoryFactory,
NHibernate.ByteCode.Castle
</property>
</session-factory>
</hibernate-configuration>
3、找了下资料,发现要重写Configure,所以我想了下自定了个类
代码
public class CustomDriverConnectionProvider : NHibernate.Connection.DriverConnectionProvider
{
public CustomDriverConnectionProvider():base()
{
}
public override void Configure(IDictionary<string, string> settings)
{
string conn = settings[Environment.ConnectionString];
DESEncrypt des = new DESEncrypt();
settings[Environment.ConnectionString] = des.Decrypt(conn, null);
base.Configure(settings);
}
}
然后将
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
替换成<property name="connection.provider">DataDrawoff.Interface.CustomDriverConnectionProvider</property>
后面NHibernate报错,网上和帮助文档都没如何自定义provider资料(谁知道如何做请告之~~),无奈之下换了种办法:
在NHibernate初始化Configuration文件时候解密即可(当然你要先将连接字符串加密)
NHibernate.Cfg.Configuration cfg = new Configuration();
cfg.Properties["connection.connection_string"] = Global.Decrypt(cfg.Properties["connection.connection_string"], null);//解密
配置文件连接字符串改成类似
代码
<property name="connection.connection_string">123E0E1DE42F3172025DA161423E580567ED047841A6A3B8704C34A0C04AFC713E055FD4D8442F708295A1EC153CDD96A624C0926BD3B634716BB095F7C40831FF00AA0CA2C4B5A4F0E071F16428940C069E28F0B83A82A135FABFEFA</property>
当然如果嫌加密字符串长度加密太多,可以只加密数据库名,用户名和密码配置项即可。
这个基本满足了要求,当然要更安全,还要把操作数据库的DLL和加密密钥的DLL混淆;(这个有时间在去尝试下)
4、后面部署碰到本机调试没问题,在服务器调试一直报错,最后找了半天发现时NET2.0框架 需要装个SP1补丁包;
以后要注意了这些框架装完都要找下是否还需要补丁包;