Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet exemple crée un message CMS/PKCS #7 signé à l'aide de System.Security.Cryptography.Pkcs. Le message est signé par un seul signataire. Il comprend un horodatage comme attribut authentifié, ce qui signifie que le contenu du message et l'horodatage sont signés. La signature du message est ensuite vérifiée afin de s'assurer que le contenu du message et l'horodatage sont authentiques.
Exemple
Cet exemple illustre également l'utilisation d'un message CMS/PKCS #7 détaché. Le contenu du message n'est donc pas stocké dans le message CMS/PKCS #7. C'est pourquoi il doit être transmis à la méthode qui vérifie le message CMS/PKCS #7.
Cet exemple utilise les classes suivantes :
L'exemple suivant nécessite que le magasin de certificats My contienne un certificat de clé publique avec le nom d'objet « SignataireMessage1 » et qu'il existe une clé privée associée.
Remarque : |
|---|
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 générer des tests de certificats. Dans un environnement de production, les certificats sont générés par une autorité de certification.
La commande Makecert suivante génère les certificats de clé publique ainsi que les clés privées nécessaires.
Makecert -n "CN=SignataireMessage2" -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;
}
}
}
Voir aussi
Référence
CmsSigner
ContentInfo
SignedCms
X509Certificate2
X509Certificate2Collection
X509Store
.gif)
Copyright ©2007 par Microsoft Corporation. Tous droits réservés.
Remarque :