方法 : データ保護を使用する
更新 : 2007 年 11 月
.NET Framework では、データ保護 API (DPAPI: Data Protection API) へのアクセスを提供します。DPAPI を使用すると、現在のユーザー アカウントまたは現在のコンピュータの情報を使用してデータを暗号化できます。DPAPI を使用することにより、暗号化キーの明示的な生成および保存という難しい問題を軽減できます。
メモリ内バイトの配列を暗号化するには、ProtectedMemory クラスを使用します。この機能は、Microsoft Windows XP 以降のオペレーティング システムで使用できます。現在のプロセスによって暗号化されたメモリの復号化は、現在のプロセスのみによって、すべてのプロセスによって、または同じユーザー コンテキストから行うことができるように指定できます。ProtectedMemory オプションの詳細については、MemoryProtectionScope 列挙体のトピックを参照してください。
バイトの配列のコピーを暗号化するには、ProtectedData クラスを使用します。この機能は、Microsoft Windows 2000 以降のオペレーティング システムで使用できます。現在のユーザー アカウントによって暗号化されたデータを同じユーザー カウントのみによって復号化できるように指定したり、現在のユーザー アカウントによって暗号化されたデータをコンピュータ上の任意のアカウントによって復号化できるように指定したりできます。ProtectedData オプションの詳細については、DataProtectionScope 列挙体のトピックを参照してください。
データ保護を使用してインメモリ データを暗号化するには
- 静的メソッド Protect を呼び出し、暗号化するバイトの配列、エントロピ、およびメモリ保護のスコープを渡します。
データ保護を使用してインメモリ データを復号化するには
- 静的メソッド Unprotect を呼び出し、復号化するバイトの配列およびメモリ保護のスコープを渡します。
データ保護を使用してデータをファイルまたはストリームに暗号化するには
ランダム エントロピを作成します。
静的メソッド Protect を呼び出し、暗号化するバイトの配列、エントロピ、およびデータ保護のスコープを渡します。
暗号化されたデータをファイルまたはストリームに書き込みます。
データ保護を使用してファイルまたはストリームからデータを復号化するには
ファイルまたはストリームから暗号化されたデータを読み込みます。
静的メソッド Unprotect を呼び出し、復号化するバイトの配列およびデータ保護のスコープを渡します。
使用例
暗号化と復号化の 2 つの形式のコード例を次に示します。最初のコード例では、インメモリのバイト配列を暗号化し、次に復号化します。2 番目のコード例では、バイト配列のコピーを暗号化し、ファイルに保存し、そのファイルからデータを読み込み、データを復号化します。この例では、元のデータ、暗号化されたデータ、および復号化されたデータを表示します。
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
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
public class MemoryProtectionSample
{
public static void Main()
{
Run();
}
public static void Run()
{
try
{
///////////////////////////////
//
// Memory Encryption - ProtectedMemory
//
///////////////////////////////
// Create the original data to be encrypted (The data length should be a multiple of 16).
byte[] toEncrypt = 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.
FileStream fStream = new FileStream("Data.dat", FileMode.OpenOrCreate);
// Create some random entropy.
byte[] entropy = 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.
int bytesWritten = 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.
byte[] decryptData = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, bytesWritten);
fStream.Close();
Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(decryptData));
}
catch (Exception e)
{
Console.WriteLine("ERROR: " + e.Message);
}
}
public static void EncryptInMemoryData(byte[] Buffer, MemoryProtectionScope Scope )
{
if (Buffer.Length <= 0)
throw new ArgumentException("Buffer");
if (Buffer == null)
throw new ArgumentNullException("Buffer");
// Encrypt the data in memory. The result is stored in the same same array as the original data.
ProtectedMemory.Protect(Buffer, Scope);
}
public static void DecryptInMemoryData(byte[] Buffer, MemoryProtectionScope Scope)
{
if (Buffer.Length <= 0)
throw new ArgumentException("Buffer");
if (Buffer == null)
throw new ArgumentNullException("Buffer");
// Decrypt the data in memory. The result is stored in the same same array as the original data.
ProtectedMemory.Unprotect(Buffer, Scope);
}
public static byte[] CreateRandomEntropy()
{
// Create a byte array to hold the random value.
byte[] entropy = new byte[16];
// Create a new instance of the RNGCryptoServiceProvider.
// Fill the array with a random value.
new RNGCryptoServiceProvider().GetBytes(entropy);
// Return the array.
return entropy;
}
public static int EncryptDataToStream(byte[] Buffer, byte[] Entropy, DataProtectionScope Scope, Stream S)
{
if (Buffer.Length <= 0)
throw new ArgumentException("Buffer");
if (Buffer == null)
throw new ArgumentNullException("Buffer");
if (Entropy.Length <= 0)
throw new ArgumentException("Entropy");
if (Entropy == null)
throw new ArgumentNullException("Entropy");
if (S == null)
throw new ArgumentNullException("S");
int length = 0;
// Encrypt the data in memory. The result is stored in the same same array as the original data.
byte[] encrptedData = ProtectedData.Protect(Buffer, Entropy, Scope);
// Write the encrypted data to a stream.
if (S.CanWrite && encrptedData != null)
{
S.Write(encrptedData, 0, encrptedData.Length);
length = encrptedData.Length;
}
// Return the length that was written to the stream.
return length;
}
public static byte[] DecryptDataFromStream(byte[] Entropy, DataProtectionScope Scope, Stream S, int Length)
{
if (S == null)
throw new ArgumentNullException("S");
if (Length <= 0 )
throw new ArgumentException("Length");
if (Entropy == null)
throw new ArgumentNullException("Entropy");
if (Entropy.Length <= 0)
throw new ArgumentException("Entropy");
byte[] inBuffer = new byte[Length];
byte[] outBuffer;
// Read the encrypted data from a stream.
if (S.CanRead)
{
S.Read(inBuffer, 0, Length);
outBuffer = ProtectedData.Unprotect(inBuffer, Entropy, Scope);
}
else
{
throw new IOException("Could not read the stream.");
}
// Return the length that was written to the stream.
return outBuffer;
}
}
コードのコンパイル方法
System.Security.dll への参照を含めます。
System、System.IO、System.Security.Cryptography、および System.Text の各名前空間を含めます。