Return to HomePage



Generate RSA Keys and Store in the Registry Using DPAPI (VB)


Applies to

* .NET Framework 2.0
* VB

Summary

The purpose of this code snippet is to illustrate how to generate and securely store a public key pair in .NET using RSA and the DPAPI.


Objectives

* Create a encryption key that can be publicly distributed without fearing that encrypted messages could become compromised
* Securely store the private key material without needing to implement additional encryption operations or relying on file system on database security


Solution Example

' Some useful globals
Private RSAKEYSIZE As Integer = 2048
Private myRSA As RSACryptoServiceProvider

Public Sub GenerateAndStoreRSAKeys()
		    		*_ Generate RSA Key Public and Private Pairs _*
		    		' The RSA CSP class automatically generates public and private key material
		    		' during constructions using the provided key size (or 1024bits if blank)
		    		myRSA = New RSACryptoServiceProvider(RSA_KEY_SIZE)
	

		    		*_ Store in the registry using DPAPI and a Registry ACL _*
		    		' Serialize the RSA key pair as an XML string for registry storage
		    		Dim [keyPairXml] As String = [myRSA.ToXmlString(True)]
	

		    		' Convert the RSA key pair to a byte array and encrypt the data by using 
		    		' the DPAPI [ProtectedData] class. We're using the [CurrentUser] scope instead 
		   	 	' of the [MachineKey] scope so that other, potentially malicious applications 
		   	 	' cannot access this key in the registry and decrypt. This provides additional
		   	 	' security but sacrifices interoperability with other applications. Consider
		    		' using the [MachineKey] scope if you have a need to share keys between 
		    		' applications.
		    		Dim [encryptedKeyPair] As Byte() = [ProtectedData.Protect(UnicodeEncoding.ASCII.GetBytes(keyPairXml),] Nothing, [DataProtectionScope.CurrentUser)]
	

		   	 	' Create a security context for a new key that we will use to store 
		    		' our RSA key pair. The security context will restrict access to only 
		    		' our user.
		    		Dim user As String = [Environment.UserDomainName] + "\" + [Environment.UserName]
		    		Dim security As New [RegistrySecurity()]
		    		Dim rule As 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.
		    		Registry.CurrentUser.CreateSubKey("RSAKeyPair", [RegistryKeyPermissionCheck.ReadWriteSubTree,] security)
	

		    		' Write the encrypted connection string into the registry
		    		Registry.SetValue("HKEY_CURRENT_USER\RSAKeyPair", "KeyData", [encryptedKeyPair)]
	
End Sub 'GenerateAndStoreRSAKeys


Problem Example

The following example demonstrates the generation of an RSA key pair and storage of those keys on the file system.

		 	' The RSA CSP class automatically generates public and private key material
	
' during construction
myRSA = New RSACryptoServiceProvider()

_ Store in the registry using DPAPI and a Registry ACL _
' Convert the RSA public key to an xml string (passing "true" retrieves
' both the private and public key data
Dim keyPairXml As String = myRSA.ToXmlString(True)

' Open up the key pair file and read into a string
Dim keyWriter As New StreamWriter("C:\temp\rsakeypair.xml")
keyWriter.Write(keyPairXml)
keyWriter.Close()

* If the file system is compromised the private key may be exposed and the encrypted messages can be compromised.
* Default key size provides degraded strength and diminishes security


Test Case

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

Imports System.IO
Imports System.Security
Imports System.Security.AccessControl
Imports System.Security.Cryptography
Imports System.Text
Imports Microsoft.Win32

Execute the following code and then open "regedit" and look in the registry under the key "HKEYCURRENTUSER\RSAKeyPair" to see the RSA key pair data encrypted in the registry.

Sub Main(ByVal args() As String)
		    		' Generate an RSA key pair and store using the DPAPI
		    		[GenerateAndStoreRSAKeys()]
	
End Sub 'Main


Expected Result

The RSA key is encrypted using DPAPI and stored in the registry key.


Scenarios

* Distributed client-server architecture where clients need to send confidential encrypted messages to the server but don't need to ever read those messages
* Application does not want to maintain a dedicated key store for encryption purposes


More Information

RSA is an algorithm for public key (also knows as asymmetric) cryptography in which distinct public and private keys are created. Encryption operations makes use of the public key while decryption requires the private key. This offers an advantage over symmetric cryptography because the secret key used to decrypt a message does not need to be shared in order to support encryption of messages to a recipient.

The RSA private key must be securely stored in order to maintain the confidentiality of data encrypted using an individual's public RSA key. However, the public key can be freely distributed by the owner of the key pair to anyone who wishes to send an encrypted message to that owner.


Additional Resources

* RSACryptoServiceProvider (.NET): http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecuritycryptographyrsacryptoserviceproviderclassctortopic.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: Cryptography
* Author: Jonathan Bailey



Return to HomePage
Microsoft Communities