【问题标题】:Encrypt from C# just like SQL Server EncryptByPassPhrase?像 SQL Server EncryptByPassPhrase 一样从 C# 加密?
【发布时间】:2020-05-13 00:52:49
【问题描述】:

按照question 的回答后,我能够重新创建 SQL 的 DecryptByPassPhrase 函数。现在我正在尝试执行 EncryptByPassPhrase 函数。

我们在不同的服务器上有不同的SQL版本,不能同时升级到相同的版本,所以我们想创建我们的c#函数(使用SQL CLR)。

我需要使用 SHA1(如 SQL 2012)进行编码,因为另一台服务器上的 SQL 可能尚未升级到 2017

这是我的c#,函数编译,但我不能用我的其他c#函数解密它(这正是另一个问题的答案的函数)

        int keySize = 16;

        var cryptoAlgo = TripleDES.Create();
        cryptoAlgo.Padding = PaddingMode.PKCS7;
        cryptoAlgo.Mode = CipherMode.CBC;

        cryptoAlgo.GenerateIV(); //cryptoAlgo.IV = StringToByteArray(value.Substring(8, 16));
        //cryptoAlgo.IV = StringToByteArray("7854E155CEE338D5");
        var valueInByte = Encoding.Unicode.GetBytes(value); //UTF8Encoding.UTF8.GetBytes(value); //encrypted = StringToByteArray(value.Substring(24));


        byte[] passwordBytes = Encoding.Unicode.GetBytes(password);
        var hashAlgo = SHA1.Create();
        hashAlgo.TransformFinalBlock(passwordBytes, 0, passwordBytes.Length);
        cryptoAlgo.Key = hashAlgo.Hash.Take(keySize).ToArray();

        byte[] encrypted = cryptoAlgo.CreateEncryptor().TransformFinalBlock(valueInByte, 0, valueInByte.Length);

        //byte[] encryptedData = encrypted.Skip(8).ToArray();
        //bool isUtf16 = (Array.IndexOf(encryptedData, (byte)0) != -1);
        //string encryptedText = (isUtf16 ? Encoding.Unicode.GetString(encryptedData) : Encoding.UTF8.GetString(encryptedData));

        return new SqlString(encryptedText);
        //return new SqlString(encryptedText);
        //return Convert.ToBase64String(encrypted, 0, encrypted.Length);
        //return Convert.ToBase64String(encryptedData, 0, encryptedData.Length);
        //return "0x01000000" + Convert.ToBase64String(cryptoAlgo.IV, 0, cryptoAlgo.IV.Length) + Convert.ToBase64String(encrypted, 0, encrypted.Length);
        //return "0x01000000" + Convert.ToBase64String(encryptedData, 0, encryptedData.Length);

我尝试过很多不同的回报(他们在评论中)。我注意到 SQL 返回“0x01000000”,我猜接下来的 16 个字符是 IV,所以我尝试添加它们,但没有运气

【问题讨论】:

  • 强烈考虑借此机会完全摆脱基于 SQL 的加密/解密功能(即使用 SQL Server 本身对现有数据执行一次性解密传递,然后严格重新加密和解密带有客户端代码)。这使您不必为将来的版本束缚于这些函数的未记录内部结构——如果数据可能需要迁移到/从 SQL Server 迁移,甚至在不同版本中迁移(正如您所发现的),它们并不真正适合.
  • 我同意,但是由于我无法控制先更新哪一方,而且当前保存在数据库中的数据也没有加密,所以我不能这样做。当客户进行购买时,我们会在他的一些数据在互联网上传输到我们的另一个系统时对其进行加密

标签: c# sql sql-server encryption 3des


【解决方案1】:

有类似的需求,注意仅仅加密数据是不够的,你最终的字节数组应该如下结构:

  • 前四个字节是版本:2 0 0 0
  • 接下来的 16 个字节是 初始化向量:cryptoAlgo.IV

  • 剩下的是加密数据,结构(加密前)如下:

    • 第一 四个字节是魔术值:13, 240, 173, 186 (0xbaadf00d)
    • 下一个 2 字节为 0
    • 接下来的 2 个字节是值字节的长度
    • 余数为字节值

代码:

public static class SqlCryptographyExtensions
{
    const uint MagicPrefix = 0xbaadf00d;

    public static byte[] EncryptByPassPhrase(this string value, string passPhrase)
    {
        var keyBytes = Encoding.Unicode.GetBytes(passPhrase);
        // Depending on whether you're working with NVARCHAR/VARCHAR on SQL Server, use Unicode/UTF encoding here
        var valueBytes = Encoding.UTF8.GetBytes(value); 
        var payload = new List<byte>();
        payload.AddRange(BitConverter.GetBytes(MagicPrefix));
        payload.AddRange(BitConverter.GetBytes((UInt16)0));
        payload.AddRange(BitConverter.GetBytes((UInt16)valueBytes.Length));
        payload.AddRange(valueBytes);
        var payloadBytes = payload.ToArray();

        HashAlgorithm hash = SHA256.Create();
        SymmetricAlgorithm encryption = Aes.Create();
        encryption.GenerateIV();
        encryption.Padding = PaddingMode.PKCS7;
        encryption.Mode = CipherMode.CBC;
        hash.TransformFinalBlock(keyBytes, 0, keyBytes.Length);
        encryption.Key = hash.Hash.Take(32).ToArray();

        byte[] encryptedPayload = encryption.CreateEncryptor().TransformFinalBlock(payloadBytes, 0, payloadBytes.Length);

        byte[] version = new byte[] { 2, 0, 0, 0 };

        var encryptedBytes = new List<byte>();
        encryptedBytes.AddRange(version);
        encryptedBytes.AddRange(encryption.IV);
        encryptedBytes.AddRange(encryptedPayload);

        return encryptedBytes.ToArray();
    }
}

【讨论】:

    猜你喜欢
    • 2014-03-08
    • 2019-09-11
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多