Return to
HomePage
Retrieve an RSA Key Pair from the Registry and Decrypt a Message (VB.NET)
Applies to
* .NET Framework 2.0
* VB.NET
Summary
The purpose of this code snippet is to illustrate how to retrieve a public keypair stored in the registry using the Data Protection API (DPAPI) and decrypt a message using that key pair.
Objectives
* Make use of a securely stored RSA keypair for to decrypt an encrypted message
* Illustrate how securely stored keys in the registry and using the DPAPI can be easy to implement
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
Solution Example
Public Shared Function
RetrieveRSAKeyPairAndDecryptMessage(encrypted() As Byte) As Byte()
' Retrieve the keypair from the registry, decrypt using the DPAPI
' and store the serialized key data as an XML string
Dim [encryptedKeyPair] As Byte() = Registry.GetValue("HKEY_CURRENT_USER\RSAKeyPair", "KeyData", Nothing)
Dim [keyPairBytes] As Byte() = [ProtectedData.Unprotect(encryptedKeyPair,] Nothing, [DataProtectionScope.CurrentUser)]
Dim [keyPairXml] As String = [UnicodeEncoding.ASCII.GetString(keyPairBytes)]
' Create a new RSA CSP in which to load the public/private key
' data retrieved from the registry
Dim retrievedRSA As New [RSACryptoServiceProvider()]
[retrievedRSA.FromXmlString(keyPairXml)]
' Decrypt message and return
Return retrievedRSA.Decrypt(encrypted, False)
End Function
Problem Example
The following example demonstrates the retrieval of an RSA key pair containing private key material from the file system.
' fileName is a string containing a path location with a serialized RSA key pair
' encrypted is a byte array containing an encrypted message for decryption
' Open up the public key file and read into a string
Dim keyReader As New
StreamReader(fileName) Dim
keyPairXml As String =
keyReader.ReadToEnd() keyReader.Close()
' Create a new RSA CSP in which to load the public/private key
' data retrieved from the registry
Dim retrievedRSA As New
RSACryptoServiceProvider() retrievedRSA.FromXmlString(keyPairXml) ' Decrypt message
retrievedRSA.Decrypt(encrypted, False)
* If the filesystem is compromised, the private key material may be exposed
* Extra management required to ensure that ACL's are securely set for files that contain key data
* In alternate settings, lack of encryption when sending message exposes sensitive data to eavesdropping while in transit
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 Microsoft.Win32
Use the solution example above and the following code to encrypt an example using the registry-stored public key and then decrypt using the solution example:
Sub Main(args() As String)
' Read public key into a string
Dim [publicKeyXml] As String = "<RSAKeyValue>" + "<Modulus>tnLAgAJwXXxYj+2QPX6q/mHZZf23xSvvovoBlZ1Y7RbTlkY4N2nlcGxfR6mQcTTWKfWShQ7yEaX6rVfhhRhd aHLCsg7g3AmW2BsoBxWUijD81ZeNKyWrw8t0gjnigNR46+PqO1Xi7R9aA+PgaluhuZBBgJK2wIAlRJSPlTr5OjDr4vJlZiAG /VqmJVXioPfv1QI2hfLM86JgIcrD47L0K44tKwyhAj4PN1nsomjPeb0P9m9t3od/c+yZGKk+iJ1nwQwG02H/EXROaO6YFKb3 xijNv69gv+ZLGc+qssXs7Bs7CdzqmQvSylxuXkYz5bQG++raYWm4l056WhtIRG8mqQ==</Modulus>" + "<Exponent>AQAB</Exponent>" + "</RSAKeyValue>"
' Encrypt a message using our key and write out the results
Dim msg As String = "The quick brown fox jumped over the lazy dog"
Dim encrypted As Byte() = [ReadRSAPublicKeyAndEncryptMessage(publicKeyXml,] msg)
Console.WriteLine("Encrypted data:")
[Console.WriteLine(Convert.ToBase64String(encrypted))]
' Retrieve RSA [KeyPair] from registry and decrypt a message
Dim decrypted As Byte() = [RetrieveRSAKeyPairAndDecryptMessage(encrypted)]
[Console.WriteLine(ControlChars.Lf] + "Decrypted data:")
[Console.WriteLine(Encoding.ASCII.GetString(decrypted))]
End Sub
Shared Function
ReadRSAPublicKeyAndEncryptMessage(xmlKeyData As String, fileName As String) As Byte()
' Create a new RSA CSP in which to load the public key data from file
Dim yourRSA As New [RSACryptoServiceProvider()]
[yourRSA.FromXmlString(xmlKeyData)]
' Encrypt a message and return
Dim original As Byte() = Encoding.ASCII.GetBytes("The quick brown fox jumped over the lazy dog")
Return yourRSA.Encrypt(original, False)
End Function
Expected Result
Encrypted data:
YQdGxH+fyXEVjaoToOT4kVR00nmNv4xBWLRP5hyk7qz2zS9a64I0Ug9S99shDWvmbIT/nsKTkmPu8gZG
Xx3R7zNXn44KKKIlXKcIxvfXHHnkuMuX3tXdpLZKPhPKcG09nFVtxdKehOnvVQEr5Wyp54XnkqU3B6Vp Bui6wabN/dqrhE0ziqpAkM2NbhU5h38mfo6brq0Ug9Tns9xj4mAD5AwDvqKlkumr9qS94czPzt5ECFv8 rX4/HBvl/PhQZ
zsYt3xHwkQRDtT
A5zf1G5ey9pOAKpzPtLI/2LShaJVujo/fQifoLU1vCa1BoMON
Cpk0A1B4zIm5a
TpYzp6w==
Decrypted data:
The quick brown fox jumped over the lazy dog
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