Sno*_*owy 4 sql-server encryption des cryptostream
继在C#中复制T-SQL DecryptByPassPhrase,我无法获得与MSSQL简单的加密在C#descrypt。某些列中的加密值是必需的,因为该表会定期导出到Excel和Access中,因此简单的加密足以“阻止”值,而无需开发人员去(重新)执行视图等工作。
在SQL Server 2012中:
select EncryptByPassPhrase( N'hello' , N'world' )
-- returns 0x01000000AA959FFB3A8E4B06B734051437E198C8B72000A058ACE91D617123DA102287EB
Run Code Online (Sandbox Code Playgroud)
在C#中:
byte[] buf = System.Text.Encoding.UTF8.GetBytes( "0x010000003A95FA870ED699A5F90D33C2BF01491D9132F61BA162998E96F37117AF5DA0905D51EB6FB298EC88" );
// bytes emitted from the database
var cp = new TripleDESCryptoServiceProvider();
var m = new MemoryStream(buf);
cp.Key = System.Text.Encoding.UTF8.GetBytes( "hello" ); // throws
cp.IV = System.Text.Encoding.UTF8.GetBytes( "hello" ); // throws
CryptoStream cs = new CryptoStream( m , cp.CreateDecryptor( cp.Key , cp.IV ) , CryptoStreamMode.Read );
StreamReader reader = new StreamReader( cs );
string plainText = reader.ReadToEnd();
Run Code Online (Sandbox Code Playgroud)
工作的C#代码应该是什么样的?
谢谢。
Bal*_*123 11
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 /sf/ask/22495931/?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();
}
Run Code Online (Sandbox Code Playgroud)
小智 -1
我相信您所关注的链接建议采用一种新的加密和解密方法,模仿 SQL EncryptByPassPhrase 的制作方式。因此,如果您也在 C# 中加密,则只能在 C# 中使用解密。
既然您已经在 SQL 中使用了 EncryptByPassPhrase,那么我建议在传递给 C# 代码之前在 SQL 中使用 DecryptByPassPhrase。
你的 hello world 加密和解密示例:
Declare @lEncryptedText VARBINARY(256) = (select ENCRYPTBYPASSPHRASE('hello','world'))
SELECT @lEncryptedText --Encrypted VALUE for world
SELECT CONVERT(VARCHAR(100),DECRYPTBYPASSPHRASE('hello',@lEncryptedText)) --Decrypted Value
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4803 次 |
最近记录: |