Return to HomePage




Protect Credentials Within a Connection String in Code (VB.NET)




Applies to

* .NET Framework 2.0
* VB.NET
* Server-side code

Summary

The purpose of this code is to offer an alternative mechanism for encrypting database connection string data using the Windows Data Protection API (DPAPI) in .NET source code.


Objectives

* Protect database connection strings credentials using both encryption and access control
* Relegate encryption implementation specifics such as cipher selection encryption modes, key generation and key management to the DPAPI
* Store the data in an easily recoverable and protected fashion in the Windows Registry

Scenarios

* Application does not make use of ASP.NET and therefore does not have a web.config file, such as a client-server application
* Developer wishes to make use of user store, as opposed to machine key, to restrict database credentials access to specific user accounts


Solution Example

Sub StoreConnectionString(ByVal keyName As String, ByVal valueName As String, ByVal connectionString As String)
		    		' Convert the connection string to a byte array
		    		' and encrypt the data by using the DPAPI [ProtectedData] class.
		    		Byte() [encryptedConnStrBytes] = [ProtectedData.Protect(]
		                    	[UnicodeEncoding.ASCII.GetBytes(connectionString),] 
		                    	Nothing, 
		                    	[DataProtectionScope.CurrentUser)]
	

		    	' Create a security context for a new key that we will use to store our encrypted connection string.
		    	' The security context will restrict access to only our user.
		    	Dim user As String =  [Environment.UserDomainName] + "\" + [Environment.UserName] 
		    	Dim security As [RegisTrySecurity] =  New [RegisTrySecurity()] 
		    	[RegisTryAccessRule] rule = New [RegisTryAccessRule(user,]
		                    [RegisTryRights.FullControl,]
		                    [InheritanceFlags.ContainerInherit,]
		                    [PropagationFlags.None,]
		                    [AccessControlType.Allow)]
		    	[security.AddAccessRule(rule)]
	

		    	' Actually create the new registry key and apply the security context we just came up with.
		    	[RegisTryKey] key = [RegisTry.CurrentUser.CreateSubKey(keyName,]
		                    [RegisTryKeyPermissionCheck.ReadWriteSubTree,]
		                    security)
	

		   	 ' Write the encrypted connection string into the registry
		    	[key.SetValue(valueName,] [encryptedConnStrBytes)]
	
End Sub


Problem Example

The following example demonstrates the use of the registry to store a cleartext database connection string.

' Database connection string
Dim connStr As String = "Initial Catalog=snippets;Data Source=vm-win2003\sqlexpress;Integrated Security=SSPI;"

' Store connection string in the registry
Dim key As RegisTryKey = RegisTry.CurrentUser.CreateSubKey("PlaintextConnectionString")
key.SetValue("ConnStr", connStr)

* Cleartext connection string details can be viewed by any user with access to the registry
* In a mixed-mode authentication scenario, credentials would be viewable by any user with access to the registry
* Lack of registry ACL's allows all systems users read access to this registry key

Test Case

The following classes must be included in any project making use of the sample code provided above:

Imports System
Imports System.Collections.Generic
Imports System.Security.Cryptography
Imports System.Security.AccessControl
Imports System.Text
Imports Microsoft.Win32

The following test case methods store and retrieve encrypted registry data and output the results to the console.

Function RetrieveConnectionString(ByVal keyName As String, ByVal valueName As String) As String
		    		' Read the encrypted connection string value from the registry 
		    		Dim key As [RegisTryKey] =  [RegisTry.CurrentUser.OpenSubKey(keyName)] 
		    		Dim [encryptedConnStrBytes()] As Byte =  [key.GetValueCType(as] Byte(), valueName)
	

		    		' Decrypt the encrypted bytes using DPAPI, convert to string and return
		    		Byte() [decryptedConnStrBytes] = [ProtectedData.Unprotect(]
		                     	[encryptedConnStrBytes,] 
		                    	 Nothing,
		                     	[DataProtectionScope.CurrentUser)]
		    		[Return(UnicodeEncoding.ASCII.GetString(decryptedConnStrBytes))]
	
End Function

Sub Main(ByVal args() As String)
		    		' A sample connection string we might want to store
		    		Dim stored As String =  "Initial Catalog=snippets;Data Source=vm-win2003\sqlexpress;Integrated Security=SSPI;" 
		    		Console.WriteLine("Stored String: " + stored)
	

		    		' Create an instance of our class and pass the string we want to encrypt
		    		StoreConnectionString("EncryptedConnectionString", "CipherText", stored)
	

		    		' Retrieve from the registry and print to make sure it worked.
		    		' You can also fire up regedit and browse to HKEY_CURRENT_USER\EncryptedConnectionString
		    		' to see the encrypted bytes.
		    		Dim retrieved As String =  RetrieveConnectionString("EncryptedConnectionString","CipherText") 
		    		Console.WriteLine("Retrieved String: " + retrieved)
	
End Sub


Expected Result

* Stored String: Initial Catalog=snippets;Data Source=vm-win2003\sqlexpress;Integrated Security=SSPI;
* Retrieved String: Initial Catalog=snippets;Data Source=vm-win2003\sqlexpress;Integrated Security=SSPI;


More Information

* This implementation makes use of the DPAPI user key as opposed to the machine key. This means that the connection string will not be accessible by other applications running under different service accounts.
* This adds additional protection against a rogue application (such as a virus or Trojan) compromising connection string data but could pose problems where sharing between multiple applications running under different accounts is required.


Additional Resources

* Encrypting Connection Strings using DPAPI (ASP.NET): http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000005.asp
* Encrypting Connection Strings using RSA (ASP.NET): http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag2/html/paght000005.asp
* Cryptography (.NET): http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGGuidelines0003.asp?frame=true#pagguidelines0003_cryptography


Attributes

* Applies To: .NET Framework 2.0, VB
* Category: Data Access
* Author: Jonathan Bailey





Return to HomePage
Microsoft Communities