Procédure de mise d'un message sous enveloppe pour plusieurs destinataires

Cet exemple crée un message CMS/PKCS #7 sous enveloppe à l'aide de System.Security.Cryptography.Pkcs. Le message est chiffré pour plusieurs destinataires. Il est ensuite déchiffré pour chaque destinataire à l'aide de la clé privée du destinataire en question. Cet exemple utilise l'objet EnvelopedCms, qui permet de chiffrer des messages pour un ou plusieurs destinataires, c'est-à-dire de les mettre sous enveloppe.

Exemple

Cet exemple utilise les classes suivantes :

Pour fonctionner sur un seul ordinateur, l'exemple suivant nécessite que les magasins de certificats AddressBook et My contiennent deux certificats de clé publique avec les noms d'objet « Destinataire1 » et « Destinataire2 ». Cet exemple nécessite également que les clés privées associées soient stockées sur cet ordinateur. L'exemple de code opère d'abord en tant qu'émetteur du message, puis en tant que destinataire du message. Les mêmes informations d'identification de clé publique sont utilisées pour chaque rôle. En tant que tel, l'exemple nécessite que le certificat de clé publique se trouve dans deux magasins. En tant qu'émetteur, l'exemple recherche dans le magasin de certificats AddressBook le certificat du destinataire qu'il utilise pour chiffrer le message. En tant que destinataire, il recherche le certificat dans le magasin de certificats My et utilise la clé privée associée pour déchiffrer le message.

NoteRemarque :

Cet exemple n'est utilisé qu'à des fins d'illustration. Les environnements de production peuvent utiliser un modèle différent dans lequel l'expéditeur et le destinataire du message s'exécutent selon des processus différents avec les informations d'identification de leur clé publique unique.

Vous pouvez configurer cet exemple à l'aide de l'utilitaire Makecert.exe, qui constitue une des multiples façons de procéder. Certificate Creation Tool (Makecert.exe) est un utilitaire très pratique pour tester les certificats. Dans un environnement de production, les certificats sont générés par une autorité de certification.

Les commandes Makecert suivantes génèrent les certificats de clé publique ainsi que les clés privées nécessaires.

Makecert -n "CN=Destinataire1" -ss My

Makecert -n "CN=Destinataire2" -ss My

Ces commandes placent les certificats de clé publique appropriés dans le magasin de certificats My. À ce stade, vous devez exporter les certificats de clé publique pour ensuite les importer dans le magasin de certificats AddressBook en procédant comme indiqué dans Procédure d'exportation et d'importation d'un certificat de clé publique pour chaque destinataire.

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

Voir aussi

Tâches

Procédure de signature de messages par un signataire
Procédure de signature d'un message par plusieurs signataires
Procédure de contre-signature d'un message
Procédure de mise d'un message sous enveloppe pour un seul destinataire

Concepts

Procédure de signature et de mise sous enveloppe d'un message

Footer image

Copyright ©2007 par Microsoft Corporation. Tous droits réservés.