How to: Use Data Protection
The .NET Framework provides access to the data protection API (DPAPI), which allows you to encrypt data using information from the current user account or computer. When you use the DPAPI, you alleviate the difficult problem of explicitly generating and storing a cryptographic key.
Use the ProtectedMemory class to encrypt an array of in-memory bytes. This functionality is available in Microsoft Windows XP and later operating systems. You can specify that memory encrypted by the current process can be decrypted by the current process only, by all processes, or from the same user context. See the MemoryProtectionScope enumeration for a detailed description of ProtectedMemory options.
Use the ProtectedData class to encrypt a copy of an array of bytes. This functionality is available in Microsoft Windows 2000 and later operating systems. You can specify that data encrypted by the current user account can be decrypted only by the same user account, or you can specify that data encrypted by the current user account can be decrypted by any account on the computer. See the DataProtectionScope enumeration for a detailed description of ProtectedData options.
To encrypt in-memory data using data protection
-
Call the static Protect method while passing an array of bytes to encrypt, the entropy, and the memory protection scope.
To decrypt in-memory data using data protection
-
Call the static Unprotect method while passing an array of bytes to decrypt and the memory protection scope.
To encrypt data to a file or stream using data protection
-
Create random entropy.
-
Call the static Protect method while passing an array of bytes to encrypt, the entropy, and the data protection scope.
-
Write the encrypted data to a file or stream.
To decrypt data from a file or stream using data protection
-
Read the encrypted data from a file or stream.
-
Call the static Unprotect method while passing an array of bytes to decrypt and the data protection scope.
Example
The following code example demonstrates two forms of encryption and decryption. First, the code example encrypts and then decrypts an in-memory array of bytes. Next, the code example encrypts a copy of a byte array, saves it to a file, loads the data back from the file, and then decrypts the data. The example displays the original data, the encrypted data, and the decrypted data.
Imports System Imports System.IO Imports System.Text Imports System.Security.Cryptography Public Module MemoryProtectionSample Sub Main() Run() End Sub 'Main Sub Run() Try '''''''''''''''''''''''''''''''''''' ' ' Memory Encryption - ProtectedMemory ' '''''''''''''''''''''''''''''''''''' ' Create the original data to be encrypted (The data length should be a multiple of 16). Dim toEncrypt As Byte() = UnicodeEncoding.ASCII.GetBytes("ThisIsSomeData16") Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt)) Console.WriteLine("Encrypting...") ' Encrypt the data in memory. EncryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon) Console.WriteLine("Encrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt)) Console.WriteLine("Decrypting...") ' Decrypt the data in memory. DecryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon) Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt)) '''''''''''''''''''''''''''''''''''' ' ' Data Encryption - ProtectedData ' '''''''''''''''''''''''''''''''''''' ' Create the original data to be encrypted toEncrypt = UnicodeEncoding.ASCII.GetBytes("This is some data of any length.") ' Create a file. Dim fStream As New FileStream("Data.dat", FileMode.OpenOrCreate) ' Create some random entropy. Dim entropy As Byte() = CreateRandomEntropy() Console.WriteLine() Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt)) Console.WriteLine("Encrypting and writing to disk...") ' Encrypt a copy of the data to the stream. Dim bytesWritten As Integer = EncryptDataToStream(toEncrypt, entropy, DataProtectionScope.CurrentUser, fStream) fStream.Close() Console.WriteLine("Reading data from disk and decrypting...") ' Open the file. fStream = New FileStream("Data.dat", FileMode.Open) ' Read from the stream and decrypt the data. Dim decryptData As Byte() = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, bytesWritten) fStream.Close() Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(decryptData)) Catch e As Exception Console.WriteLine("ERROR: " + e.Message) End Try End Sub 'Run Sub EncryptInMemoryData(ByVal Buffer() As Byte, ByVal Scope As MemoryProtectionScope) If Buffer.Length <= 0 Then Throw New ArgumentException("Buffer") End If If Buffer Is Nothing Then Throw New ArgumentNullException("Buffer") End If ' Encrypt the data in memory. The result is stored in the same same array as the original data. ProtectedMemory.Protect(Buffer, Scope) End Sub 'EncryptInMemoryData Sub DecryptInMemoryData(ByVal Buffer() As Byte, ByVal Scope As MemoryProtectionScope) If Buffer.Length <= 0 Then Throw New ArgumentException("Buffer") End If If Buffer Is Nothing Then Throw New ArgumentNullException("Buffer") End If ' Decrypt the data in memory. The result is stored in the same same array as the original data. ProtectedMemory.Unprotect(Buffer, Scope) End Sub 'DecryptInMemoryData Function CreateRandomEntropy() As Byte() ' Create a byte array to hold the random value. Dim entropy(15) As Byte ' Create a new instance of the RNGCryptoServiceProvider. ' Fill the array with a random value. Dim RNG As New RNGCryptoServiceProvider() RNG.GetBytes(entropy) ' Return the array. Return entropy End Function 'CreateRandomEntropy Function EncryptDataToStream(ByVal Buffer() As Byte, ByVal Entropy() As Byte, ByVal Scope As DataProtectionScope, ByVal S As Stream) As Integer If Buffer.Length <= 0 Then Throw New ArgumentException("Buffer") End If If Buffer Is Nothing Then Throw New ArgumentNullException("Buffer") End If If Entropy.Length <= 0 Then Throw New ArgumentException("Entropy") End If If Entropy Is Nothing Then Throw New ArgumentNullException("Entropy") End If If S Is Nothing Then Throw New ArgumentNullException("S") End If Dim length As Integer = 0 ' Encrypt the data in memory. The result is stored in the same same array as the original data. Dim encrptedData As Byte() = ProtectedData.Protect(Buffer, Entropy, Scope) ' Write the encrypted data to a stream. If S.CanWrite AndAlso Not (encrptedData Is Nothing) Then S.Write(encrptedData, 0, encrptedData.Length) length = encrptedData.Length End If ' Return the length that was written to the stream. Return length End Function 'EncryptDataToStream Function DecryptDataFromStream(ByVal Entropy() As Byte, ByVal Scope As DataProtectionScope, ByVal S As Stream, ByVal Length As Integer) As Byte() If S Is Nothing Then Throw New ArgumentNullException("S") End If If Length <= 0 Then Throw New ArgumentException("Length") End If If Entropy Is Nothing Then Throw New ArgumentNullException("Entropy") End If If Entropy.Length <= 0 Then Throw New ArgumentException("Entropy") End If Dim inBuffer(Length) As Byte Dim outBuffer() As Byte ' Read the encrypted data from a stream. If S.CanRead Then S.Read(inBuffer, 0, Length) outBuffer = ProtectedData.Unprotect(inBuffer, Entropy, Scope) Else Throw New IOException("Could not read the stream.") End If ' Return the length that was written to the stream. Return outBuffer End Function 'DecryptDataFromStream End Module 'MemoryProtectionSample
Compiling the Code
-
Include a reference to System.Security.dll.
-
Include the System, System.IO, System.Security.Cryptography, and System.Text namespace.