2009-07-01 15 views
2

我有一個應用程序連接到許多SQL Server以進行監視和其他任務。目前,我只支持可信認證,因爲我不需要存儲任何敏感信息。我想添加使用SQL身份驗證(用戶名/密碼)的功能。存儲SQL連接詳細信息 - 如何安全地對每個用戶進行加密?

在會話之間存儲敏感數據的最佳方法是什麼?是否有可供我使用的僅供用戶使用的證書或加密密鑰?使用每個用戶隨機生成的註冊表密鑰來加密這些信息足夠安全嗎?如果有辦法,我可以使用一個密鑰(或創建一個並存儲它),使計算機上的其他用戶無法訪問它,這是理想的。

我明白了加密,所以我不是在尋找一個教程 - 我在尋找保持一個用戶的配置數據,我的應用程序從其他用戶的安全是最安全的方法。

回答

6

使用Data Protection API (aka. DPAPI)。每次使用都有一個密碼,由其密碼保護。將密碼/連接字符串存儲在.config文件中,.Net框架具有使用機器密鑰,用戶密鑰或RSA密鑰加密/解密配置部分的方法。不要重複做你自己的定製方案。而使用註冊表鍵絕對是一個壞主意。安全來自祕密,而不是來自訪問保護:它必須依賴用戶提供祕密(登錄時的密碼),而不是無法訪問的註冊表項。

How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI

+0

看來,我可以使用DPAPI,並存儲在用戶存儲的關鍵,所以它不是在機器上的任何其他用戶訪問。這看起來正是我想要做的 - 謝謝! – SqlRyan 2009-07-01 20:55:56

+0

我在這裏結束了使用相同的修改後的版本:http://www.obviex.com/samples/dpapi.aspx – SqlRyan 2009-07-01 21:03:16

0

正如瑞摩斯指出的那樣,有用戶/機器級加密提供。

我總是害怕這樣的事情,因爲這些數據可能會相對容易地丟失。

如果我是你,我會推出自己的系統。使用應用程序中硬編碼的密鑰加密連接字符串,轉換爲Base64,並將生成的加密連接字符串存儲在註冊表中。


下面的函數需要一個字符串,用AES-256和指定密鑰加密它和Base64的結果所以它的背部,作爲可打印字符串:

用法示例:

String connectionString = EncryptString(
    "Provider=SQLOLEDB;Data Source=Lithium;User Id=sa;Password=hello", 
    "A fairly complicated password, like a guid: 8B4B0D73-84C9-4A1E-8DD2-9A189F84FD9B"); 


public static string EncryptString(string source, string key) 
{ 
    Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(key, salt); 
    byte[] derivedKey = deriveBytes.GetBytes(derivedKeySize); 


    Rijndael rijndael = Rijndael.Create(); 

    rijndael.Mode = cipherMode; 
    rijndael.Padding = paddingMode; 
    rijndael.KeySize = keySize; 
    rijndael.BlockSize = blockSize; 
    rijndael.FeedbackSize = blockSize; // no bigger than the blocksize 

    rijndael.Key = derivedKey; 
    rijndael.IV = iv; 

    ICryptoTransform transform = rijndael.CreateEncryptor(); 

    byte[] encoded = Encoding.UTF8.GetBytes(source); 

    byte[] target = transform.TransformFinalBlock(encoded, 0, encoded.Length); 
    return Convert.ToBase64String(target); 
} 

public static string DecryptString(string source, string key) 
{ 
    Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(key, salt); 
    byte[] derivedKey = deriveBytes.GetBytes(derivedKeySize); 

    Rijndael rijndael = Rijndael.Create(); 

    rijndael.Mode = cipherMode; 
    rijndael.Padding = paddingMode; 
    rijndael.KeySize = keySize; 
    rijndael.BlockSize = blockSize; 
    rijndael.FeedbackSize = blockSize; // no bigger than the blocksize 

    rijndael.Key = derivedKey; 
    rijndael.IV = iv; 

    ICryptoTransform transform = rijndael.CreateDecryptor(); 

    byte[] decoded = Convert.FromBase64String(source); 
    byte[] target = transform.TransformFinalBlock(decoded, 0, decoded.Length); 

    return Encoding.UTF8.GetString(target); 
} 

    private static readonly byte[] iv = { 
     0x30,0xA6,0x65,0xDE,0x8C,0x63,0x17,0x44, 
     0xB6,0xFD,0xEA,0x5F,0x76,0xA1,0x1C,0x5F 
    }; 

    private static readonly byte[] salt = { 
     0xF9,0x39,0x0C,0xE0,0x22,0xE0,0x8E,0x84, 
     0xB2,0x05,0x1E,0xA8,0x6D,0x1C,0x39,0xAC 
    }; 

    private const int keySize = 256; 
    private const int blockSize = 128; 
    private const CipherMode cipherMode = CipherMode.CBC; 
    private const PaddingMode paddingMode = PaddingMode.PKCS7; 
    private const int derivedKeySize = 32; 
1

正如Remus所說,使用DPAPI。但不是使用PInvoke方法(如在您的鏈接示例中),請使用ProtectedData類。這是DPAPI的託管包裝。很多的例子使用的PInvoke訪問DPAPI因爲有NET 2.0之前做它沒有管理辦法。 DataProtectionScope類使您能夠爲當前用戶或機器加密/解密數據。

相關問題