Condividi tramite


Procedura: proteggere un messaggio digitalmente per un destinatario

In questo esempio viene creato un messaggio CMS/PKCS #7 protetto digitalmente utilizzando System.Security.Cryptography.Pkcs. Il messaggio viene crittografato per un destinatario singolo e viene quindi decrittografato utilizzando la chiave privata di tale destinatario. In questo esempio viene utilizzato l'oggetto EnvelopedCms, che consente di crittografare messaggi, ovvero proteggerli digitalmente, per uno o più destinatari.

Esempio

Nell'esempio vengono utilizzate le classi seguenti:

Per l'esecuzione dell'esempio seguente in un computer singolo è necessario che entrambi gli archivi AddressBook e My certificate contengano un certificato con chiave pubblica con il nome soggetto "Recipient1". È inoltre necessario che la chiave privata associata sia archiviata in tale computer. Il codice di esempio innanzitutto funge da mittente del messaggio e quindi da destinatario, utilizzando le stesse credenziali di chiave pubblica in ogni ruolo. Come mittente, il codice di esempio cerca nell'archivio certificati AddressBook il certificato del destinatario e lo utilizza per crittografare il messaggio. Come destinatario, cerca il certificato nell'archivio My certificate e utilizza la chiave privata associata per decrittografare il messaggio.

NoteNota:

L'esempio ha solo scopo illustrativo. È possibile che negli ambienti di produzione venga utilizzato un modello diverso, nel quale il mittente e il destinatario del messaggio vengono eseguiti in processi diversi con le relative rispettive credenziali di chiave pubblica univoche.

Uno degli strumenti disponibili per impostare questo esempio è Makecert.exe. LoCertificate Creation Tool (Makecert.exe) è un'utilità che consente di generare in modo semplice i certificati di prova. In un ambiente di produzione i certificati vengono generati da un'autorità di certificazione.

Il comando Makecert seguente genera le chiavi private e i certificati di chiave pubblica necessari.

Makecert -n "CN=Recipient1" -ss My

Il comando inserisce il certificato di chiave pubblica appropriato nell'archivio My certificate e genera la chiave privata. A questo punto è necessario ottenere una copia del certificato di chiave pubblica nell'archivio certificati AddressBook. A tale scopo, esportare il certificato di chiave pubblica e quindi importarlo nell'archivio certificati AddressBook attenendosi alla procedura Procedura: esportare e importare un certificato di chiave pubblica.

// 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 EnvelopAMessageForOneRecipient
{
    class EnvelopedCmsSingleRecipient
    {
        const String recipientName = "Recipient1";

        static void Main(string[] args)
        {
            Console.WriteLine("System.Security.Cryptography.Pkcs " +
            "Sample: Single-recipient encrypted and decrypted message");
            
            //  Original message.
            const String msg = "Here is your personal identification number:";

            Console.WriteLine("\nOriginal message (len {0}): {1}  ",
                              msg.Length, msg);

            //  Convert message to an 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 recipient's certificate is necessary to encrypt
            //  the message for that recipient.
            X509Certificate2 recipientCert = GetRecipientCert();

            Console.WriteLine("\n\n----------------------");
            Console.WriteLine("     SENDER SIDE      ");
            Console.WriteLine("----------------------\n");

            byte[] encodedEnvelopedCms = EncryptMsg(msgBytes,
                recipientCert);

            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");

            Byte[] decryptedMsg = DecryptMsg(encodedEnvelopedCms);

            //  Convert Unicode bytes to the original message string.
            Console.WriteLine("\nDecrypted Message: {0}",
                unicode.GetString(decryptedMsg));
        }

        //  Open the AddressBook (also known as Other in 
        //  Internet Explorer) certificate store and search for 
        //  a recipient certificate with which to encrypt the 
        //  message. The certificate must have a subject name 
        //  of "Recipient1".
        static public X509Certificate2 GetRecipientCert()
        {
            //  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 certificate.
            //  For purposes of this sample, do not validate the
            //  certificate. Note that in a production environment,
            //  validating the certificate will probably be necessary.
            X509Certificate2Collection certColl = storeAddressBook.
                Certificates.Find(X509FindType.FindBySubjectName,
                recipientName, false);
            Console.WriteLine(
                "Found {0} certificates in the {1} store with name {2}",
                certColl.Count, storeAddressBook.Name, recipientName);

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

            storeAddressBook.Close();

            return certColl[0];
        }

        //  Encrypt the message with the public key of
        //  the recipient. This is done by enveloping the message by
        //  using an EnvelopedCms object.
        static public byte[] EncryptMsg(
            Byte[] msg,
            X509Certificate2 recipientCert)
        {
            //  Place the message in a ContentInfo object.
            //  This is required to build an EnvelopedCms object.
            ContentInfo contentInfo = new ContentInfo(msg);

            //  Instantiate an 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 CmsRecipient object that
            //  represents information about the recipient 
            //  to encrypt the message for.
            CmsRecipient recip1 = new CmsRecipient(
                SubjectIdentifierType.IssuerAndSerialNumber,
                recipientCert);

            Console.Write(
                "Encrypting data for a single recipient of " +
                "subject name {0} ... ",
                recip1.Certificate.SubjectName.Name);
            //  Encrypt the message for the recipient.
            envelopedCms.Encrypt(recip1);
            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.
        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 1 for this example.
            DisplayEnvelopedCms(envelopedCms, false);

            //  Decrypt the message for the single recipient.
            Console.Write("Decrypting Data ... ");
            envelopedCms.Decrypt(envelopedCms.RecipientInfos[0]);
            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 CMS/PKCS #7 Message " +
                "Information:");
            Console.WriteLine(
                "\tThe number of recipients for the Enveloped CMS/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 CMS/PKCS " +
                    "#7 Content", e);
            }
            Console.WriteLine();
        }
    }
}

Vedere anche

Attività

Procedura: firmare messaggi da parte di un firmatario
Procedura: firmare un messaggio da parte di più firmatari
Procedura: controfirmare un messaggio
Procedura: proteggere un messaggio digitalmente per più destinatari

Concetti

Procedura: firmare e proteggere digitalmente un messaggio

Footer image

Copyright © 2007 Microsoft Corporation. Tutti i diritti riservati.