【问题标题】:C# 4.0 / Sql Server 2008: Encrypt/decrypt in business layerC# 4.0 / Sql Server 2008:在业务层加密/解密
【发布时间】:2012-03-28 16:14:57
【问题描述】:

我只是需要一些建议。我需要保护一些列数据,所以我一直在搜索C# 4.0/Sql server 2008(不是 R2)中的加密。

这可能是我需要的:

“当数据必须受到系统管理员的保护时。实际上,在这个 场景最好不要使用 SQL Server 内部加密 并且更好地完全依靠中间层来执行 加密和解密。很难保护你的 如果您的密钥存储在 SQL 中,则来自确定的系统管理员的数据 服务器。” 来源:msdn

正确的做法是什么?

我已尝试将使用Rijndael 加密的数据保存到数据库中。

我收到错误:Length of the data to decrypt is invalid

我还没有用谷歌搜索过这个。

我应该继续为此苦苦挣扎,还是应该尝试使用 CLR 或其他什么来解决这个问题? 我只是找不到向我展示如何在业务层加密/解密的教程。

有什么建议吗?

谢谢

编辑:

好的,这就是我目前所拥有的。 如前所示,数据使用 Rinjdael 加密。 它存储在列中

TestCrypt (varbinary(255), null)

我在数据库中看起来像这样:

0xF6CA99F5B6BFA1D9A0BD2381177E049E02F381078966195B68A54A5BEC4C

用sp检索,如:

SELECT cast(s.TestCrypt AS varbinary) AS TestCrypt

在数据访问层:

while (reader.Read())
{
    data.TestCrypt = (byte[])reader["TestCrypt"];
}

DecryptStringFromBytes 在这一行发现错误

plaintext = srDecrypt.ReadToEnd();

错误:要解密的数据长度无效。

【问题讨论】:

  • 如果您发布您的加密/解密代码,那么也许我们可以帮助解决错误。这应该不是很困难。

标签: sql sql-server-2008 tsql c#-4.0


【解决方案1】:

【讨论】:

  • 您好,谢谢。两个 url:s 都显示了如何在 sql server 中加密/解密。我需要在我的 asp.net web 项目的业务层中发生这种情况。
  • 好的,我以为你需要sql server中的加密和解密机制...我会更新答案.....
【解决方案2】:

就业务层的加解密而言,我更喜欢使用下面的加解密方式:

#region Encryption Decription
public class CryptorEngine
{
/// <summary>
/// Encrypt a string using dual encryption method. Return a encrypted cipher Text
/// </summary>
/// <param name="toEncrypt">string to be encrypted</param>
/// <param name="useHashing">use hashing? send to for extra security</param>
/// <returns></returns>
public static string Encrypt(string toEncrypt, bool useHashing)
{
    try
    {
        byte[] keyArray;
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

        System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
        // Get the key from config file
        string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));
        //System.Windows.Forms.MessageBox.Show(key);
        if (useHashing)
        {
            MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            hashmd5.Clear();
        }
        else
            keyArray = UTF8Encoding.UTF8.GetBytes(key);

        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;
        tdes.Mode = CipherMode.ECB;
        tdes.Padding = PaddingMode.PKCS7;

        ICryptoTransform cTransform = tdes.CreateEncryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        tdes.Clear();
        return Convert.ToBase64String(resultArray, 0, resultArray.Length);
    }
    catch (Exception ex)
    {
        return "Invalid";   
    }
}
/// <summary>
/// DeCrypt a string using dual encryption method. Return a DeCrypted clear string
/// </summary>
/// <param name="cipherString">encrypted string</param>
/// <param name="useHashing">Did you use hashing to encrypt this data? pass true is yes</param>
/// <returns></returns>
public static string Decrypt(string cipherString, bool useHashing)
{
    try
    {
        if (string.IsNullOrEmpty(cipherString))
            return "";
        byte[] keyArray;
        byte[] toEncryptArray = Convert.FromBase64String(cipherString);

        System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader();
        //Get your key from config file to open the lock!
        string key = (string)settingsReader.GetValue("SecurityKey", typeof(String));

        if (useHashing)
        {
            MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            hashmd5.Clear();
        }
        else
            keyArray = UTF8Encoding.UTF8.GetBytes(key);

        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;
        tdes.Mode = CipherMode.ECB;
        tdes.Padding = PaddingMode.PKCS7;

        ICryptoTransform cTransform = tdes.CreateDecryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

        tdes.Clear();
        return UTF8Encoding.UTF8.GetString(resultArray);
    }
    catch (Exception ex)
    {
       return "Invalid";   
    }
}
}
#endregion

【讨论】:

  • 是的,但是您可以从异常块返回任何内容,例如 Invalid 或 InCorrecrt ......
  • (删除原始评论以添加此内容)如何使用 MS 编译器进行编译? catch (Exception ex) { } -- 如果抛出异常,该函数永远不会返回定义的值。我认为try/catch { do nothing }(或return String.Empty)在这里无效:最好让an异常转义,以免有人使用parameters.AddWithValue("@OldValue", CryptorEngine.Encrypt(oldValue))之类的函数——如果有什么不好的在Encrypt 期间发生,您将存储一个空值。这可能不是你想要的。
  • 是的,我曾经从异常块中返回“无效”字符串,所以,每当我使用这种加密/解密方法时,我都会检查返回值......
  • 好的,谢谢,我一直在谷歌搜索,但找不到如何将 SecurityKey 添加到 web.config。
  • 好的,我找到了。我每次都在创建一个新密钥。现在我将它保存在我的班级中的静态字符串中。我想将它存储在 web.config 中的 SecurityKey 中,找不到如何做到这一点。可以给我看看吗?
【解决方案3】:

使用您喜欢的任何加密提供程序在 .net 中加密您的数据,并将其存储在具有正确长度的 VARBINARY 数据类型的列中。

对于其余数据,将数据与所有其他数据一样对待。

【讨论】:

    【解决方案4】:
    SELECT cast(s.TestCrypt AS varbinary) AS TestCrypt
    

    那行truncates the value of TestCrypt to 30 bytes:

    在数据定义或变量声明语句中未指定n时,默认长度为1。当未使用CAST函数指定nis时,默认长度为30。

    试试:

    SELECT cast(s.TestCrypt AS varbinary(255)) AS TestCrypt
    

    【讨论】:

    • 谢谢。现在我遇到了另一个我正在努力解决的错误:填充无效并且无法删除。
    • 但它没有帮助。我已经替换了两者,但我没有对尺寸做任何事情,因为它没有设置在任何地方
    猜你喜欢
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    • 2011-03-11
    • 2012-10-18
    • 2014-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多