方法 :複数の受信者に対するメッセージをエンベロープ化する
この例では、System.Security.Cryptography.Pkcs を使用して、エンベロープ化された CMS/PKCS #7 メッセージを作成します。メッセージは、複数の受信者に対して暗号化されます。メッセージはその後、各受信者の秘密キーを使用して、受信者に対して復号化されます。この例では、EnvelopedCms オブジェクトを使用しています。このオブジェクトにより、単一または複数の受信者に対してメッセージを暗号化 (エンベロープ化) できるようになります。
例
この例では、次のクラスを使用します。
EnvelopedCms
単一のコンピュータで実行するには、次の例では、サブジェクト名が "Recipient1" および "Recipient2" である 2 つの公開キー証明書が、AddressBook 証明書ストアと My 証明書ストアの両方に含まれている必要があります。また、関連付けられた秘密キーがそのコンピュータ上に格納されていることも必要です。このコード例は、最初はメッセージの送信者として、次にメッセージの受信者として機能します。それぞれの役割で同じ公開キー資格情報が使用されます。そのため、この例では、公開キー証明書が 2 つのストアに含まれている必要があります。この例では、送信者としては AddressBook 証明書ストアで受信者の証明書を検索し、その証明書を使用してメッセージを暗号化します。受信者としては、My 証明書ストアで証明書を検索し、関連付けられた秘密キーを使用してメッセージを復号化します。
メモ : |
---|
この例は、例を示すことのみを目的としています。実稼動環境では、メッセージの送信者および受信者が、異なるプロセスで独自の公開キー資格情報を使用して実行する、別のモデルが使用される場合があります。 |
いくつか方法はありますが、この例は Makecert.exe ユーティリティを使用してセットアップします。Certificate Creation Tool (Makecert.exe) は、証明書をテストするための便利なユーティリティです。実稼働環境では、証明書は証明機関によって生成されます。
次の Makecert コマンドは、必要な公開キー証明書と秘密キーを生成します。
Makecert -n "CN=Recipient1" -ss My
Makecert -n "CN=Recipient2" -ss My
これらのコマンドを実行すると、適切な公開キー証明書が My 証明書ストアに配置されます。この時点で、受信者ごとに、「方法 :公開キー証明書をエクスポートしてインポートする」の手順に従って公開キー証明書をエクスポートし、その証明書を AddressBook 証明書ストアにインポートする必要があります。
// Copyright (c) Microsoft Corporation. All rights reserved.
#region Using directives
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;
using System.Text;
#endregion
namespace EnvelopAMessageForMultipleRecipients
{
class EnvelopedCmsMultipleRecipients
{
const String recipientName1 = "Recipient1";
const String recipientName2 = "Recipient2";
static void Main(string[] args)
{
Console.WriteLine("System.Security.Cryptography.Pkcs " +
"Sample: Multiple-recipient " +
"encrypted and decrypted message");
// Original message.
const String msg = "To all department heads: The following " +
"organizational changes will be announced next week:";
Console.WriteLine("\nOriginal message (len {0}): {1} ",
msg.Length, msg);
// Convert message to array of Unicode bytes for signing.
UnicodeEncoding unicode = new UnicodeEncoding();
byte[] msgBytes = unicode.GetBytes(msg);
Console.WriteLine("\n\n------------------------------");
Console.WriteLine(" SETUP OF CREDENTIALS ");
Console.WriteLine("------------------------------\n");
// The recipients' certificates are necessary to encrypt
// the message for those recipients.
X509Certificate2Collection recipientCerts = GetRecipientCerts();
Console.WriteLine("\n\n----------------------");
Console.WriteLine(" SENDER SIDE ");
Console.WriteLine("----------------------\n");
byte[] encodedEnvelopedCms = EncryptMsg(msgBytes,
recipientCerts);
Console.Write("\nMessage after encryption (len {0}): ",
encodedEnvelopedCms.Length);
foreach (byte b in encodedEnvelopedCms)
{
Console.Write("{0:x}", b);
}
Console.WriteLine();
Console.WriteLine("\n\n------------------------");
Console.WriteLine(" RECIPIENT SIDE ");
Console.WriteLine("------------------------\n");
// Decrypts the message for one of the recipients.
// Return the decrypted message to display it.
Byte[] decryptedMsg = DecryptMsg(encodedEnvelopedCms);
// Convert Unicode bytes to the original message string.
Console.WriteLine("\nDecrypted Message: {0}",
unicode.GetString(decryptedMsg));
}
// Open the AddressBook (called Other in Internet Explorer)
// certificate store and search for recipient
// certificates with which to encrypt the message. It must
// include two certificates: one with the subject name
// "Recipient1", and one with the subject name "Recipient2".
static public X509Certificate2Collection GetRecipientCerts()
{
// Open the AddressBook local user X509 certificate store.
X509Store storeAddressBook = new X509Store(StoreName.
AddressBook, StoreLocation.CurrentUser);
storeAddressBook.Open(OpenFlags.ReadOnly);
// Display certificates to help troubleshoot the
// example's setup.
Console.WriteLine(
"Found certs with the following subject names in the " +
"{0} store:", storeAddressBook.Name);
foreach (X509Certificate2 cert in storeAddressBook.Certificates)
{
Console.WriteLine("\t{0}", cert.SubjectName.Name);
}
// Get recipient certificates.
// For purposes of this sample, do not validate the
// certificates. Note that in a production environment,
// validating the certificates will probably be necessary.
// Get first recipient certificate.
X509Certificate2Collection certColl = storeAddressBook.
Certificates.Find(X509FindType.FindBySubjectName,
recipientName1, false);
Console.WriteLine(
"Found {0} certificates in the {1} store with name {2}",
certColl.Count, storeAddressBook.Name, recipientName1);
X509Certificate2Collection recipientCerts =
new X509Certificate2Collection();
// Check to see if the certificate suggested by the example
// requirements is not present.
if (certColl.Count == 0)
{
Console.WriteLine(
"A suggested certificate to use for this example " +
"is not in the certificate store. Select " +
"an alternate certificate to use for " +
"signing the message.");
}
recipientCerts.Add(certColl[0]);
// Get second recipient certificate.
certColl = storeAddressBook.
Certificates.Find(X509FindType.FindBySubjectName,
recipientName2, false);
Console.WriteLine(
"Found {0} certificates in the {1} store with name {2}",
certColl.Count, storeAddressBook.Name, recipientName2);
// Check to see if the certificate suggested by the example
// requirements is not present.
if (certColl.Count == 0)
{
Console.WriteLine(
"A suggested certificate to use for this example " +
"is not in the certificate store. Select " +
"an alternate certificate to use for " +
"signing the message.");
}
recipientCerts.Add(certColl[0]);
storeAddressBook.Close();
return recipientCerts;
}
// Encrypt the message for each recipient by using the public
// key of that recipient. This is done by
// enveloping the message by using an EnvelopedCms object.
static public byte[] EncryptMsg(
Byte[] msg,
X509Certificate2Collection recipientCerts)
{
// Place message in a ContentInfo object.
// This is required to build an EnvelopedCms object.
ContentInfo contentInfo = new ContentInfo(msg);
// Instantiate EnvelopedCms object with the ContentInfo
// above.
// Has default SubjectIdentifierType IssuerAndSerialNumber.
// Has default ContentEncryptionAlgorithm property value
// RSA_DES_EDE3_CBC.
EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo);
// Formulate a CmsRecipientCollection object that
// represents information about the set of recipients
// to encrypt the message for.
CmsRecipientCollection recips =
new CmsRecipientCollection(
SubjectIdentifierType.IssuerAndSerialNumber,
recipientCerts);
Console.WriteLine("\nEncrypting data for multiple " +
"recipients with subject names: ");
foreach (CmsRecipient recip in recips)
{
Console.WriteLine("\t" +
recip.Certificate.SubjectName.Name);
}
// Encrypt the message for the collection of recipients.
envelopedCms.Encrypt(recips);
Console.WriteLine("Done.");
// The encoded EnvelopedCms message contains the message
// ciphertext and the information about each recipient
// that the message was enveloped for.
return envelopedCms.Encode();
}
// Decrypt the encoded EnvelopedCms message for one of the
// recipients.
static public Byte[] DecryptMsg(byte[] encodedEnvelopedCms)
{
// Prepare object in which to decode and decrypt.
EnvelopedCms envelopedCms = new EnvelopedCms();
// Decode the message.
envelopedCms.Decode(encodedEnvelopedCms);
// Display the number of recipients the message is
// enveloped for; it should be 2 for this example.
DisplayEnvelopedCms(envelopedCms, false);
// Decrypt the message.
// The message is decrypted for the recipient that
// you find the first matching private key for.
// A line similar to the following, however,
// decrypts the message for a specified recipient. In
// in this case, the first recipient.
// envelopedCms.Decrypt(envelopedCms.RecipientInfos[0]);
Console.Write("Decrypting Data for one recipient ... ");
envelopedCms.Decrypt();
Console.WriteLine("Done.");
// The decrypted message occupies the ContentInfo property
// after the Decrypt method is invoked.
return envelopedCms.ContentInfo.Content;
}
// Display the ContentInfo property of an EnvelopedCms object.
static private void DisplayEnvelopedCmsContent(String desc,
EnvelopedCms envelopedCms)
{
Console.WriteLine(desc + " (length {0}): ",
envelopedCms.ContentInfo.Content.Length);
foreach (byte b in envelopedCms.ContentInfo.Content)
{
Console.Write(b.ToString() + " ");
}
Console.WriteLine();
}
// Display some properties of an EnvelopedCms object.
static private void DisplayEnvelopedCms(EnvelopedCms e,
Boolean displayContent)
{
Console.WriteLine("\nEnveloped PKCS #7 Message Information:");
Console.WriteLine(
"\tThe number of recipients for the Enveloped PKCS #7 " +
"is: {0}", e.RecipientInfos.Count);
for (int i = 0; i < e.RecipientInfos.Count; i++)
{
Console.WriteLine(
"\tRecipient #{0} has type {1}.",
i + 1,
e.RecipientInfos[i].RecipientIdentifier.Type);
}
if (displayContent)
{
DisplayEnvelopedCmsContent("Enveloped PKCS #7 Content", e);
}
Console.WriteLine();
}
}
}
関連項目
タスク
方法 :メッセージに単一の署名者が署名する
方法 :メッセージに複数の署名者が署名する
方法 :メッセージに副署名する
方法 :単一の受信者に対するメッセージをエンベロープ化する
概念
Copyright © 2007 by Microsoft Corporation.All rights reserved.