Freigeben über


Verfahrensweise: Versehen einer Nachricht mit einem Umschlag für mehrere Empfänger

In diesem Beispiel wird eine mit einem CMS/PKCS #7-Umschlag versehene Nachricht unter Verwendung von System.Security.Cryptography.Pkcs erstellt. Die Nachricht wird für mehrere Empfänger verschlüsselt. Anschließend wird die Nachricht für jeden Empfänger mithilfe des privaten Schlüssels des jeweiligen Empfängers entschlüsselt. Das Beispiel verwendet das EnvelopedCms-Objekt, das es ermöglicht, Nachrichten für einen oder mehrere Empfänger zu verschlüsseln oder mit einem Umschlag zu versehen.

Beispiel

In diesem Beispiel werden die folgenden Klassen verwendet:

Für die Ausführung auf einem einzelnen Computer ist für das folgende Beispiel erforderlich, dass zwei Zertifikate mit öffentlichem Schlüssel mit den Antragstellernamen "Recipient1" und "Recipient2" in den Zertifikatspeichern "AddressBook" und "My" enthalten sind. Darüber hinaus müssen die zugeordneten privaten Schlüssel auf diesem Computer gespeichert sein. Der Beispielcode agiert erst als Absender der Nachricht und übernimmt anschließend die Rolle des Nachrichtenempfängers. In beiden Rollen werden dieselben Anmeldeinformationen des öffentlichen Schlüssels verwendet. Deshalb ist es für das Beispiel erforderlich, dass das Zertifikat mit öffentlichem Schlüssel in zwei Speichern vorhanden ist. Als Absender durchsucht der Beispielcode den Zertifikatspeicher "AddressBook" nach dem Zertifikat des Empfängers und verschlüsselt damit die Nachricht. Als Empfänger durchsucht der Code den Zertifikatspeicher "My" nach dem Zertifikat und entschlüsselt mit dem zugeordneten privaten Schlüssel die Nachricht.

NoteHinweis:

Dieses Beispiel dient nur der Veranschaulichung. In Produktionsumgebungen kann ein anderes Modell verwendet werden, in dem Absender und Empfänger der Nachricht in verschiedenen Prozessen mit ihren eindeutigen Anmeldeinformationen des öffentlichen Schlüssels ausgeführt werden.

Richten Sie dieses Beispiel mithilfe des Dienstprogramms Makecert.exe ein; dies ist nur eine von vielen Möglichkeiten. Certificate Creation Tool (Makecert.exe) ist ein komfortables Dienstprogramm zum Testen von Zertifikaten. In einer Produktionsumgebung werden Zertifikate von einer Zertifizierungsstelle generiert.

Mithilfe der folgenden Makecert-Befehle werden die erforderlichen Zertifikate mit öffentlichem Schlüssel und die privaten Schlüssel generiert.

Makecert -n "CN=Recipient1" -ss My

Makecert -n "CN=Recipient2" -ss My

Diese Befehle legen die entsprechenden Zertifikate mit öffentlichem Schlüssel im Zertifikatspeicher "My" ab. Zu diesem Zeitpunkt müssen Sie die Zertifikate mit öffentlichem Schlüssel exportieren und dann in den Zertifikatspeicher "AddressBook" importieren, indem Sie für jeden Empfänger das in Verfahrensweise: Exportieren und Importieren eines Zertifikats mit öffentlichem Schlüssel geschilderte Verfahren verwenden.

// 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();
        }
    }
}

Siehe auch

Aufgaben

Verfahrensweise: Signieren von Nachrichten durch einen Signierer
Verfahrensweise: Signieren einer Nachricht durch mehrere Signierer
Verfahrensweise: Gegensignieren einer Nachricht
Verfahrensweise: Versehen einer Nachricht mit einem Umschlag für einen Empfänger

Konzepte

Verfahrensweise: Signieren und Versehen einer Nachricht mit einem Umschlag

Footer image

Copyright © 2007 by Microsoft Corporation. Alle Rechte vorbehalten.