sql >> データベース >  >> RDS >> Sqlserver

C#SQL Serverからバイトを復号化するEncryptByPassPhrase?

    SQL Server 2017は、パスワードのSHA256ハッシュ+AES-256暗号化を使用します

    古いバージョンでは、パスワードのSHA1ハッシュ+3DES-128暗号化を使用しています

    IVサイズはブロックサイズと同じです:AES =128ビット、3DES=64ビット

    パディングモード:PKCS#7暗号モード:CBC

    サーバー2017によって暗号化されたデータは「0x02」で始まり、古いバージョンは「0x01」で始まります。

    // Example decrypt:
    // UInt32 - "magic" (0xbaadf00d): 0d f0 ad ba
    // UInt16 - unknown (always zero): 00 00
    // UInt16 - decrypted data length (16): 10 00
    // byte[] - decrypted data: 4c 65 74 54 68 65 53 75 6e 53 68 69 6e 69 6e 67
    
    DecryptCombined("0x02000000266AD4F387FA9474E825B013B0232E73A398A5F72B79BC90D63BD1E45AE3AA5518828D187125BECC285D55FA7CAFED61", "Radames");
    DecryptCombined("0x010000007854E155CEE338D5E34808BA95367D506B97C63FB5114DD4CE687FE457C1B5D5", "banana");
    
    
    void DecryptCombined(string FromSql, string Password)
    {
        // Encode password as UTF16-LE
        byte[] passwordBytes = Encoding.Unicode.GetBytes(Password);
    
        // Remove leading "0x"
        FromSql = FromSql.Substring(2);
    
        int version = BitConverter.ToInt32(StringToByteArray(FromSql.Substring(0, 8)), 0);
        byte[] encrypted = null;
    
        HashAlgorithm hashAlgo = null;
        SymmetricAlgorithm cryptoAlgo = null;
        int keySize = (version == 1 ? 16 : 32);
    
        if (version == 1)
        {
            hashAlgo = SHA1.Create();
            cryptoAlgo = TripleDES.Create();
            cryptoAlgo.IV = StringToByteArray(FromSql.Substring(8, 16));
            encrypted = StringToByteArray(FromSql.Substring(24));
        }
        else if (version == 2)
        {
            hashAlgo = SHA256.Create();
            cryptoAlgo = Aes.Create();
            cryptoAlgo.IV = StringToByteArray(FromSql.Substring(8, 32));
            encrypted = StringToByteArray(FromSql.Substring(40));
        }
        else
        {
            throw new Exception("Unsupported encryption");
        }
    
        cryptoAlgo.Padding = PaddingMode.PKCS7;
        cryptoAlgo.Mode = CipherMode.CBC;
    
        hashAlgo.TransformFinalBlock(passwordBytes, 0, passwordBytes.Length);
        cryptoAlgo.Key = hashAlgo.Hash.Take(keySize).ToArray();
    
        byte[] decrypted = cryptoAlgo.CreateDecryptor().TransformFinalBlock(encrypted, 0, encrypted.Length);
        int decryptLength = BitConverter.ToInt16(decrypted, 6);
        UInt32 magic = BitConverter.ToUInt32(decrypted, 0);
        if (magic != 0xbaadf00d)
        {
            throw new Exception("Decrypt failed");
        }
    
        byte[] decryptedData = decrypted.Skip(8).ToArray();
        bool isUtf16 = (Array.IndexOf(decryptedData, (byte)0) != -1);
        string decryptText = (isUtf16 ? Encoding.Unicode.GetString(decryptedData) : Encoding.UTF8.GetString(decryptedData));
    
        Console.WriteLine("Result: {0}", decryptText);
    }
    
    // Method taken from https://stackoverflow.com/questions/321370/how-can-i-convert-a-hex-string-to-a-byte-array?answertab=votes#tab-top
    public static byte[] StringToByteArray(string hex)
    {
        return Enumerable.Range(0, hex.Length)
                         .Where(x => x % 2 == 0)
                         .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                         .ToArray();
    }
    


    1. 文字と数字の配置に関するSQLの一致

    2. PHPはMySqlに接続するときにSSL証明書を無視します

    3. MySQLのフィールドをインクリメントすることはアトミックですか?

    4. ユーロ記号がサイトに表示されない