SelfSignedCertificate.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / SelfSignedCertificate.cs / 1 / SelfSignedCertificate.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
using System;
using System.ComponentModel; 
using System.Diagnostics;
using System.Runtime.InteropServices; 
using System.Runtime.ConstrainedExecution; 
using System.Security;
using System.Security.Cryptography; 
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel.Channels;
using System.ServiceModel.Diagnostics;
using System.Text; 

namespace System.ServiceModel.Channels 
{ 
    sealed partial class SelfSignedCertificate : IDisposable
    { 
        private CertificateHandle cert = null;
        private KeyContainerHandle keyContainer = null;
        private KeyHandle key = null;
        private string keyContainerName = null; 
        private string password = null;
        private byte[] exportedBytes = null; 
        X509Certificate2 x509Cert; 

        const int CERT_STORE_PROV_MEMORY = 2; 
        const int DefaultLifeSpanInYears = 2;

        public static SelfSignedCertificate Create(string name, string password)
        { 
            return Create(name,
                        password, 
                        DateTime.UtcNow, 
                        DateTime.UtcNow.AddYears(DefaultLifeSpanInYears),
                        Guid.NewGuid().ToString()); 
        }

        public static SelfSignedCertificate Create(
                                    string name, 
                                    string password,
                                    DateTime start, 
                                    DateTime expire, 
                                    string containerName)
        { 
            SelfSignedCertificate cert = new SelfSignedCertificate(password, containerName);
            cert.GenerateKeys();
            cert.CreateCertContext(name, start, expire);
            cert.GetX509Certificate(); 
            DiagnosticUtility.DebugAssert(cert.cert != null, "CertContext could not be created");
            return cert; 
        } 

        void CreateCertContext(string name, DateTime start, DateTime expire) 
        {
            CriticalAllocHandle provInfo;
            CriticalAllocHandle algorithmId;
            provInfo = GetProviderInfo(); 
            algorithmId = GetSha1AlgorithmId();
 
            // convert the times to SystemTime structures 
            SystemTime beginTime = new SystemTime(start);
            SystemTime expireTime = new SystemTime(expire); 

            // convert the name into a X500 name
            CertificateName certName = new CertificateName(name);
 
            using (CryptoApiBlob nameBlob = certName.GetCryptoApiBlob())
            { 
                using(provInfo) 
                {
                    using(algorithmId) 
                    {
                        cert = CertCreateSelfSignCertificate(keyContainer,
                                                                    nameBlob.GetMemoryForPinning(),
                                                                    SelfSignFlags.None, 
                                                                    provInfo,
                                                                    algorithmId, 
                                                                    ref beginTime, 
                                                                    ref expireTime,
                                                                    IntPtr.Zero); 

                        if (cert.IsInvalid)
                            PeerExceptionHelper.ThrowInvalidOperation_PeerCertGenFailure(PeerExceptionHelper.GetLastException());
 
//                        if (!CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0, provInfo))
  //                          PeerExceptionHelper.ThrowInvalidOperation_PeerCertGenFailure(PeerExceptionHelper.GetLastException()); 
                        if (!CertSetCertificateContextProperty(cert, CERT_KEY_SPEC_PROP_ID, 0, key)) 
                            PeerExceptionHelper.ThrowInvalidOperation_PeerCertGenFailure(PeerExceptionHelper.GetLastException());
                    } 
                }
            }
        }
 
        public X509Certificate2 GetX509Certificate()
        { 
            if(this.x509Cert == null) 
            {
                Export(); 
                this.x509Cert = new X509Certificate2(exportedBytes, password);
            }
            return this.x509Cert;
        } 

