次の方法で共有


方法 :認証済み属性を署名付きメッセージに追加する

この例では、System.Security.Cryptography.Pkcs を使用して、署名付きの CMS/PKCS #7 メッセージを作成します。メッセージは、単一の署名者によって署名されます。メッセージには、認証済み属性としてタイムスタンプが含まれます。これは、メッセージの内容とタイムスタンプの両方が署名されることを意味しています。このメッセージの署名は後で検証され、メッセージの内容とタイムスタンプの両方が本物であるかどうかが確認されます。

この例では、デタッチされた CMS/PKCS #7 メッセージの使用法についても説明します。これは、メッセージの内容が CMS/PKCS #7 メッセージに格納されないことを意味します。このため、メッセージの内容を、CMS/PKCS #7 メッセージを検証するメソッドに渡す必要があります。

この例では、次のクラスを使用します。

次の例では、サブジェクト名が "MessageSigner1" である公開キー証明書が My 証明書ストアに含まれており、関連付けられた秘密キーが存在することが必要になります。

Noteメモ :

この例は、例を示すことのみを目的としています。実稼動環境では、メッセージの送信者および受信者が、異なるプロセスで独自の公開キー資格情報を使用して実行する、別のモデルが使用される場合があります。

いくつか方法はありますが、この例は、Makecert.exe ユーティリティを使用してセットアップします。Certificate Creation Tool (Makecert.exe) は、テスト証明書を生成するための便利なユーティリティです。実稼働環境では、証明書は証明機関によって生成されます。

以下の Makecert コマンドは、必要な公開キー証明書と秘密キーを生成します。

Makecert -n "CN=MessageSigner1" -ss My

// 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 AddAnAuthenticatedAttributeToASignedMessage
{
    class SignedCmsAuthenticatedAttribute
    {
        const String signerName = "MessageSigner1";

        static void Main(string[] args)
        {
            Console.WriteLine("System.Security.Cryptography.Pkcs " +
                "Sample: Single-signer signed and verified message");

            //  Original message.
            const String msg = "This is the message to be signed. " +
                      "A time stamp is included as an authenticated " +
                      "attribute.";

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

            //  Convert message to array of bytes for signing.
            Encoding unicode = Encoding.Unicode;
            byte[] msgBytes = unicode.GetBytes(msg);

            Console.WriteLine("\n\n------------------------------");
            Console.WriteLine("     SETUP OF CREDENTIALS     ");
            Console.WriteLine("------------------------------\n");

            X509Certificate2 signerCert = GetSignerCert();

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

            byte[] encodedSignedCms = SignMsg(msgBytes, signerCert);

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

            if (VerifyMsg(msgBytes, encodedSignedCms))
            {
                Console.WriteLine("\nMessage verified");
            }
            else
            {
                Console.WriteLine("\nMessage failed to verify");
            }
        }

        //  Open the My (or Personal) certificate store and search for
        //  credentials to sign the message with. The certificate
        //  must have the subject name "MessageSigner1".
        static public X509Certificate2 GetSignerCert()
        {
            //  Open the My certificate store.
            X509Store storeMy = new X509Store(StoreName.My,
                StoreLocation.CurrentUser);
            storeMy.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:", storeMy.Name);
            foreach (X509Certificate2 cert in storeMy.Certificates)
            {
                Console.WriteLine("\t{0}", cert.SubjectName.Name);
            }

            //  Find the signer's certificate.
            X509Certificate2Collection certColl =
                storeMy.Certificates.Find(X509FindType.FindBySubjectName,
                signerName, false);
            Console.WriteLine(
                "Found {0} certificates in the {1} store with name {2}",
                certColl.Count, storeMy.Name, signerName);

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

            //  If more than one matching cert, return the first one.
            return certColl[0];
        }

        //  Sign the message with the private key of the signer.
        static public byte[] SignMsg(
            Byte[] msg,
            X509Certificate2 signerCert)
        {
            //  Place message in a ContentInfo object.
            //  This is required to build a SignedCms object.
            ContentInfo contentInfo = new ContentInfo(msg);

            //  Instantiate SignedCms object with the ContentInfo above.
            //  Has default SubjectIdentifierType IssuerAndSerialNumber.
            //  Set the Detached property value to true, so message is
            //  not included in the encoded SignedCms.
            SignedCms signedCms = new SignedCms(contentInfo, true);

            //  Formulate a CmsSigner object for the signer.
            CmsSigner cmsSigner = new CmsSigner(signerCert);

            // Add an authenticated time stamp attribute to the signer.
            // The signing time is the current time.
            cmsSigner.SignedAttributes.Add(new Pkcs9SigningTime());

            //  Sign the CMS/PKCS #7 message.
            Console.Write("Computing signature with signer subject " +
                "name {0} ... ", signerCert.SubjectName.Name);
            signedCms.ComputeSignature(cmsSigner);
            Console.WriteLine("Done.");

            //  Encode the CMS/PKCS #7 message.
            return signedCms.Encode();
        }

        //  Verify the encoded SignedCms message and return a Boolean
        //  value that specifies whether the verification was successful.
        static public bool VerifyMsg(byte[] msgBytes, byte[] encodedSignedCms)
        {
            Pkcs9SigningTime st = new Pkcs9SigningTime();

            //  Build a ContentInfo object with the message bytes.  This
            //  is necessary because the message is detached from the
            //  SignedCms object.
            ContentInfo contentInfo = new ContentInfo(msgBytes);

            //  Prepare an object in which to decode and verify.
            SignedCms signedCms = new SignedCms(contentInfo, true);

            signedCms.Decode(encodedSignedCms);

            //  Catch a verification exception if you want to
            //  advise the message recipient that 
            //  security actions might be appropriate.
            try
            {
                //  Verify signature. Do not validate signer
                //  certificate for the purposes of this example.
                //  Note that in a production environment, validating
                //  the signer certificate chain will probably
                //  be necessary.
                Console.Write("Checking signature on message ... ");
                signedCms.CheckSignature(true);
                Console.WriteLine("Done.");

                //  Report the signing time for the CMS/PKCS #7 message.
                for (int i = 0; i < signedCms.SignerInfos[0].SignedAttributes.Count; i++)
                {
                    //if (signedCms.SignerInfos[0].SignedAttributes[i].
                    //Values[0].GetType().Equals(st.GetType()))
                    if (signedCms.SignerInfos[0].SignedAttributes[i].Values[0] is Pkcs9SigningTime)
                    {
                        Pkcs9SigningTime signingTime = (Pkcs9SigningTime)signedCms.SignerInfos[0].SignedAttributes[i].Values[0];
                        Console.WriteLine("Signing time:  {0}", signingTime.SigningTime);
                    }
                }
            }
            catch (System.Security.Cryptography.CryptographicException e)
            {
                Console.WriteLine("VerifyMsg caught exception:  {0}",
                    e.Message);
                Console.WriteLine("Verification of the signed PKCS #7 " +
                    "failed. The message, signatures, " +
                    " countersignatures, or authenticated attributes " +
                    " may have been modified in transit or storage. The  " +
                    " message signers or countersigners may not be who " +
                    " they claim to be. The message's authenticity or " +
                    " integrity, or both, are not guaranteed.");
                return false;
            }

            return true;
        }
    }
}

関連項目

参照

CmsSigner
ContentInfo
SignedCms
X509Certificate2
X509Certificate2Collection
X509Store

Footer image

Copyright © 2007 by Microsoft Corporation.All rights reserved.