データの暗号化
更新 : 2007 年 11 月
対称暗号化と非対称暗号化の実行時には、異なるプロセスが使用されます。対称暗号化はストリームに対して実行されるため、大量のデータを暗号化する場合に便利です。非対称暗号化は少量のバイトに対して実行されるため、データが少ない場合にだけ役立ちます。
対称暗号化方式
マネージ対称暗号化クラスは、CryptoStream という、ストリームに読み込まれたデータを暗号化する特別なストリーム クラスと共に使用されます。CryptoStream クラスは、マネージ ストリーム クラス、ICryptoTransform インターフェイス (暗号化アルゴリズムを実装するクラスから作成されます)、および CryptoStream に許可されるアクセス権の種類を示す CryptoStreamMode 列挙型を使用して初期化されます。CryptoStream クラスの初期化は、FileStream、MemoryStream、NetworkStream など、Stream クラスから派生する任意のクラスによって実行できます。これらのクラスを使用し、各種のストリーム オブジェクトに対して対称暗号化を実行できます。
RijndaelManaged クラスの新しいインスタンスを作成する方法を次の例に示します。このクラスは Rijndael 暗号化アルゴリズムを実装し、それを使用して CryptoStream クラスで暗号化を実行します。この例では、任意のタイプのマネージ ストリームにできる MyStream というストリーム オブジェクトによって CryptoStream が初期化されます。暗号化で使用されるキーと IV は、RijndaelManaged クラスの CreateEncryptor メソッドに渡されます。この例では、RMCrypto から生成された既定のキーと IV が使用されます。最後に CryptoStreamMode.Write が渡され、ストリームへの書き込みアクセスが指定されます。
Dim RMCrypto As New RijndaelManaged()
Dim CryptStream As New CryptoStream(MyStream, RMCrypto.CreateEncryptor(RMCrypto.Key, RMCrypto.IV), CryptoStreamMode.Write)
RijndaelManaged RMCrypto = new RijndaelManaged();
CryptoStream CryptStream = new CryptoStream(MyStream, RMCrypto.CreateEncryptor(), CryptoStreamMode.Write);
上記のコードを実行すると、CryptoStream オブジェクトに書き込まれたすべてのデータが Rijndael アルゴリズムで暗号化されます。
ストリームを作成し、ストリームを暗号化し、ストリームに書き込み、ストリームを閉じるプロセス全体を次の例に示します。この例では、CryptoStream クラスと RijndaelManaged クラスを使用して暗号化されるネットワーク ストリームを作成します。メッセージは、StreamWriter クラスによって暗号ストリームに書き込まれます。
Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Net.Sockets
Module Module1
Sub Main()
Try
'Create a TCP connection to a listening TCP process.
'Use "localhost" to specify the current computer or
'replace "localhost" with the IP address of the
'listening process.
Dim TCP As New TcpClient("localhost", 11000)
'Create a network stream from the TCP connection.
Dim NetStream As NetworkStream = TCP.GetStream()
'Create a new instance of the RijndaelManaged class
'and encrypt the stream.
Dim RMCrypto As New RijndaelManaged()
Dim Key As Byte() = {&H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16}
Dim IV As Byte() = {&H1, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &H10, &H11, &H12, &H13, &H14, &H15, &H16}
'Create a CryptoStream, pass it the NetworkStream, and encrypt
'it with the Rijndael class.
Dim CryptStream As New CryptoStream(NetStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write)
'Create a StreamWriter for easy writing to the
'network stream.
Dim SWriter As New StreamWriter(CryptStream)
'Write to the stream.
SWriter.WriteLine("Hello World!")
'Inform the user that the message was written
'to the stream.
Console.WriteLine("The message was sent.")
'Close all the connections.
SWriter.Close()
CryptStream.Close()
NetStream.Close()
TCP.Close()
Catch
'Inform the user that an exception was raised.
Console.WriteLine("The connection failed.")
End Try
End Sub
End Module
using System;
using System.IO;
using System.Security.Cryptography;
using System.Net.Sockets;
public class main
{
public static void Main(string[] args)
{
try
{
//Create a TCP connection to a listening TCP process.
//Use "localhost" to specify the current computer or
//replace "localhost" with the IP address of the
//listening process.
TcpClient TCP = new TcpClient("localhost",11000);
//Create a network stream from the TCP connection.
NetworkStream NetStream = TCP.GetStream();
//Create a new instance of the RijndaelManaged class
// and encrypt the stream.
RijndaelManaged RMCrypto = new RijndaelManaged();
byte[] Key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
byte[] IV = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16};
//Create a CryptoStream, pass it the NetworkStream, and encrypt
//it with the Rijndael class.
CryptoStream CryptStream = new CryptoStream(NetStream,
RMCrypto.CreateEncryptor(Key, IV),
CryptoStreamMode.Write);
//Create a StreamWriter for easy writing to the
//network stream.
StreamWriter SWriter = new StreamWriter(CryptStream);
//Write to the stream.
SWriter.WriteLine("Hello World!");
//Inform the user that the message was written
//to the stream.
Console.WriteLine("The message was sent.");
//Close all the connections.
SWriter.Close();
CryptStream.Close();
NetStream.Close();
TCP.Close();
}
catch
{
//Inform the user that an exception was raised.
Console.WriteLine("The connection failed.");
}
}
}
上記の例を正しく実行するためには、TCPCLient クラスで指定された IP アドレスとポート番号で待機するプロセスが必要です。待機プロセスが存在すると、コードはその待機プロセスに接続し、Rijndael 対称アルゴリズムによってストリームを暗号化して、ストリームに "Hello World!" と書き込みます。コードが正しく実行されると、コンソールに次のテキストが表示されます。
The message was sent.
ただし、待機プロセスが見つからない場合、または例外が発生した場合は、コンソールに次のテキストが表示されます。
The connection failed.
非対称暗号化方式
通常、非対称アルゴリズムが使用されるのは、共通キーや IV などの少量のデータを暗号化する場合です。一般に、非対称暗号化を実行する人は、他者によって作成された公開キーを使用することになります。.NET Framework には、この目的のための RSACryptoServiceProvider クラスが用意されています。
公開キー情報を使用して共通キーと IV を暗号化する例を次に示します。この例では、第三者の公開キーを表現する 2 つのバイト配列を初期化しています。RSAParameters オブジェクトはこれらの値に初期化されます。次に、RSACryptoServiceProvider.ImportParameters メソッドを使用して、RSAParameters オブジェクト (およびそれが表現する公開キー) が RSACryptoServiceProvider にインポートされます。最後に、RijndaelManaged クラスによって作成された秘密キーと IV を暗号化します。この例では、システムに 128 ビットの暗号化がインストールされている必要があります。
Imports System
Imports System.Security.Cryptography
Module Module1
Sub Main()
'Initialize the byte arrays to the public key information.
Dim PublicKey As Byte() = {214, 46, 220, 83, 160, 73, 40, 39, 201, 155, 19,202, 3, 11, 191, 178, 56, 74, 90, 36, 248, 103, 18, 144, 170, 163, 145, 87, 54, 61, 34, 220, 222, 207, 137, 149, 173, 14, 92, 120, 206, 222, 158, 28, 40, 24, 30, 16, 175, 108, 128, 35, 230, 118, 40, 121, 113, 125, 216, 130, 11, 24, 90, 48, 194, 240, 105, 44, 76, 34, 57, 249, 228, 125, 80, 38, 9, 136, 29, 117, 207, 139, 168, 181, 85, 137, 126, 10, 126, 242, 120, 247, 121, 8, 100, 12, 201, 171, 38, 226, 193, 180, 190, 117, 177, 87, 143, 242, 213, 11, 44, 180, 113, 93, 106, 99, 179, 68, 175, 211, 164, 116, 64, 148, 226, 254, 172, 147}
Dim Exponent As Byte() = {1, 0, 1}
'Create values to store encrypted symmetric keys.
Dim EncryptedSymmetricKey() As Byte
Dim EncryptedSymmetricIV() As Byte
'Create a new instance of the RSACryptoServiceProvider class.
Dim RSA As New RSACryptoServiceProvider()
'Create a new instance of the RSAParameters structure.
Dim RSAKeyInfo As New RSAParameters()
'Set RSAKeyInfo to the public key values.
RSAKeyInfo.Modulus = PublicKey
RSAKeyInfo.Exponent = Exponent
'Import key parameters into RSA.
RSA.ImportParameters(RSAKeyInfo)
'Create a new instance of the RijndaelManaged class.
Dim RM As New RijndaelManaged()
'Encrypt the symmetric key and IV.
EncryptedSymmetricKey = RSA.Encrypt(RM.Key, False)
EncryptedSymmetricIV = RSA.Encrypt(RM.IV, False)
End Sub
End Module
using System;
using System.Security.Cryptography;
class Class1
{
static void Main()
{
//Initialize the byte arrays to the public key information.
byte[] PublicKey = {214,46,220,83,160,73,40,39,201,155,19,202,3,11,191,178,56,
74,90,36,248,103,18,144,170,163,145,87,54,61,34,220,222,
207,137,149,173,14,92,120,206,222,158,28,40,24,30,16,175,
108,128,35,230,118,40,121,113,125,216,130,11,24,90,48,194,
240,105,44,76,34,57,249,228,125,80,38,9,136,29,117,207,139,
168,181,85,137,126,10,126,242,120,247,121,8,100,12,201,171,
38,226,193,180,190,117,177,87,143,242,213,11,44,180,113,93,
106,99,179,68,175,211,164,116,64,148,226,254,172,147};
byte[] Exponent = {1,0,1};
//Create values to store encrypted symmetric keys.
byte[] EncryptedSymmetricKey;
byte[] EncryptedSymmetricIV;
//Create a new instance of the RSACryptoServiceProvider class.
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
//Create a new instance of the RSAParameters structure.
RSAParameters RSAKeyInfo = new RSAParameters();
//Set RSAKeyInfo to the public key values.
RSAKeyInfo.Modulus = PublicKey;
RSAKeyInfo.Exponent = Exponent;
//Import key parameters into RSA.
RSA.ImportParameters(RSAKeyInfo);
//Create a new instance of the RijndaelManaged class.
RijndaelManaged RM = new RijndaelManaged();
//Encrypt the symmetric key and IV.
EncryptedSymmetricKey = RSA.Encrypt(RM.Key, false);
EncryptedSymmetricIV = RSA.Encrypt(RM.IV, false);
}
}