        private void Export() 
        { 
            DiagnosticUtility.DebugAssert(this.exportedBytes == null, "calling Export twice!!");
 
            // create a temporary store to export
            using(CertificateStoreHandle store = CertOpenStore(	new IntPtr(CERT_STORE_PROV_MEMORY),
                                                                0,
                                                                IntPtr.Zero, 
                                                                0,
                                                                IntPtr.Zero)) 
            { 
                // add the certificate to the store
                StoreCertificateHandle addedCert; 
                if(!CertAddCertificateContextToStore(store,
                                                cert,
                                                AddDisposition.ReplaceExisting,
                                                out addedCert)) 
                {
                    int error = Marshal.GetLastWin32Error(); 
                    Utility.CloseInvalidOutSafeHandle(addedCert); 
                    PeerExceptionHelper.ThrowInvalidOperation_PeerCertGenFailure(new Win32Exception(error));
                } 

                using(addedCert)
                {
                    // Translate to a PFX 
                    CryptoApiBlob pfxBlob = new CryptoApiBlob();
                    CryptoApiBlob.InteropHelper blob = pfxBlob.GetMemoryForPinning(); 
                    GCHandle pfxHandle = GCHandle.Alloc(blob, GCHandleType.Pinned); 

                    try 
                    {
                        // first figure out the storage space necessary
                        bool result = PFXExportCertStoreEx(store,
                                                            pfxHandle.AddrOfPinnedObject(), 
                                                            password,
                                                            IntPtr.Zero, 
                                                            PfxExportFlags.ExportPrivateKeys | 
                                                            PfxExportFlags.ReportNoPrivateKey |
                                                            PfxExportFlags.ReportNotAbleToExportPrivateKey); 

                        if(!result)
                            PeerExceptionHelper.ThrowInvalidOperation_PeerCertGenFailure(PeerExceptionHelper.GetLastException());
 
                        int storageSize = blob.size;
                        pfxHandle.Free(); 
                        pfxBlob.AllocateBlob(storageSize); 
                        blob = pfxBlob.GetMemoryForPinning();
                        pfxHandle = GCHandle.Alloc(blob, GCHandleType.Pinned); 

                        // now do the translation
                        if(!PFXExportCertStoreEx(store,
                                                    pfxHandle.AddrOfPinnedObject(), 
                                                    password,
                                                    IntPtr.Zero, 
                                                    PfxExportFlags.ExportPrivateKeys | 
                                                    PfxExportFlags.ReportNoPrivateKey |
                                                    PfxExportFlags.ReportNotAbleToExportPrivateKey)) 
                            PeerExceptionHelper.ThrowInvalidOperation_PeerCertGenFailure(PeerExceptionHelper.GetLastException());
                        exportedBytes = pfxBlob.GetBytes();
                    }
                    finally 
                    {
                        if(pfxHandle != null) 
                            pfxHandle.Free(); 

                        if(pfxBlob != null) 
                            pfxBlob.Dispose();
                    }
                }
            } 
        }
 
        private void GenerateKeys() 
        {
            // generate the key container to put the key in 
            if(!CryptAcquireContext(out keyContainer,
                                        keyContainerName,
                                        null,
                                        ProviderType.RsaSecureChannel, 
                                        ContextFlags.NewKeySet | ContextFlags.Silent))
            { 
                int error = Marshal.GetLastWin32Error(); 
                Utility.CloseInvalidOutSafeHandle(keyContainer);
                keyContainer = null; 
                PeerExceptionHelper.ThrowInvalidOperation_PeerCertGenFailure(new Win32Exception(error));
            }

            // generate the key 
            if(!CryptGenKey(keyContainer,
                                AlgorithmType.KeyExchange, 
                                KeyFlags.Exportable2k, 
                                out key))
            { 
                int error = Marshal.GetLastWin32Error();
                Utility.CloseInvalidOutSafeHandle(key);
                key = null;
                PeerExceptionHelper.ThrowInvalidOperation_PeerCertGenFailure(new Win32Exception(error)); 
            }
        } 
 
        private void Dispose(bool disposing)
        { 
            if(disposing)
            {
                if(cert != null)
                    cert.Dispose(); 
                if(key != null)
                    key.Dispose(); 
                if(keyContainer != null) 
                    keyContainer.Dispose();
                if(keyContainerName != null) 
                {
                    CryptAcquireContext(out keyContainer,
                                        keyContainerName,
                                        null, 
                                        ProviderType.RsaSecureChannel,
                                        ContextFlags.DeleteKeySet); 
                    Utility.CloseInvalidOutSafeHandle(keyContainer); 
                }
                GC.SuppressFinalize(this); 
            }
        }

        public void Dispose() 
        {
            Dispose(true); 
        } 

        private SelfSignedCertificate(string password, string containerName) 
        {
            this.password = password;
            this.keyContainerName = containerName;
        } 

    } 
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK