コード例 #1
0
        // end: gost

        private unsafe ICertificatePal CopyWithPersistedCapiKey(CspKeyContainerInfo keyContainerInfo)
        {
            if (string.IsNullOrEmpty(keyContainerInfo.KeyContainerName))
            {
                return(null);
            }

            // Make a new pal from bytes.
            CertificatePal      pal         = (CertificatePal)FromBlob(RawData, SafePasswordHandle.InvalidHandle, X509KeyStorageFlags.PersistKeySet);
            CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();

            fixed(byte *keyName = Encoding.UTF32.GetBytes(keyContainerInfo.KeyContainerName))
            fixed(byte *provName = Encoding.UTF32.GetBytes(keyContainerInfo.ProviderName))
            {
                keyProvInfo.pwszContainerName = (char *)keyName;
                keyProvInfo.pwszProvName      = (char *)provName;
                keyProvInfo.dwFlags           = keyContainerInfo.MachineKeyStore ? CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET : 0;
                keyProvInfo.dwProvType        = keyContainerInfo.ProviderType;
                keyProvInfo.dwKeySpec         = (int)keyContainerInfo.KeyNumber;

                if (!Interop.crypt32.CertSetCertificateContextProperty(
                        pal._certContext,
                        CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID,
                        CertSetPropertyFlags.None,
                        &keyProvInfo))
                {
                    pal.Dispose();
                    throw Interop.CPError.GetHRForLastWin32Error().ToCryptographicException();
                }
            }

            return(pal);
        }
コード例 #2
0
        /// <summary>
        /// Given a certificate, this will return back the Cng private key.
        /// You will have to use this method if the PrivateKey method on X509Certificate2 returns null or throws an exception
        /// if the X509Certificate2.HasPrivateKey property returns true.
        /// This situation indicates that the key is stored using Cng and not CryptoApi.
        /// The reason this happens is that .NET -le 4.7 does not provide an interface for Cng so Win32 interop must be used instead.
        /// The default constructor for this class will instantiate an instance of CngNativeProviderProxy which uses the win32 native apis
        /// For testing, dependency injection can be used to provide a mock of CngNativeProviderProxy via ICngNativeProvider
        /// </summary>
        /// <param name="cert"></param>
        /// <returns></returns>
        public CngKey GetCngKey(X509Certificate2 cert)
        {
            ValidateCertificateArgument(cert);

            IntPtr providerHandle = IntPtr.Zero;
            IntPtr keyHandle      = IntPtr.Zero;

            try
            {
                CRYPT_KEY_PROV_INFO keyProvider = GetPrivateKeyProvider(cert);

                providerHandle = OpenKeyVault(keyProvider);

                keyHandle = OpenKey(keyProvider, providerHandle);

                uint keyNameSize = GetKeyNameBufferSize(keyHandle);

                string keyName = GetKeyName(keyHandle, keyNameSize);

                return(InitializeCngKey(keyName));
            }
            catch (Exception e)
            {
                throw e;
            }
            finally
            {
                FreeCngHandles(providerHandle, keyHandle);
            }
        }
コード例 #3
0
 private static extern SafeCertContextHandle CertCreateSelfSignCertificate(SafeNCryptKeyHandle hCryptProvOrNCryptKey,
                                                                           [In] ref CRYPTOAPI_BLOB pSubjectIssuerBlob,
                                                                           X509CertificateCreationOptions dwFlags,
                                                                           [In] ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
                                                                           [In] ref CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
                                                                           [In] ref SYSTEMTIME pStartTime,
                                                                           [In] ref SYSTEMTIME pEndTime,
                                                                           [In] ref CERT_EXTENSIONS pExtensions);
コード例 #4
0
 public static extern IntPtr CertCreateSelfSignCertificate(IntPtr hProv,
                                                           ref CERT_NAME_BLOB pSubjectIssuerBlob,
                                                           uint dwFlagsm,
                                                           ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
                                                           ref CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
                                                           ref SYSTEM_TIME pStartTime,
                                                           ref SYSTEM_TIME pEndTime,
                                                           IntPtr other);
コード例 #5
0
 internal static extern IntPtr CertCreateSelfSignCertificate(
     IntPtr providerHandle,
     [In] CryptoApiBlob subjectIssuerBlob,
     int flags,
     ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
     ref CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
     [In] SystemTime startTime,
     [In] SystemTime endTime,
     IntPtr extensions);
コード例 #6
0
        public static extern IntPtr CertCreateSelfSignCertificate(
																	IntPtr hProv,
																	ref CERT_NAME_BLOB pSubjectIssuerBlob,
																	uint dwFlagsm,
																	ref CRYPT_KEY_PROV_INFO pKeyProvInfo,
																	IntPtr pSignatureAlgorithm,
																	IntPtr pStartTime,
																	IntPtr pEndTime,
																	IntPtr other);
コード例 #7
0
ファイル: X509Native.cs プロジェクト: hookttg/opc-ua-client
 internal static extern SafeCertContextHandle CertCreateSelfSignCertificate(
     SafeCryptProvHandle providerHandle,
     [In] ref CRYPTOAPI_BLOB subjectIssuerBlob,
     uint flags,
     [In] ref CRYPT_KEY_PROV_INFO keyProviderInformation,
     [In] ref CRYPT_ALGORITHM_IDENTIFIER signatureAlgorithm,
     [In] ref SYSTEMTIME startTime,
     [In] ref SYSTEMTIME endTime,
     [In] ref CERT_EXTENSIONS extensions);
コード例 #8
0
        public unsafe X509Certificate2 GenerateCertificateAuthority(PrivateKey privateKey, X500DistinguishedName dn, HashAlgorithm signatureAlgorithm, DateTime?notBefore = null, DateTime?notAfter = null)
        {
            {
                fixed(byte *dnPtr = dn.RawData)
                {
                    var blob = new NATIVE_CRYPTOAPI_BLOB
                    {
                        cbData = (uint)dn.RawData.Length,
                        pbData = dnPtr
                    };
                    var signatureAlgorithmIdentifier = new CRYPT_ALGORITHM_IDENTIFIER
                    {
                        pszObjId = HashAlgorithmToSignatureAlgorithm(privateKey, signatureAlgorithm)
                    };

                    using (var extensions = new MarshalX509ExtensionCollection())
                    {
                        using (extensions.Freeze())
                        {
                            extensions.Add(new X509BasicConstraintsExtension(true, true, 1, true));
                            extensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.CrlSign | X509KeyUsageFlags.KeyCertSign, true));
                            extensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection {
                                new Oid(OIDs.EKU_SERVER)
                            }, false));
                            using (var publicKey = privateKey.ToPublicKey())
                            {
                                using (var sha1 = new SHA1CryptoServiceProvider())
                                {
                                    var pubKeyHash = sha1.ComputeHash(publicKey.Key);
                                    extensions.Add(new X509SubjectKeyIdentifierExtension(pubKeyHash, false));
                                    extensions.Add(new X509AuthorityKeyIdentifierExtension(pubKeyHash, null));
                                }
                            }
                        }
                        var certExtensions = extensions.Extensions;
                        var keyProvInfo    = new CRYPT_KEY_PROV_INFO
                        {
                            cProvParam        = 0,
                            dwKeySpec         = privateKey.KeySpec,
                            dwProvType        = privateKey.Handle.IsNCryptKey ? ProviderType.CNG : ProviderType.PROV_RSA_AES,
                            pwszProvName      = privateKey.ProviderName,
                            dwFlags           = 0,
                            pwszContainerName = privateKey.Name
                        };
                        var beginning   = new SYSTEMTIME(notBefore ?? DateTime.UtcNow.AddHours(-1));
                        var expiration  = new SYSTEMTIME(notAfter ?? DateTime.UtcNow.AddHours(-1).AddYears(30));
                        var certContext = Crypt32.CertCreateSelfSignCertificate(privateKey.Handle, ref blob, SelfSignFlags.NONE, ref keyProvInfo, ref signatureAlgorithmIdentifier, beginning, expiration, ref certExtensions);
                        if (certContext == IntPtr.Zero)
                        {
                            throw new Win32Exception(Marshal.GetLastWin32Error());
                        }
                        return(new X509Certificate2(certContext));
                    }
                }
            }
        }
コード例 #9
0
ファイル: CryptoApiMethods.cs プロジェクト: wflk/canape
 public static extern IntPtr CertCreateSelfSignCertificate(
     SafeCryptProviderHandle hCryptProvOrNCryptKey,
     [Out] CRYPTOAPI_BLOB pSubjectIssuerBlob,
     CertCreationFlags dwFlags,
     CRYPT_KEY_PROV_INFO pKeyProvInfo,
     CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
     SYSTEMTIME pStartTime,
     SYSTEMTIME pEndTime,
     CERT_EXTENSIONS pExtension
     );
        CriticalAllocHandle GetProviderInfo()
        {
            CRYPT_KEY_PROV_INFO provInfo = new CRYPT_KEY_PROV_INFO();

            provInfo.container    = this.keyContainerName;
            provInfo.providerType = (int)ProviderType.RsaSecureChannel;
            provInfo.paramsCount  = 0;
            provInfo.keySpec      = (int)AlgorithmType.KeyExchange;
            return(CriticalAllocHandleBlob.FromBlob <CRYPT_KEY_PROV_INFO>(provInfo));
        }
コード例 #11
0
        private CriticalAllocHandle GetProviderInfo()
        {
            CRYPT_KEY_PROV_INFO id = new CRYPT_KEY_PROV_INFO {
                container    = this.keyContainerName,
                providerType = 12,
                paramsCount  = 0,
                keySpec      = 1
            };

            return(CriticalAllocHandleBlob.FromBlob <CRYPT_KEY_PROV_INFO>(id));
        }
コード例 #12
0
        /// <summary>
        /// Given a certificate, this will return information about how the private key is stored.
        /// If the certificate doesn't have a private key, an exception will be thrown.
        /// </summary>
        /// <param name="cert"></param>
        /// <returns></returns>
        public PrivateKeyStorageMetadata GetPrivateKeyStorageMetadata(X509Certificate2 cert)
        {
            ValidateCertificateArgument(cert);

            CRYPT_KEY_PROV_INFO provider = this.GetPrivateKeyProvider(cert);

            return(new PrivateKeyStorageMetadata()
            {
                ContainerName = provider.pwszContainerName,
                ProviderName = provider.pwszProvName,
                ProviderType = provider.dwProvType
            });
        }
コード例 #13
0
        internal static bool SetCertificateKeyProvInfo(
            SafeCertContextHandle certificateContext,
            ref CRYPT_KEY_PROV_INFO provInfo)
        {
            Debug.Assert(certificateContext != null, "certificateContext != null");
            Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid,
                         "!certificateContext.IsClosed && !certificateContext.IsInvalid");

            return(UnsafeNativeMethods.CertSetCertificateContextProperty(
                       certificateContext,
                       CertificateProperty.KeyProviderInfo,
                       CertSetPropertyFlags.None,
                       ref provInfo));
        }
コード例 #14
0
        /// <summary>
        /// Opens a private key and returns a handle to the opened key.
        /// </summary>
        /// <param name="keyProv"></param>
        /// <param name="providerHandle"></param>
        /// <returns></returns>
        private IntPtr OpenKey(CRYPT_KEY_PROV_INFO keyProv, IntPtr providerHandle)
        {
            IntPtr keyHandle = IntPtr.Zero;

            int result = cngProvider.NCryptOpenKey(providerHandle, out keyHandle, keyProv.pwszContainerName, 0, NCRYPT_MACHINE_KEY_FLAG);

            switch (result)
            {
            case SUCCESS:
                return(keyHandle);

            default:
                throw new Exception(string.Format("Unable to open key - {0}", result));
            }
        }
コード例 #15
0
        /// <summary>
        /// Opens the specified key provider and returns back a handle to the opened provider
        /// </summary>
        /// <param name="keyProvider"></param>
        /// <returns></returns>
        private IntPtr OpenKeyVault(CRYPT_KEY_PROV_INFO keyProvider)
        {
            int    result         = int.MaxValue;
            IntPtr providerHandle = IntPtr.Zero;

            result = cngProvider.NCryptOpenStorageProvider(ref providerHandle, keyProvider.pwszProvName, 0);

            switch (result)
            {
            case SUCCESS:
                return(providerHandle);

            default:
                throw new Exception(string.Format("Unable to open provider - {0}", result));
            }
        }
コード例 #16
0
        private unsafe ICertificatePal CopyWithPersistedCngKey(CngKey cngKey)
        {
            if (string.IsNullOrEmpty(cngKey.KeyName))
            {
                return(null);
            }

            // Make a new pal from bytes.
            CertificatePal pal = (CertificatePal)FromBlob(RawData, SafePasswordHandle.InvalidHandle, X509KeyStorageFlags.PersistKeySet);

            CngProvider provider   = cngKey.Provider;
            string      keyName    = cngKey.KeyName;
            bool        machineKey = cngKey.IsMachineKey;

            // CAPI RSA_SIGN keys won't open correctly under CNG without the key number being specified, so
            // check to see if we can figure out what key number it needs to re-open.
            int keySpec = GuessKeySpec(provider, keyName, machineKey, cngKey.AlgorithmGroup);

            CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();

            fixed(char *keyNamePtr = cngKey.KeyName)
            fixed(char *provNamePtr = cngKey.Provider.Provider)
            {
                keyProvInfo.pwszContainerName = keyNamePtr;
                keyProvInfo.pwszProvName      = provNamePtr;
                keyProvInfo.dwFlags           = machineKey ? CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET : 0;
                keyProvInfo.dwKeySpec         = keySpec;

                if (!Interop.crypt32.CertSetCertificateContextProperty(
                        pal._certContext,
                        CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID,
                        CertSetPropertyFlags.None,
                        &keyProvInfo))
                {
                    pal.Dispose();
                    throw Marshal.GetLastWin32Error().ToCryptographicException();
                }
            }

            return(pal);
        }
コード例 #17
0
        public static void RegisterKeyContainer()
        {
            uint[] keySpecs       = { AT_SIGNATURE, AT_KEYEXCHANGE };
            string providerName   = "Microsoft Base Smart Card Crypto Provider";
            IntPtr hCryptProvider = new IntPtr();

            if (!CryptAcquireContext(ref hCryptProvider, null, providerName, PROV_RSA_FULL, (uint)0))
            {
                throw new RegisterException(new RegisterExceptionEventArgs(RegisterException.ACQUIRE_CONTEXT));
            }

            uint          bufferSize    = 1024;
            StringBuilder containerName = new StringBuilder((int)bufferSize);

            // enumerate all containers
            while (CryptGetProvParam(hCryptProvider, PP_ENUMCONTAINERS, containerName, ref bufferSize, CRYPT_FIRST))
            {
                Debug.WriteLine("Container Name: " + containerName.ToString());
                if (!CryptAcquireContext(ref hCryptProvider, containerName.ToString(), providerName, PROV_RSA_FULL, 0))
                {
                    continue;
                }

                // loop over the key specs
                foreach (uint keySpec in keySpecs)
                {
                    IntPtr hUserKey = new IntPtr();
                    uint   certLen  = 0;

                    if (!CryptGetUserKey(hCryptProvider, keySpec, ref hUserKey))
                    {
                        continue;
                    }

                    if (!CryptGetKeyParam(hUserKey, KP_CERTIFICATE, 0, ref certLen, 0)) // get certificate length
                    {
                        throw new Exception("Could not retrieve certificate length.");
                    }

                    Debug.WriteLine("got certificate length");

                    byte[] rawCert = new byte[certLen];
                    if (!CryptGetKeyParam(hUserKey, KP_CERTIFICATE, rawCert, ref certLen, 0)) // get certificate
                    {
                        throw new Exception("Could not retrieve certificate.");
                    }

                    Debug.WriteLine("got certificate");
                    IntPtr hCertContext = new IntPtr();
                    hCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, rawCert, certLen);

                    CRYPT_KEY_PROV_INFO ProvInfo = new CRYPT_KEY_PROV_INFO();
                    ProvInfo.ContainerName = containerName.ToString();
                    ProvInfo.ProvName      = providerName;
                    ProvInfo.ProvType      = PROV_RSA_FULL;
                    ProvInfo.Flags         = 0;
                    ProvInfo.KeySpec       = AT_SIGNATURE;
                    ProvInfo.ProvParam     = 0;
                    ProvInfo.rgProvParam   = new IntPtr();

                    X509Certificate2 c    = new X509Certificate2(rawCert);
                    string           name = c.SubjectName.Name;

                    if (!CertSetCertificateContextProperty(hCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, ref ProvInfo))
                    {
                        throw new Exception("Could set certificate's context.");
                    }

                    Debug.WriteLine("Context set!");

                    IntPtr hCertStore = CertOpenStoreStringPara(CERT_STORE_PROV_SYSTEM_W, 0, new IntPtr(),
                                                                CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, "My");

                    if (!CertAddCertificateContextToStore(hCertStore, hCertContext, CERT_STORE_ADD_REPLACE_EXISTING, new IntPtr()))
                    {
                        throw new Exception("Could not add certificate to store.");
                    }
                }
            }
        }
コード例 #18
0
        /// <summary>
        /// Creates and returns a self-signed X509 certificate.
        /// </summary>
        /// <param name="key">The key of the certificate.</param>
        /// <param name="issuerName">The encoded common name of the issuer.</param>
        /// <param name="settings">The settings of the X509 certificate.</param>
        /// <returns>An <see cref="X509Certificate"/> instance.</returns>
        /// <exception cref="CryptographicException">An error occurs while creating the self-signed certificate.</exception>
        public static X509Certificate Create(RSACryptoServiceProvider key, string issuerName, CertificateSettings settings)
        {
            if (settings == null)
                settings = new CertificateSettings();

            CspKeyContainerInfo container = key.CspKeyContainerInfo;
            IntPtr certHandle = IntPtr.Zero;
            byte[] issuerBlob = null;
            uint pcbEncoded = 0;
            if (CertStrToName(X509_ASN_ENCODING, issuerName, CERT_X500_NAME_STR, IntPtr.Zero, null, ref pcbEncoded, IntPtr.Zero)) {
                issuerBlob = new byte[pcbEncoded];
                CertStrToName(X509_ASN_ENCODING, issuerName, CERT_X500_NAME_STR, IntPtr.Zero, issuerBlob, ref pcbEncoded, IntPtr.Zero);
            } else {
                throw new CryptographicException("Cannot encode the issuer name! Please check whether the string is in a valid format.");
            }

            List<IntPtr> extensionList = new List<IntPtr>();
            CERT_NAME_BLOB subject = new CERT_NAME_BLOB();
            try {
                subject.pbData = Marshal.AllocHGlobal(issuerBlob.Length);
                Marshal.Copy(issuerBlob, 0, subject.pbData, issuerBlob.Length);
                subject.cbData = issuerBlob.Length;

                SYSTEMTIME startDate = ConvertDateTime(settings.StartDate);
                SYSTEMTIME endDate = ConvertDateTime(settings.EndDate);

                CRYPT_KEY_PROV_INFO providerInfo = new CRYPT_KEY_PROV_INFO();
                providerInfo.pwszContainerName = container.KeyContainerName;
                providerInfo.pwszProvName = container.ProviderName;
                providerInfo.dwProvType = container.ProviderType;
                providerInfo.dwFlags = (int)0;
                providerInfo.cProvParam = 0;
                providerInfo.rgProvParam = IntPtr.Zero;
                providerInfo.dwKeySpec = (int)container.KeyNumber;

                // convert the list of extensions to an unmanaged structure
                // the .NET marshallers don't handle recursive arrays too well,
                // so we do it manually :-/
                extensionList = ConvertExtensions(settings.Extensions);

                certHandle = CertCreateSelfSignCertificate(IntPtr.Zero, ref subject, settings.Flags, ref providerInfo, IntPtr.Zero, ref startDate, ref endDate, extensionList[0]);
                if (certHandle == IntPtr.Zero) {
                    throw new CryptographicException("Couldn't create unsigned certificate");
                }

                return new X509Certificate2(certHandle);
            } finally {
                if (subject.pbData != IntPtr.Zero)
                    Marshal.FreeHGlobal(subject.pbData);
                if (extensionList != null && extensionList.Count > 0) {
                    foreach (IntPtr ptr in extensionList) {
                        if (ptr != IntPtr.Zero)
                            Marshal.FreeHGlobal(ptr);
                    }
                }
            }
        }
コード例 #19
0
        /// <summary>
        /// Create a self-signed x509 certificate.
        /// </summary>
        /// <param name="subjectName">The distinguished name.</param>
        /// <param name="notBefore">The start time.</param>
        /// <param name="notAfter">the end time.</param>
        /// <param name="extensions">the extensions.</param>
        /// <returns>A byte array containing the certificate and private key encoded as PFX.</returns>
        public static byte[] CreateSelfSignCertificatePfx(
            string subjectName,
            DateTime notBefore,
            DateTime notAfter,
            params X509Extension[] extensions)
        {
            if (subjectName == null)
            {
                subjectName = string.Empty;
            }

            byte[] pfxData;

            SYSTEMTIME startSystemTime = ToSystemTime(notBefore);
            SYSTEMTIME endSystemTime   = ToSystemTime(notAfter);
            string     containerName   = $"Created by Workstation. {Guid.NewGuid().ToString()}";

            GCHandle gcHandle         = default(GCHandle);
            var      providerContext  = SafeCryptProvHandle.InvalidHandle;
            var      cryptKey         = SafeCryptKeyHandle.InvalidHandle;
            var      certContext      = SafeCertContextHandle.InvalidHandle;
            var      certStore        = SafeCertStoreHandle.InvalidHandle;
            var      storeCertContext = SafeCertContextHandle.InvalidHandle;

            try
            {
                Check(NativeMethods.CryptAcquireContextW(
                          out providerContext,
                          containerName,
                          null,
                          PROV_RSA_FULL,
                          CRYPT_NEWKEYSET));

                Check(NativeMethods.CryptGenKey(
                          providerContext,
                          AT_KEYEXCHANGE,
                          CRYPT_EXPORTABLE | (2048 << 16), // 2048bit
                          out cryptKey));

                IntPtr pbEncoded = IntPtr.Zero;
                int    cbEncoded = 0;

                Check(NativeMethods.CertStrToNameW(
                          X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                          subjectName,
                          CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
                          IntPtr.Zero,
                          IntPtr.Zero,
                          ref cbEncoded,
                          IntPtr.Zero));

                pbEncoded = Marshal.AllocHGlobal(cbEncoded);

                Check(NativeMethods.CertStrToNameW(
                          X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                          subjectName,
                          CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
                          IntPtr.Zero,
                          pbEncoded,
                          ref cbEncoded,
                          IntPtr.Zero));

                var nameBlob = new CRYPTOAPI_BLOB
                {
                    cbData = (uint)cbEncoded,
                    pbData = pbEncoded
                };

                var kpi = new CRYPT_KEY_PROV_INFO
                {
                    pwszContainerName = containerName,
                    dwProvType        = PROV_RSA_FULL,
                    dwKeySpec         = AT_KEYEXCHANGE
                };

                var signatureAlgorithm = new CRYPT_ALGORITHM_IDENTIFIER
                {
                    pszObjId   = OID_RSA_SHA256RSA,
                    Parameters = default(CRYPTOAPI_BLOB)
                };

                IntPtr pInfo     = IntPtr.Zero;
                int    cbInfo    = 0;
                byte[] keyHash   = null;
                int    cbKeyHash = 0;

                try
                {
                    Check(NativeMethods.CryptExportPublicKeyInfoEx(
                              providerContext,
                              AT_KEYEXCHANGE,
                              X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                              OID_RSA_RSA,
                              0,
                              IntPtr.Zero,
                              IntPtr.Zero,
                              ref cbInfo));

                    pInfo = Marshal.AllocHGlobal(cbInfo);

                    Check(NativeMethods.CryptExportPublicKeyInfoEx(
                              providerContext,
                              AT_KEYEXCHANGE,
                              X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                              OID_RSA_RSA,
                              0,
                              IntPtr.Zero,
                              pInfo,
                              ref cbInfo));

                    Check(NativeMethods.CryptHashPublicKeyInfo(
                              providerContext,
                              CALG_SHA1,
                              0,
                              X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                              pInfo,
                              null,
                              ref cbKeyHash));

                    keyHash = new byte[cbKeyHash];

                    Check(NativeMethods.CryptHashPublicKeyInfo(
                              providerContext,
                              CALG_SHA1,
                              0,
                              X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                              pInfo,
                              keyHash,
                              ref cbKeyHash));
                }
                finally
                {
                    if (pInfo != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(pInfo);
                    }
                }

                var safeExtensions = new List <SafeX509Extension>();
                var blob           = IntPtr.Zero;
                try
                {
                    foreach (var item in extensions)
                    {
                        safeExtensions.Add(new SafeX509Extension(item));
                    }

                    // adding SubjectKeyIdentifier TODO: AuthKeyIdentifier?
                    safeExtensions.Add(new SafeX509Extension(new X509SubjectKeyIdentifierExtension(keyHash, false)));

                    var structSize = Marshal.SizeOf <CERT_EXTENSION>();
                    blob = Marshal.AllocHGlobal(structSize * safeExtensions.Count);
                    for (int index = 0, offset = 0; index < safeExtensions.Count; index++, offset += structSize)
                    {
                        var marshalX509Extension = safeExtensions[index];
                        Marshal.StructureToPtr(marshalX509Extension.Value, blob + offset, false);
                    }

                    var certExtensions = new CERT_EXTENSIONS {
                        cExtension = (uint)safeExtensions.Count, rgExtension = blob
                    };

                    certContext = NativeMethods.CertCreateSelfSignCertificate(
                        providerContext,
                        ref nameBlob,
                        0,
                        ref kpi,
                        ref signatureAlgorithm,
                        ref startSystemTime,
                        ref endSystemTime,
                        ref certExtensions);
                    Check(!certContext.IsInvalid);
                }
                finally
                {
                    foreach (var safeExtension in safeExtensions)
                    {
                        safeExtension.Dispose();
                    }

                    safeExtensions.Clear();
                    Marshal.FreeHGlobal(blob);
                    Marshal.FreeHGlobal(pbEncoded);
                }

                certStore = NativeMethods.CertOpenStore(
                    sz_CERT_STORE_PROV_MEMORY,
                    0,
                    IntPtr.Zero,
                    CERT_STORE_CREATE_NEW_FLAG,
                    IntPtr.Zero);
                Check(!certStore.IsInvalid);

                Check(NativeMethods.CertAddCertificateContextToStore(
                          certStore,
                          certContext,
                          CERT_STORE_ADD_NEW,
                          out storeCertContext));

                NativeMethods.CertSetCertificateContextProperty(
                    storeCertContext,
                    CERT_KEY_PROV_INFO_PROP_ID,
                    0,
                    ref kpi);

                CRYPTOAPI_BLOB pfxBlob = default(CRYPTOAPI_BLOB);
                Check(NativeMethods.PFXExportCertStoreEx(
                          certStore,
                          ref pfxBlob,
                          IntPtr.Zero,
                          IntPtr.Zero,
                          EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY));

                pfxData        = new byte[pfxBlob.cbData];
                gcHandle       = GCHandle.Alloc(pfxData, GCHandleType.Pinned);
                pfxBlob.pbData = gcHandle.AddrOfPinnedObject();

                Check(NativeMethods.PFXExportCertStoreEx(
                          certStore,
                          ref pfxBlob,
                          IntPtr.Zero,
                          IntPtr.Zero,
                          EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY));

                gcHandle.Free();
            }
            finally
            {
                if (gcHandle.IsAllocated)
                {
                    gcHandle.Free();
                }

                if (!certContext.IsInvalid)
                {
                    certContext.Dispose();
                }

                if (!storeCertContext.IsInvalid)
                {
                    storeCertContext.Dispose();
                }

                if (!certStore.IsInvalid)
                {
                    certStore.Dispose();
                }

                if (!cryptKey.IsInvalid)
                {
                    cryptKey.Dispose();
                }

                if (!providerContext.IsInvalid)
                {
                    providerContext.Dispose();
                    providerContext = SafeCryptProvHandle.InvalidHandle;

                    // Delete generated keyset. Does not return a providerContext
                    NativeMethods.CryptAcquireContextW(
                        out providerContext,
                        containerName,
                        null,
                        PROV_RSA_FULL,
                        CRYPT_DELETEKEYSET);
                }
            }

            return(pfxData);
        }
コード例 #20
0
 public static extern bool CertSetCertificateContextProperty(IntPtr pCertContext, uint dwPropId, uint dwFlags, ref CRYPT_KEY_PROV_INFO pvData);
コード例 #21
0
        public unsafe X509Certificate2 GenerateCertificate(X509Certificate2 issuingCertificate, PrivateKey privateKey, X500DistinguishedName dn, string[] dnsNames, IPAddress[] ipAddresses = null, HashAlgorithm?signatureAlgorithm = null, DateTime?notBefore = null, DateTime?notAfter = null)
        {
            if (!issuingCertificate.HasPrivateKey)
            {
                throw new ArgumentException("Issuing certificate must have a private key.", nameof(issuingCertificate));
            }
            IntPtr basicEncodedDataPtr = IntPtr.Zero, certExtensionPtr = IntPtr.Zero;
            var    serialNumber = new byte[16];
            var    rng = RandomNumberGenerator.Create();

            rng.GetNonZeroBytes(serialNumber);
            serialNumber[15] &= 0x7F;
            fixed(byte *dnPtr = dn.RawData, issuerDnPtr = issuingCertificate.SubjectName.RawData, serialNumberPtr = serialNumber)
            {
                try
                {
                    var blob = new NATIVE_CRYPTOAPI_BLOB
                    {
                        cbData = (uint)dn.RawData.Length,
                        pbData = dnPtr
                    };
                    var signingSignatureAlgorithmIdentifier = new CRYPT_ALGORITHM_IDENTIFIER
                    {
                        pszObjId = issuingCertificate.SignatureAlgorithm.Value
                    };
                    using (var signingKey = ExtractKey(issuingCertificate))
                    {
                        var signingAlgorithmIdentifier = new CRYPT_ALGORITHM_IDENTIFIER
                        {
                            pszObjId = signatureAlgorithm != null?HashAlgorithmToSignatureAlgorithm(signingKey, signatureAlgorithm.Value) : issuingCertificate.SignatureAlgorithm.Value
                        };
                        using (PublicKeyInfo publicKey = privateKey.ToPublicKey(), signingPublicKey = signingKey.ToPublicKey())
                        {
                            using (var extensions = new MarshalX509ExtensionCollection())
                            {
                                using (extensions.Freeze())
                                {
                                    var usage = X509KeyUsageFlags.DigitalSignature;
                                    if (privateKey.AlgorithmGroup == AlgorithmGroup.RSA)
                                    {
                                        //Key encipherment is not valid for DSA/ECDSA
                                        usage |= X509KeyUsageFlags.KeyEncipherment;
                                    }
                                    extensions.Add(new X509BasicConstraintsExtension(false, false, 0, true));
                                    extensions.Add(new X509KeyUsageExtension(usage, true));
                                    extensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection {
                                        new Oid(OIDs.EKU_SERVER)
                                    }, false));
                                    extensions.Add(new X509SubjectAlternativeNameExtension(DnsAltNamesFromArray(dnsNames, ipAddresses ?? new IPAddress[0]), false));
                                    using (var sha1 = new SHA1CryptoServiceProvider())
                                    {
                                        var issuingKeyId = sha1.ComputeHash(signingPublicKey.Key);
                                        extensions.Add(new X509SubjectKeyIdentifierExtension(sha1.ComputeHash(publicKey.Key), false));
                                        extensions.Add(new X509AuthorityKeyIdentifierExtension(issuingKeyId, null));
                                    }
                                }
                                var certInfo = new CERT_INFO();
                                certInfo.Subject      = blob;
                                certInfo.SerialNumber = new NATIVE_CRYPTOAPI_BLOB {
                                    cbData = (uint)serialNumber.Length, pbData = serialNumberPtr
                                };
                                certInfo.SubjectPublicKeyInfo = publicKey.PublicKey;
                                certInfo.dwVersion            = CertificateVersion.CERT_V3;
                                certInfo.Issuer = new NATIVE_CRYPTOAPI_BLOB {
                                    cbData = (uint)issuingCertificate.SubjectName.RawData.Length, pbData = issuerDnPtr
                                };
                                certInfo.SignatureAlgorithm = signingAlgorithmIdentifier;
                                certInfo.NotAfter           = FileTimeHelper.ToFileTimeStructureUtc(notAfter ?? DateTime.Now.AddHours(-1).AddYears(5));
                                certInfo.NotBefore          = FileTimeHelper.ToFileTimeStructureUtc(notBefore ?? DateTime.Now.AddHours(-1));
                                certInfo.cExtension         = extensions.Extensions.cExtension;
                                certInfo.rgExtension        = extensions.Extensions.rgExtension;
                                var size           = 0u;
                                var CERT_INFO_TYPE = (IntPtr)2;
                                if (!Crypt32.CryptSignAndEncodeCertificate(signingKey.Handle, signingKey.KeySpec, EncodingType.X509_ASN_ENCODING, CERT_INFO_TYPE, ref certInfo, ref signingSignatureAlgorithmIdentifier, IntPtr.Zero, IntPtr.Zero, ref size))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                var buffer = Marshal.AllocHGlobal((int)size);
                                if (!Crypt32.CryptSignAndEncodeCertificate(signingKey.Handle, signingKey.KeySpec, EncodingType.X509_ASN_ENCODING, CERT_INFO_TYPE, ref certInfo, ref signingSignatureAlgorithmIdentifier, IntPtr.Zero, buffer, ref size))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                const int CERT_KEY_PROV_INFO_PROP_ID = 2;
                                var       certificate = new X509Certificate2(SerializeCertificate(buffer, size));
                                var       keyProvInfo = new CRYPT_KEY_PROV_INFO
                                {
                                    cProvParam        = 0,
                                    dwKeySpec         = privateKey.KeySpec,
                                    dwProvType        = privateKey.Handle.IsNCryptKey ? ProviderType.CNG : ProviderType.PROV_RSA_AES,
                                    pwszProvName      = privateKey.ProviderName,
                                    dwFlags           = 0,
                                    pwszContainerName = privateKey.Name
                                };
                                if (!Crypt32.CertSetCertificateContextProperty(certificate.Handle, CERT_KEY_PROV_INFO_PROP_ID, 0u, ref keyProvInfo))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                return(new X509Certificate2(certificate));
                            }
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(basicEncodedDataPtr);
                    Marshal.FreeHGlobal(certExtensionPtr);
                }
            }
        }
コード例 #22
0
 CriticalAllocHandle GetProviderInfo()
 {
     CRYPT_KEY_PROV_INFO provInfo = new CRYPT_KEY_PROV_INFO();
     provInfo.container = this.keyContainerName;
     provInfo.providerType = (int)ProviderType.RsaSecureChannel;
     provInfo.paramsCount = 0;
     provInfo.keySpec = (int)AlgorithmType.KeyExchange;
     return CriticalAllocHandleBlob.FromBlob<CRYPT_KEY_PROV_INFO>(provInfo);
 }
コード例 #23
0
ファイル: CertHelper.cs プロジェクト: suwatch/AzureCLI
        private static SafeCertContextHandle CreateSelfSignedCertificate(CngKey key,
                                                                         bool takeOwnershipOfKey,
                                                                         byte[] subjectName,
                                                                         X509CertificateCreationOptions creationOptions,
                                                                         string signatureAlgorithmOid,
                                                                         DateTime startTime,
                                                                         DateTime endTime)
        {
            // Create an algorithm identifier structure for the signature algorithm
            CRYPT_ALGORITHM_IDENTIFIER nativeSignatureAlgorithm = new CRYPT_ALGORITHM_IDENTIFIER();
            nativeSignatureAlgorithm.pszObjId = signatureAlgorithmOid;
            nativeSignatureAlgorithm.Parameters = new CRYPTOAPI_BLOB();
            nativeSignatureAlgorithm.Parameters.cbData = 0;
            nativeSignatureAlgorithm.Parameters.pbData = IntPtr.Zero;

            // Convert the begin and expire dates to system time structures
            SYSTEMTIME nativeStartTime = new SYSTEMTIME(startTime);
            SYSTEMTIME nativeEndTime = new SYSTEMTIME(endTime);

            CERT_EXTENSIONS nativeExtensions = new CERT_EXTENSIONS();
            nativeExtensions.cExtension = 0;

            // Setup a CRYPT_KEY_PROV_INFO for the key
            CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();
            keyProvInfo.pwszContainerName = key.UniqueName;
            keyProvInfo.pwszProvName = key.Provider.Provider;
            keyProvInfo.dwProvType = 0;     // NCRYPT
            keyProvInfo.dwFlags = 0;
            keyProvInfo.cProvParam = 0;
            keyProvInfo.rgProvParam = IntPtr.Zero;
            keyProvInfo.dwKeySpec = 0;

            //
            // Now that all of the needed data structures are setup, we can create the certificate
            //

            SafeCertContextHandle selfSignedCertHandle = null;
            unsafe
            {
                fixed (byte* pSubjectName = &subjectName[0])
                {
                    // Create a CRYPTOAPI_BLOB for the subject of the cert
                    CRYPTOAPI_BLOB nativeSubjectName = new CRYPTOAPI_BLOB();
                    nativeSubjectName.cbData = subjectName.Length;
                    nativeSubjectName.pbData = new IntPtr(pSubjectName);

                    // Now that we've converted all the inputs to native data structures, we can generate
                    // the self signed certificate for the input key.
                    using (SafeNCryptKeyHandle keyHandle = key.Handle)
                    {
                        selfSignedCertHandle = CertCreateSelfSignCertificate(keyHandle,
                                                                             ref nativeSubjectName,
                                                                             creationOptions,
                                                                             ref keyProvInfo,
                                                                             ref nativeSignatureAlgorithm,
                                                                             ref nativeStartTime,
                                                                             ref nativeEndTime,
                                                                             ref nativeExtensions);
                        if (selfSignedCertHandle.IsInvalid)
                        {
                            throw new CryptographicException(Marshal.GetLastWin32Error());
                        }
                    }
                }
            }

            Debug.Assert(selfSignedCertHandle != null, "selfSignedCertHandle != null");

            // Attach a key context to the certificate which will allow Windows to find the private key
            // associated with the certificate if the NCRYPT_KEY_HANDLE is ephemeral.
            // is done.
            using (SafeNCryptKeyHandle keyHandle = key.Handle)
            {
                CERT_KEY_CONTEXT keyContext = new CERT_KEY_CONTEXT();
                keyContext.cbSize = Marshal.SizeOf(typeof(CERT_KEY_CONTEXT));
                keyContext.hNCryptKey = keyHandle.DangerousGetHandle();
                keyContext.dwKeySpec = KeySpec.NCryptKey;

                bool attachedProperty = false;
                int setContextError = 0;

                // Run in a CER to ensure accurate tracking of the transfer of handle ownership
                RuntimeHelpers.PrepareConstrainedRegions();
                try { }
                finally
                {
                    CertificatePropertySetFlags flags = CertificatePropertySetFlags.None;
                    if (!takeOwnershipOfKey)
                    {
                        // If the certificate is not taking ownership of the key handle, then it should
                        // not release the handle when the context is released.
                        flags |= CertificatePropertySetFlags.NoCryptRelease;
                    }

                    attachedProperty = CertSetCertificateContextProperty(selfSignedCertHandle,
                                                                         CertificateProperty.KeyContext,
                                                                         flags,
                                                                         ref keyContext);
                    setContextError = Marshal.GetLastWin32Error();

                    // If we succesfully transferred ownership of the key to the certificate,
                    // then we need to ensure that we no longer release its handle.
                    if (attachedProperty && takeOwnershipOfKey)
                    {
                        keyHandle.SetHandleAsInvalid();
                    }
                }

                if (!attachedProperty)
                {
                    throw new CryptographicException(setContextError);
                }
            }

            return selfSignedCertHandle;
        }
コード例 #24
0
        /// <summary>
        /// Set the private key object. The additional "publicKey" argument is used to validate that the private key corresponds to the existing publicKey.
        /// </summary>
        public void SetPrivateKey(AsymmetricAlgorithm privateKey, AsymmetricAlgorithm publicKey)
        {
            if (privateKey == null)
            {
                unsafe
                {
                    if (!Interop.crypt32.CertSetCertificateContextProperty(_certContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, CertSetPropertyFlags.None, (CRYPT_KEY_PROV_INFO *)null))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }
                }
            }
            else
            {
                // we do not support keys in non-CAPI storage for now.
                ICspAsymmetricAlgorithm asymmetricAlgorithm = privateKey as ICspAsymmetricAlgorithm;
                if (asymmetricAlgorithm == null)
                {
                    throw new NotSupportedException(SR.NotSupported_InvalidKeyImpl);
                }
                if (asymmetricAlgorithm.CspKeyContainerInfo == null)
                {
                    throw new ArgumentException("CspKeyContainerInfo");
                }

                // check that the public key in the certificate corresponds to the private key passed in.
                //
                // note that it should be legal to set a key which matches in every aspect but the usage
                // i.e. to use a CALG_RSA_KEYX private key to match a CALG_RSA_SIGN public key. A
                // PUBLICKEYBLOB is defined as:
                //
                //  BLOBHEADER publickeystruc
                //  RSAPUBKEY rsapubkey
                //  BYTE modulus[rsapubkey.bitlen/8]
                //
                // To allow keys which differ by key usage only, we skip over the BLOBHEADER of the key,
                // and start comparing bytes at the RSAPUBKEY structure.
                unsafe
                {
                    // This cast is safe because via our contract with our caller, "publicKey" is the Key property of a PublicKey object that this Pal class manufactured in the first place.
                    // Since we manufactured the PublicKey, we know the real types of the object.
                    ICspAsymmetricAlgorithm cspPublicKey = (ICspAsymmetricAlgorithm)publicKey;
                    byte[] array1 = cspPublicKey.ExportCspBlob(false);
                    byte[] array2 = asymmetricAlgorithm.ExportCspBlob(false);
                    if (array1 == null || array2 == null || array1.Length != array2.Length || array1.Length <= sizeof(BLOBHEADER))
                    {
                        throw new CryptographicUnexpectedOperationException(SR.Cryptography_X509_KeyMismatch);
                    }
                    for (int index = sizeof(BLOBHEADER); index < array1.Length; index++)
                    {
                        if (array1[index] != array2[index])
                        {
                            throw new CryptographicUnexpectedOperationException(SR.Cryptography_X509_KeyMismatch);
                        }
                    }
                }

                unsafe
                {
                    CspKeyContainerInfo keyContainerInfo = asymmetricAlgorithm.CspKeyContainerInfo;
                    fixed(char *pKeyContainerName = keyContainerInfo.KeyContainerName, pProviderName = keyContainerInfo.ProviderName)
                    {
                        CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO()
                        {
                            pwszContainerName = pKeyContainerName,
                            pwszProvName      = pProviderName,
                            dwProvType        = keyContainerInfo.ProviderType,
                            dwFlags           = keyContainerInfo.MachineKeyStore ? CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET : CryptAcquireContextFlags.None,
                            cProvParam        = 0,
                            rgProvParam       = IntPtr.Zero,
                            dwKeySpec         = (int)(keyContainerInfo.KeyNumber),
                        };

                        if (!Interop.crypt32.CertSetCertificateContextProperty(_certContext, CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID, CertSetPropertyFlags.None, &keyProvInfo))
                        {
                            throw new CryptographicException(Marshal.GetLastWin32Error());
                        }
                    }
                }
            }
        }
コード例 #25
0
        /// <summary>
        /// Creates the certificate and adds it to the store.
        /// </summary>
        private static string CreateSelfSignedCertificate(
            IntPtr hProvider,
            IntPtr hStore,
            bool useMachineStore,
            string applicationName,
            string applicationUri,
            string subjectName,
            IList<string> hostNames,
            ushort keySize,
            ushort lifetimeInMonths,
            ushort algorithm = 0)
        {
            IntPtr hKey = IntPtr.Zero;
            IntPtr pKpi = IntPtr.Zero;
            IntPtr pThumbprint = IntPtr.Zero;
            IntPtr pContext = IntPtr.Zero;
            IntPtr pAlgorithmId = IntPtr.Zero;
            IntPtr pNewContext = IntPtr.Zero;
            CRYPT_DATA_BLOB publicKeyId = new CRYPT_DATA_BLOB();
            CERT_NAME_BLOB subjectNameBlob = new CERT_NAME_BLOB();
            SYSTEMTIME stValidTo = new SYSTEMTIME();
            CERT_EXTENSIONS extensions = new CERT_EXTENSIONS();
            CRYPT_DATA_BLOB friendlyName = new CRYPT_DATA_BLOB();

            GCHandle hValidTo = new GCHandle();
            GCHandle hExtensionList = new GCHandle();
            GCHandle hSubjectNameBlob = new GCHandle();
            GCHandle hFriendlyName = new GCHandle();

            try
            {
                // create a new key pair.
                int bResult = NativeMethods.CryptGenKey(
                    hProvider,
                    AT_KEYEXCHANGE,
                    CRYPT_EXPORTABLE | (keySize << 16),
                    ref hKey);

                if (bResult == 0)
                {
                    Throw("Could not generate a new key pair. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // gey the public key identifier.
                GetPublicKeyIdentifier(hProvider, ref publicKeyId);

                // construct the certificate subject name.
                CreateX500Name(subjectName, ref subjectNameBlob);
                GCHandle hSubjectName = GCHandle.Alloc(subjectNameBlob, GCHandleType.Pinned);

                // allocate memory for all possible extensions.
                extensions.cExtension = 0;
                extensions.rgExtension = Marshal.AllocHGlobal(6 * Marshal.SizeOf(typeof(CERT_EXTENSION)));

                // create the subject key info extension.
                IntPtr pPos = extensions.rgExtension;
                CERT_EXTENSION extension = new CERT_EXTENSION();
                CreateSubjectKeyIdentifierExtension(ref extension, ref publicKeyId);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the authority key info extension.
                extension = new CERT_EXTENSION();
                CreateAuthorityKeyIdentifierExtension(ref extension, ref publicKeyId);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the basic constraints extension.
                extension = new CERT_EXTENSION();
                CreateBasicConstraintsExtension(ref extension, false);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the key usage extension.
                extension = new CERT_EXTENSION();
                CreateKeyUsageExtension(ref extension, false);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the extended key usage extension.
                extension = new CERT_EXTENSION();
                CreateExtendedKeyUsageExtension(ref extension);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // create the subject alternate name extension.
                extension = new CERT_EXTENSION();
                CreateSubjectAltNameExtension(applicationUri, hostNames, ref extension);
                Marshal.StructureToPtr(extension, pPos, false);
                pPos = new IntPtr(pPos.ToInt64() + Marshal.SizeOf(typeof(CERT_EXTENSION)));
                extensions.cExtension++;

                // set the expiration date.
                DateTime validTo = DateTime.UtcNow.AddMonths(lifetimeInMonths);
                System.Runtime.InteropServices.ComTypes.FILETIME ftValidTo = new System.Runtime.InteropServices.ComTypes.FILETIME();
                ulong ticks = (ulong)(validTo.Ticks - new DateTime(1601, 1, 1).Ticks);
                ftValidTo.dwHighDateTime = (int)((0xFFFFFFFF00000000 & (ulong)ticks) >> 32);
                ftValidTo.dwLowDateTime = (int)((ulong)ticks & 0x00000000FFFFFFFF);

                NativeMethods.FileTimeToSystemTime(ref ftValidTo, ref stValidTo);

                // specify what key is being used to sign the certificate.
                CRYPT_KEY_PROV_INFO kpi = new CRYPT_KEY_PROV_INFO();

                kpi.pwszContainerName = KEY_CONTAINER_NAME; // must be the same as the hProvider
                kpi.pwszProvName = DEFAULT_CRYPTO_PROVIDER;
                kpi.dwProvType = PROV_RSA_FULL;
                kpi.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
                kpi.dwKeySpec = AT_KEYEXCHANGE;

                if (useMachineStore)
                {
                    kpi.dwFlags |= CRYPT_MACHINE_KEYSET;
                }
                else
                {
                    kpi.dwFlags |= CRYPT_USER_KEYSET;
                }

                pKpi = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CRYPT_KEY_PROV_INFO)));
                Marshal.StructureToPtr(kpi, pKpi, false);

                hValidTo = GCHandle.Alloc(stValidTo, GCHandleType.Pinned);
                hExtensionList = GCHandle.Alloc(extensions, GCHandleType.Pinned);
                hSubjectNameBlob = GCHandle.Alloc(subjectNameBlob, GCHandleType.Pinned);

                if (algorithm == 1)
                {
                    CRYPT_ALGORITHM_IDENTIFIER algorithmID = new CRYPT_ALGORITHM_IDENTIFIER();
                    algorithmID.pszObjId = "1.2.840.113549.1.1.11"; //SHA256

                    pAlgorithmId = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CRYPT_ALGORITHM_IDENTIFIER)));
                    Marshal.StructureToPtr(algorithmID, pAlgorithmId, false);

                    //create the certificate
                    pContext = NativeMethods.CertCreateSelfSignCertificate(
                         hProvider,
                         hSubjectNameBlob.AddrOfPinnedObject(),
                         0,
                         pKpi,
                         pAlgorithmId,
                         IntPtr.Zero,
                         hValidTo.AddrOfPinnedObject(),
                         hExtensionList.AddrOfPinnedObject());
                }
                else
                {
                    // (default) create the certificate.
                    pContext = NativeMethods.CertCreateSelfSignCertificate(
                    hProvider,
                    hSubjectNameBlob.AddrOfPinnedObject(),
                    0,
                    pKpi,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    hValidTo.AddrOfPinnedObject(),
                    hExtensionList.AddrOfPinnedObject());
                }

                if (pContext == IntPtr.Zero)
                {
                    Throw("Could not create self-signed certificate. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // get the thumbprint.
                int dwThumbprintSize = 20;
                pThumbprint = Marshal.AllocHGlobal(dwThumbprintSize);

                bResult = NativeMethods.CertGetCertificateContextProperty(
                    pContext,
                    CERT_SHA1_HASH_PROP_ID,
                    pThumbprint,
                    ref dwThumbprintSize);

                if (bResult == 0)
                {
                    Throw("Could not get the thumbprint of the new certificate. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                byte[] bytes = new byte[dwThumbprintSize];
                Marshal.Copy(pThumbprint, bytes, 0, dwThumbprintSize);
                string thumbprint = Utils.ToHexString(bytes);

                // set the friendly name.
                friendlyName.pbData = Marshal.StringToHGlobalUni(applicationName);
                friendlyName.cbData = (applicationName.Length+1)*Marshal.SizeOf(typeof(ushort));
                hFriendlyName = GCHandle.Alloc(friendlyName, GCHandleType.Pinned);

                bResult = NativeMethods.CertSetCertificateContextProperty(
                    pContext,
                    CERT_FRIENDLY_NAME_PROP_ID,
                    0,
                    hFriendlyName.AddrOfPinnedObject());

                if (bResult == 0)
                {
                    Throw("Could not set the friendly name for the certificate. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                // add into store.
                bResult = NativeMethods.CertAddCertificateContextToStore(
                    hStore,
                    pContext,
                    CERT_STORE_ADD_REPLACE_EXISTING,
                    ref pNewContext);

                if (bResult == 0)
                {
                    Throw("Could not add the certificate to the store. Error={0:X8}", Marshal.GetLastWin32Error());
                }

                return thumbprint;
            }
            finally
            {
                if (pContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(pContext);
                }

                if (pNewContext != IntPtr.Zero)
                {
                    NativeMethods.CertFreeCertificateContext(pNewContext);
                }

                if (friendlyName.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(friendlyName.pbData);
                }

                if (pThumbprint != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pThumbprint);
                }

                if (pAlgorithmId != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pAlgorithmId, typeof(CRYPT_ALGORITHM_IDENTIFIER));
                    Marshal.FreeHGlobal(pAlgorithmId);
                }

                if (hValidTo.IsAllocated) hValidTo.Free();
                if (hExtensionList.IsAllocated) hExtensionList.Free();
                if (hSubjectNameBlob.IsAllocated) hSubjectNameBlob.Free();
                if (hFriendlyName.IsAllocated) hFriendlyName.Free();

                if (pKpi != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(pKpi, typeof(CRYPT_KEY_PROV_INFO));
                    Marshal.FreeHGlobal(pKpi);
                }

                DeleteExtensions(ref extensions.rgExtension, extensions.cExtension);
                DeleteX500Name(ref subjectNameBlob);

                if (publicKeyId.pbData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(publicKeyId.pbData);
                }

                if (hKey != IntPtr.Zero)
                {
                    NativeMethods.CryptDestroyKey(hKey);
                }
            }
        }
コード例 #26
0
		private static IntPtr CreateUnsignedCertCntxt(String keycontainer, String provider, uint KEYSPEC, uint cspflags, String DN) {
			const uint AT_KEYEXCHANGE = 0x00000001;
			const uint AT_SIGNATURE = 0x00000002;
			const uint CRYPT_MACHINE_KEYSET = 0x00000020;
			const uint PROV_RSA_FULL = 0x00000001;
			const String MS_DEF_PROV = "Microsoft Base Cryptographic Provider v1.0";
			const String MS_STRONG_PROV = "Microsoft Strong Cryptographic Provider";
			const String MS_ENHANCED_PROV = "Microsoft Enhanced Cryptographic Provider v1.0";
			const uint CERT_CREATE_SELFSIGN_NO_SIGN = 1;
			const uint X509_ASN_ENCODING = 0x00000001;
			const uint CERT_X500_NAME_STR = 3;
			IntPtr hCertCntxt = IntPtr.Zero;
			byte[] encodedName = null;
			uint cbName = 0;

			if (provider != MS_DEF_PROV && provider != MS_STRONG_PROV && provider != MS_ENHANCED_PROV)
				return IntPtr.Zero;
			if (keycontainer == "")
				return IntPtr.Zero;
			if (KEYSPEC != AT_SIGNATURE && KEYSPEC != AT_KEYEXCHANGE)
				return IntPtr.Zero;
			if (cspflags != 0 && cspflags != CRYPT_MACHINE_KEYSET)   //only 0 (Current User) keyset is currently used.
				return IntPtr.Zero;
			if (DN == "")
				return IntPtr.Zero;


			if (Win32.CertStrToName(X509_ASN_ENCODING, DN, CERT_X500_NAME_STR, IntPtr.Zero, null, ref cbName, IntPtr.Zero)) {
				encodedName = new byte[cbName];
				Win32.CertStrToName(X509_ASN_ENCODING, DN, CERT_X500_NAME_STR, IntPtr.Zero, encodedName, ref cbName, IntPtr.Zero);
			}

			CERT_NAME_BLOB subjectblob = new CERT_NAME_BLOB();
			subjectblob.pbData = Marshal.AllocHGlobal(encodedName.Length);
			Marshal.Copy(encodedName, 0, subjectblob.pbData, encodedName.Length);
			subjectblob.cbData = encodedName.Length;

			CRYPT_KEY_PROV_INFO pInfo = new CRYPT_KEY_PROV_INFO();
			pInfo.pwszContainerName = keycontainer;
			pInfo.pwszProvName = provider;
			pInfo.dwProvType = PROV_RSA_FULL;
			pInfo.dwFlags = cspflags;
			pInfo.cProvParam = 0;
			pInfo.rgProvParam = IntPtr.Zero;
			pInfo.dwKeySpec = KEYSPEC;

			hCertCntxt = Win32.CertCreateSelfSignCertificate(IntPtr.Zero, ref subjectblob, CERT_CREATE_SELFSIGN_NO_SIGN, ref pInfo, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
			if (hCertCntxt == IntPtr.Zero)
				showWin32Error(Marshal.GetLastWin32Error());
			Marshal.FreeHGlobal(subjectblob.pbData);
			return hCertCntxt;
		}
コード例 #27
0
ファイル: PrivateKeyFile.cs プロジェクト: darbio/MTSharpSSH
 private static extern int CertSetCertificateContextProperty(IntPtr pCertContext, int dwPropId, int dwFlags, ref CRYPT_KEY_PROV_INFO pvData);
コード例 #28
0
ファイル: Certificate.cs プロジェクト: ogazitt/aenetmail
 /// <summary>
 /// Associates the certificate with a private key from a PVK file.
 /// </summary>
 /// <param name="pvkFile">The path to the PVK file to open.</param>
 /// <param name="password">The password used to encrypt the private key.</param>
 /// <param name="exportable"><b>true</b> if the private key should be marked exportable, <b>false</b> otherwise.</param>
 /// <remarks>The <paramref name="password"/> can be a null reference (<b>Nothing</b> in Visual Basic) if the private key is not encrypted.</remarks>
 /// <exception cref="ArgumentNullException">The PVK file is encrypted and <paramref name="password"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
 /// <exception cref="FileNotFoundException">The specified file could not be found.</exception>
 /// <exception cref="CertificateException">An error occurs while importing the private key.</exception>
 public void AssociateWithPrivateKey(string pvkFile, string password, bool exportable)
 {
     try {
         if (!File.Exists(pvkFile))
             throw new FileNotFoundException("The PVK file could not be found.");
     } catch (FileNotFoundException fnf) {
         throw fnf;
     } catch (Exception e) {
         throw new FileNotFoundException("The PVK file could not be found.", e);
     }
     byte[] buffer = new byte[24];
     FileStream fs = File.Open(pvkFile, FileMode.Open, FileAccess.Read, FileShare.Read);
     fs.Read(buffer, 0, buffer.Length);
     if (BitConverter.ToUInt32(buffer, 0) != 0xB0B5F11E)
         throw new CertificateException("The specified file is not a valid PVK file.");
     int keytype = BitConverter.ToInt32(buffer, 8);
     int isEncrypted = BitConverter.ToInt32(buffer, 12);
     int saltLength = BitConverter.ToInt32(buffer, 16);
     int keyLen = BitConverter.ToInt32(buffer, 20);
     byte[] salt = new byte[saltLength];
     byte[] blob = new byte[keyLen];
     fs.Read(salt, 0, salt.Length);
     fs.Read(blob, 0, blob.Length);
     if (isEncrypted != 0) { // decrypt private key
         if (password == null)
             throw new ArgumentNullException();
         byte[] pass = Encoding.ASCII.GetBytes(password);
         byte[] key = new byte[salt.Length + password.Length];
         Array.Copy(salt, 0, key, 0, salt.Length);
         Array.Copy(pass, 0, key, salt.Length, pass.Length);
         byte[] pkb = TryDecrypt(blob, 8, blob.Length - 8, key, 16);
         if (pkb == null) { // decryption failed, try with an export key
             pkb = TryDecrypt(blob, 8, blob.Length - 8, key, 5);
             if (pkb == null) {
                 throw new CertificateException("The PVK file could not be decrypted. [wrong password?]");
             }
         }
         Array.Copy(pkb, 0, blob, 8, pkb.Length);
         Array.Clear(pkb, 0, pkb.Length);
         Array.Clear(pass, 0, pass.Length);
         Array.Clear(key, 0, key.Length);
     }
     int hKey = 0, flags = 0;
     if (exportable)
         flags = SecurityConstants.CRYPT_EXPORTABLE;
     int provider = CAPIProvider.ContainerHandle;
     if (SspiProvider.CryptImportKey(provider, blob, blob.Length, 0, flags, ref hKey) == 0)
         throw new CertificateException("Could not import the private key from the PVK file.");
     CRYPT_KEY_PROV_INFO kpi = new CRYPT_KEY_PROV_INFO();
     kpi.pwszContainerName = SecurityConstants.KEY_CONTAINER;
     kpi.pwszProvName = null;
     kpi.dwProvType = SecurityConstants.PROV_RSA_FULL;
     kpi.dwFlags = 0;
     kpi.cProvParam = 0;
     kpi.rgProvParam = IntPtr.Zero;
     kpi.dwKeySpec = keytype;
     if (SspiProvider.CertSetCertificateContextProperty(this.Handle, SecurityConstants.CERT_KEY_PROV_INFO_PROP_ID, 0, ref kpi) == 0)
         throw new CertificateException("Could not associate the private key with the certificate.");
     SspiProvider.CryptDestroyKey(hKey);
     Array.Clear(blob, 0, blob.Length);
 }
コード例 #29
0
ファイル: X509Native.cs プロジェクト: hookttg/opc-ua-client
 internal static extern bool CertSetCertificateContextProperty(
     SafeCertContextHandle certificateContext,
     uint propertyId,
     uint flags,
     [In] ref CRYPT_KEY_PROV_INFO data);
コード例 #30
0
        /// <summary>
        /// Create a self-signed x509 certificate.
        /// </summary>
        /// <param name="subjectName">The distinguished name.</param>
        /// <param name="notBefore">The start time.</param>
        /// <param name="notAfter">the end time.</param>
        /// <param name="extensions">the extensions.</param>
        /// <returns>A byte array containing the certificate and private key encoded as PFX.</returns>
        public static byte[] CreateSelfSignCertificatePfx(
            string subjectName,
            DateTime notBefore,
            DateTime notAfter,
            params X509Extension[] extensions)
        {
            if (subjectName == null)
            {
                subjectName = string.Empty;
            }

            byte[] pfxData;

            SYSTEMTIME startSystemTime = ToSystemTime(notBefore);
            SYSTEMTIME endSystemTime = ToSystemTime(notAfter);
            string containerName = $"Created by Workstation. {Guid.NewGuid().ToString()}";

            GCHandle gcHandle = default(GCHandle);
            var providerContext = SafeCryptProvHandle.InvalidHandle;
            var cryptKey = SafeCryptKeyHandle.InvalidHandle;
            var certContext = SafeCertContextHandle.InvalidHandle;
            var certStore = SafeCertStoreHandle.InvalidHandle;
            var storeCertContext = SafeCertContextHandle.InvalidHandle;

            try
            {
                Check(NativeMethods.CryptAcquireContextW(
                    out providerContext,
                    containerName,
                    null,
                    PROV_RSA_FULL,
                    CRYPT_NEWKEYSET));

                Check(NativeMethods.CryptGenKey(
                    providerContext,
                    AT_KEYEXCHANGE,
                    CRYPT_EXPORTABLE | (2048 << 16), // 2048bit
                    out cryptKey));

                IntPtr pbEncoded = IntPtr.Zero;
                int cbEncoded = 0;

                Check(NativeMethods.CertStrToNameW(
                    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                    subjectName,
                    CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref cbEncoded,
                    IntPtr.Zero));

                pbEncoded = Marshal.AllocHGlobal(cbEncoded);

                Check(NativeMethods.CertStrToNameW(
                    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                    subjectName,
                    CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
                    IntPtr.Zero,
                    pbEncoded,
                    ref cbEncoded,
                    IntPtr.Zero));

                var nameBlob = new CRYPTOAPI_BLOB
                {
                    cbData = (uint)cbEncoded,
                    pbData = pbEncoded
                };

                var kpi = new CRYPT_KEY_PROV_INFO
                {
                    pwszContainerName = containerName,
                    dwProvType = PROV_RSA_FULL,
                    dwKeySpec = AT_KEYEXCHANGE
                };

                var signatureAlgorithm = new CRYPT_ALGORITHM_IDENTIFIER
                {
                    pszObjId = OID_RSA_SHA256RSA,
                    Parameters = default(CRYPTOAPI_BLOB)
                };

                IntPtr pInfo = IntPtr.Zero;
                int cbInfo = 0;
                byte[] keyHash = null;
                int cbKeyHash = 0;

                try
                {
                    Check(NativeMethods.CryptExportPublicKeyInfoEx(
                        providerContext,
                        AT_KEYEXCHANGE,
                        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                        OID_RSA_RSA,
                        0,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        ref cbInfo));

                    pInfo = Marshal.AllocHGlobal(cbInfo);

                    Check(NativeMethods.CryptExportPublicKeyInfoEx(
                        providerContext,
                        AT_KEYEXCHANGE,
                        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                        OID_RSA_RSA,
                        0,
                        IntPtr.Zero,
                        pInfo,
                        ref cbInfo));

                    Check(NativeMethods.CryptHashPublicKeyInfo(
                        providerContext,
                        CALG_SHA1,
                        0,
                        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                        pInfo,
                        null,
                        ref cbKeyHash));

                    keyHash = new byte[cbKeyHash];

                    Check(NativeMethods.CryptHashPublicKeyInfo(
                        providerContext,
                        CALG_SHA1,
                        0,
                        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                        pInfo,
                        keyHash,
                        ref cbKeyHash));
                }
                finally
                {
                    if (pInfo != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(pInfo);
                    }
                }

                var safeExtensions = new List<SafeX509Extension>();
                var blob = IntPtr.Zero;
                try
                {
                    foreach (var item in extensions)
                    {
                        safeExtensions.Add(new SafeX509Extension(item));
                    }

                    // adding SubjectKeyIdentifier TODO: AuthKeyIdentifier?
                    safeExtensions.Add(new SafeX509Extension(new X509SubjectKeyIdentifierExtension(keyHash, false)));

                    var structSize = Marshal.SizeOf<CERT_EXTENSION>();
                    blob = Marshal.AllocHGlobal(structSize * safeExtensions.Count);
                    for (int index = 0, offset = 0; index < safeExtensions.Count; index++, offset += structSize)
                    {
                        var marshalX509Extension = safeExtensions[index];
                        Marshal.StructureToPtr(marshalX509Extension.Value, blob + offset, false);
                    }

                    var certExtensions = new CERT_EXTENSIONS { cExtension = (uint)safeExtensions.Count, rgExtension = blob };

                    certContext = NativeMethods.CertCreateSelfSignCertificate(
                        providerContext,
                        ref nameBlob,
                        0,
                        ref kpi,
                        ref signatureAlgorithm,
                        ref startSystemTime,
                        ref endSystemTime,
                        ref certExtensions);
                    Check(!certContext.IsInvalid);
                }
                finally
                {
                    foreach (var safeExtension in safeExtensions)
                    {
                        safeExtension.Dispose();
                    }

                    safeExtensions.Clear();
                    Marshal.FreeHGlobal(blob);
                    Marshal.FreeHGlobal(pbEncoded);
                }

                certStore = NativeMethods.CertOpenStore(
                    sz_CERT_STORE_PROV_MEMORY,
                    0,
                    IntPtr.Zero,
                    CERT_STORE_CREATE_NEW_FLAG,
                    IntPtr.Zero);
                Check(!certStore.IsInvalid);

                Check(NativeMethods.CertAddCertificateContextToStore(
                    certStore,
                    certContext,
                    CERT_STORE_ADD_NEW,
                    out storeCertContext));

                NativeMethods.CertSetCertificateContextProperty(
                    storeCertContext,
                    CERT_KEY_PROV_INFO_PROP_ID,
                    0,
                    ref kpi);

                CRYPTOAPI_BLOB pfxBlob = default(CRYPTOAPI_BLOB);
                Check(NativeMethods.PFXExportCertStoreEx(
                    certStore,
                    ref pfxBlob,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY));

                pfxData = new byte[pfxBlob.cbData];
                gcHandle = GCHandle.Alloc(pfxData, GCHandleType.Pinned);
                pfxBlob.pbData = gcHandle.AddrOfPinnedObject();

                Check(NativeMethods.PFXExportCertStoreEx(
                    certStore,
                    ref pfxBlob,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY));

                gcHandle.Free();
            }
            finally
            {
                if (gcHandle.IsAllocated)
                {
                    gcHandle.Free();
                }

                if (!certContext.IsInvalid)
                {
                    certContext.Dispose();
                }

                if (!storeCertContext.IsInvalid)
                {
                    storeCertContext.Dispose();
                }

                if (!certStore.IsInvalid)
                {
                    certStore.Dispose();
                }

                if (!cryptKey.IsInvalid)
                {
                    cryptKey.Dispose();
                }

                if (!providerContext.IsInvalid)
                {
                    providerContext.Dispose();
                    providerContext = SafeCryptProvHandle.InvalidHandle;

                    // Delete generated keyset. Does not return a providerContext
                    NativeMethods.CryptAcquireContextW(
                        out providerContext,
                        containerName,
                        null,
                        PROV_RSA_FULL,
                        CRYPT_DELETEKEYSET);
                }
            }

            return pfxData;
        }
コード例 #31
0
ファイル: PVKFile.cs プロジェクト: zhangli0092/opennetcf
        public IntPtr Import(string password)
        {
            var containerName = "CERT";

            var context = Context.AcquireContext(containerName);

            try
            {
                var hHash = IntPtr.Zero;

                // get a symmetric key to decrypt the private key
                if (NativeMethods.CryptCreateHash(context, Const.CALG_SHA, IntPtr.Zero, 0, out hHash))
                {
                    try
                    {
                        if (SaltData.Length > 0)
                        {
                            if (!NativeMethods.CryptHashData(hHash, SaltData, SaltData.Length, 0))
                            {
                                throw new CryptographicException(Marshal.GetLastWin32Error());
                            }
                        }

                        var passwordBytes = Encoding.ASCII.GetBytes(password);
                        if (!NativeMethods.CryptHashData(hHash, passwordBytes, passwordBytes.Length, 0))
                        {
                            throw new CryptographicException(Marshal.GetLastWin32Error());
                        }
                        var decryptKey = IntPtr.Zero;

                        uint enc = EncryptionType == PVKEncryptionType.RC4Password ? Const.CALG_RC4 : Const.CALG_RC2;

                        if (!NativeMethods.CryptDeriveKey(context, enc, hHash, 0, out decryptKey))
                        {
                            throw new CryptographicException(Marshal.GetLastWin32Error());
                        }

                        try
                        {
                            // decrypt and import the private key
                            var importKey = IntPtr.Zero;
                            if (!NativeMethods.CryptImportKey(context, KeyData, (uint)KeyData.Length, decryptKey, Const.CRYPT_EXPORTABLE, out importKey))
                            {
                                throw new CryptographicException(Marshal.GetLastWin32Error());
                            }

                            // get the info length
                            int length = 0;
                            if (!NativeMethods.CryptExportPublicKeyInfo(context, KeySpec, Const.CRYPT_ASN_ENCODING, IntPtr.Zero, ref length))
                            {
                                throw new CryptographicException(Marshal.GetLastWin32Error());
                            }
                            var pInfo = Marshal.AllocHGlobal(length);

                            try
                            {
                                // get the public key info
                                if (!NativeMethods.CryptExportPublicKeyInfo(context, KeySpec, Const.CRYPT_ASN_ENCODING, pInfo, ref length))
                                {
                                    throw new CryptographicException(Marshal.GetLastWin32Error());
                                }

                                // find a certificate in the store that matches this private key
                                var pCert = NativeMethods.CertFindCertificateInStore(Store.Handle, Const.CRYPT_ASN_ENCODING, 0, Const.CERT_FIND_PUBLIC_KEY, pInfo, IntPtr.Zero);

                                if (pCert == IntPtr.Zero)
                                {
                                    throw new CryptographicException("No Certificate found in store for this Private Key");
                                }

                                var keyProvInfo = new CRYPT_KEY_PROV_INFO();

                                keyProvInfo.pwszContainerName = Context.KeyContainer;
                                keyProvInfo.pwszProvName      = Context.ProviderName == null ? null : Const.MS_ENHANCED_PROV;
                                keyProvInfo.dwProvType        = (int)Const.PROV_RSA_FULL;
                                keyProvInfo.dwFlags           = 0;
                                keyProvInfo.cProvParam        = 0;
                                keyProvInfo.rgProvParam       = IntPtr.Zero;
                                keyProvInfo.dwKeySpec         = KeySpec;


                                if (!NativeMethods.CertSetCertificateContextProperty(
                                        pCert, Const.CERT_KEY_PROV_INFO_PROP_ID,
                                        0, keyProvInfo))
                                {
                                    throw new CryptographicException(Marshal.GetLastWin32Error());
                                }

                                return(pCert);
                            }
                            finally
                            {
                                Marshal.FreeHGlobal(pInfo);
                            }
                        }
                        finally
                        {
                            NativeMethods.CryptDestroyKey(decryptKey);
                        }
                    }
                    finally
                    {
                        NativeMethods.CryptDestroyHash(hHash);
                    }
                }
            }
            finally
            {
                Context.ReleaseContext(context);
            }

            return(IntPtr.Zero);
        }
コード例 #32
0
ファイル: X509Native.cs プロジェクト: tk4218/clrsecurity
        internal static SafeCertContextHandle CreateSelfSignedCertificate(CngKey key,
                                                                          bool takeOwnershipOfKey,
                                                                          byte[] subjectName,
                                                                          X509CertificateCreationOptions creationOptions,
                                                                          string signatureAlgorithmOid,
                                                                          DateTime startTime,
                                                                          DateTime endTime,
                                                                          X509ExtensionCollection extensions)
        {
            Debug.Assert(key != null, "key != null");
            Debug.Assert(subjectName != null, "subjectName != null");
            Debug.Assert(!String.IsNullOrEmpty(signatureAlgorithmOid), "!String.IsNullOrEmpty(signatureAlgorithmOid)");
            Debug.Assert(extensions != null, "extensions != null");

            // Create an algorithm identifier structure for the signature algorithm
            CapiNative.CRYPT_ALGORITHM_IDENTIFIER nativeSignatureAlgorithm = new CapiNative.CRYPT_ALGORITHM_IDENTIFIER();
            nativeSignatureAlgorithm.pszObjId          = signatureAlgorithmOid;
            nativeSignatureAlgorithm.Parameters        = new CapiNative.CRYPTOAPI_BLOB();
            nativeSignatureAlgorithm.Parameters.cbData = 0;
            nativeSignatureAlgorithm.Parameters.pbData = IntPtr.Zero;

            // Convert the begin and expire dates to system time structures
            Win32Native.SYSTEMTIME nativeStartTime = new Win32Native.SYSTEMTIME(startTime);
            Win32Native.SYSTEMTIME nativeEndTime   = new Win32Native.SYSTEMTIME(endTime);

            // Map the extensions into CERT_EXTENSIONS.  This involves several steps to get the
            // CERT_EXTENSIONS ready for interop with the native APIs.
            //   1. Build up the CERT_EXTENSIONS structure in managed code
            //   2. For each extension, create a managed CERT_EXTENSION structure; this requires allocating
            //      native memory for the blob pointer in the CERT_EXTENSION. These extensions are stored in
            //      the nativeExtensionArray variable.
            //   3. Get a block of native memory that can hold a native array of CERT_EXTENSION structures.
            //      This is the block referenced by the CERT_EXTENSIONS structure.
            //   4. For each of the extension structures created in step 2, marshal the extension into the
            //      native buffer allocated in step 3.
            CERT_EXTENSIONS nativeExtensions = new CERT_EXTENSIONS();

            nativeExtensions.cExtension = extensions.Count;
            CERT_EXTENSION[] nativeExtensionArray = new CERT_EXTENSION[extensions.Count];

            // Run this in a CER to ensure that we release any native memory allocated for the certificate
            // extensions.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                // Copy over each extension into a native extension structure, including allocating native
                // memory for its blob if necessary.
                for (int i = 0; i < extensions.Count; ++i)
                {
                    nativeExtensionArray[i]           = new CERT_EXTENSION();
                    nativeExtensionArray[i].pszObjId  = extensions[i].Oid.Value;
                    nativeExtensionArray[i].fCritical = extensions[i].Critical;

                    nativeExtensionArray[i].Value        = new CapiNative.CRYPTOAPI_BLOB();
                    nativeExtensionArray[i].Value.cbData = extensions[i].RawData.Length;
                    if (nativeExtensionArray[i].Value.cbData > 0)
                    {
                        nativeExtensionArray[i].Value.pbData =
                            Marshal.AllocCoTaskMem(nativeExtensionArray[i].Value.cbData);
                        Marshal.Copy(extensions[i].RawData,
                                     0,
                                     nativeExtensionArray[i].Value.pbData,
                                     nativeExtensionArray[i].Value.cbData);
                    }
                }

                // Now that we've built up the extension array, create a block of native memory to marshal
                // them into.
                if (nativeExtensionArray.Length > 0)
                {
                    checked
                    {
                        // CERT_EXTENSION structures end with a pointer field, which means on all supported
                        // platforms they won't require any padding between elements of the array.
                        nativeExtensions.rgExtension =
                            Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(CERT_EXTENSION)) * nativeExtensionArray.Length);

                        for (int i = 0; i < nativeExtensionArray.Length; ++i)
                        {
                            ulong  offset            = (uint)i * (uint)Marshal.SizeOf(typeof(CERT_EXTENSION));
                            ulong  next              = offset + (ulong)nativeExtensions.rgExtension.ToInt64();
                            IntPtr nextExtensionAddr = new IntPtr((long)next);

                            Marshal.StructureToPtr(nativeExtensionArray[i], nextExtensionAddr, false);
                        }
                    }
                }

                // Setup a CRYPT_KEY_PROV_INFO for the key
                CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();
                keyProvInfo.pwszContainerName = key.UniqueName;
                keyProvInfo.pwszProvName      = key.Provider.Provider;
                keyProvInfo.dwProvType        = 0; // NCRYPT
                keyProvInfo.dwFlags           = 0;
                keyProvInfo.cProvParam        = 0;
                keyProvInfo.rgProvParam       = IntPtr.Zero;
                keyProvInfo.dwKeySpec         = 0;

                //
                // Now that all of the needed data structures are setup, we can create the certificate
                //

                SafeCertContextHandle selfSignedCertHandle = null;
                unsafe
                {
                    fixed(byte *pSubjectName = &subjectName[0])
                    {
                        // Create a CRYPTOAPI_BLOB for the subject of the cert
                        CapiNative.CRYPTOAPI_BLOB nativeSubjectName = new CapiNative.CRYPTOAPI_BLOB();
                        nativeSubjectName.cbData = subjectName.Length;
                        nativeSubjectName.pbData = new IntPtr(pSubjectName);

                        // Now that we've converted all the inputs to native data structures, we can generate
                        // the self signed certificate for the input key.
                        using (SafeNCryptKeyHandle keyHandle = key.Handle)
                        {
                            selfSignedCertHandle =
                                UnsafeNativeMethods.CertCreateSelfSignCertificate(keyHandle,
                                                                                  ref nativeSubjectName,
                                                                                  creationOptions,
                                                                                  ref keyProvInfo,
                                                                                  ref nativeSignatureAlgorithm,
                                                                                  ref nativeStartTime,
                                                                                  ref nativeEndTime,
                                                                                  ref nativeExtensions);
                            if (selfSignedCertHandle.IsInvalid)
                            {
                                throw new CryptographicException(Marshal.GetLastWin32Error());
                            }
                        }
                    }
                }

                Debug.Assert(selfSignedCertHandle != null, "selfSignedCertHandle != null");

                // Attach a key context to the certificate which will allow Windows to find the private key
                // associated with the certificate if the NCRYPT_KEY_HANDLE is ephemeral.
                // is done.
                using (SafeNCryptKeyHandle keyHandle = key.Handle)
                {
                    CERT_KEY_CONTEXT keyContext = new CERT_KEY_CONTEXT();
                    keyContext.cbSize     = Marshal.SizeOf(typeof(CERT_KEY_CONTEXT));
                    keyContext.hNCryptKey = keyHandle.DangerousGetHandle();
                    keyContext.dwKeySpec  = KeySpec.NCryptKey;

                    bool attachedProperty = false;
                    int  setContextError  = 0;

                    // Run in a CER to ensure accurate tracking of the transfer of handle ownership
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try { }
                    finally
                    {
                        CertificatePropertySetFlags flags = CertificatePropertySetFlags.None;
                        if (!takeOwnershipOfKey)
                        {
                            // If the certificate is not taking ownership of the key handle, then it should
                            // not release the handle when the context is released.
                            flags |= CertificatePropertySetFlags.NoCryptRelease;
                        }

                        attachedProperty =
                            UnsafeNativeMethods.CertSetCertificateContextProperty(selfSignedCertHandle,
                                                                                  CertificateProperty.KeyContext,
                                                                                  flags,
                                                                                  ref keyContext);
                        setContextError = Marshal.GetLastWin32Error();

                        // If we succesfully transferred ownership of the key to the certificate,
                        // then we need to ensure that we no longer release its handle.
                        if (attachedProperty && takeOwnershipOfKey)
                        {
                            keyHandle.SetHandleAsInvalid();
                        }
                    }

                    if (!attachedProperty)
                    {
                        throw new CryptographicException(setContextError);
                    }
                }

                return(selfSignedCertHandle);
            }
            finally
            {
                //
                // In order to release all resources held by the CERT_EXTENSIONS we need to do three things
                //   1. Destroy each structure marshaled into the native CERT_EXTENSION array
                //   2. Release the memory used for the CERT_EXTENSION array
                //   3. Release the memory used in each individual CERT_EXTENSION
                //

                // Release each extension marshaled into the native buffer as well
                if (nativeExtensions.rgExtension != IntPtr.Zero)
                {
                    for (int i = 0; i < nativeExtensionArray.Length; ++i)
                    {
                        ulong  offset            = (uint)i * (uint)Marshal.SizeOf(typeof(CERT_EXTENSION));
                        ulong  next              = offset + (ulong)nativeExtensions.rgExtension.ToInt64();
                        IntPtr nextExtensionAddr = new IntPtr((long)next);

                        Marshal.DestroyStructure(nextExtensionAddr, typeof(CERT_EXTENSION));
                    }

                    Marshal.FreeCoTaskMem(nativeExtensions.rgExtension);
                }

                // If we allocated memory for any extensions, make sure to free it now
                for (int i = 0; i < nativeExtensionArray.Length; ++i)
                {
                    if (nativeExtensionArray[i].Value.pbData != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(nativeExtensionArray[i].Value.pbData);
                    }
                }
            }
        }
コード例 #33
0
 public static extern bool CertSetCertificateContextProperty(IntPtr pCertContext, uint dwPropId, uint dwFlags, ref CRYPT_KEY_PROV_INFO pvData);
コード例 #34
0
ファイル: CryptoApiMethods.cs プロジェクト: michyer/canape
 public static extern IntPtr CertCreateSelfSignCertificate(
     SafeCryptProviderHandle hCryptProvOrNCryptKey,
     [Out] CRYPTOAPI_BLOB pSubjectIssuerBlob,
     CertCreationFlags dwFlags,
     CRYPT_KEY_PROV_INFO pKeyProvInfo,
     CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
     SYSTEMTIME pStartTime,
     SYSTEMTIME pEndTime,
     CERT_EXTENSIONS pExtension
     );
コード例 #35
0
        public static void Register(X509Certificate2 cert, CertificateContext context)
        {
            IntPtr hCertContext = new IntPtr();
            hCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert.RawData,(uint) cert.RawData.Length);

            CRYPT_KEY_PROV_INFO ProvInfo = new CRYPT_KEY_PROV_INFO();
            ProvInfo.ContainerName = context.containerName;
            ProvInfo.ProvName = context.providerName;
            ProvInfo.ProvType = PROV_RSA_FULL;
            ProvInfo.Flags = 0;
            ProvInfo.KeySpec = context.keySpec;
            ProvInfo.ProvParam = 0;
            ProvInfo.rgProvParam = new IntPtr();

            if (!CertSetCertificateContextProperty(hCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, ref ProvInfo))
                throw new Exception("Could set certificate's context.");

            Debug.WriteLine("Context set!");

            IntPtr hCertStore = CertOpenStoreStringPara(CERT_STORE_PROV_SYSTEM_W, 0, new IntPtr(),
                CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, "My");

            if (!CertAddCertificateContextToStore(hCertStore, hCertContext, CERT_STORE_ADD_REPLACE_EXISTING, new IntPtr()))
                throw new Exception("Could not add certificate to store.");
        }
コード例 #36
0
 internal static extern bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext,
                                                               CertificateProperty dwPropId,
                                                               CertSetPropertyFlags dwFlags,
                                                               [In] ref CRYPT_KEY_PROV_INFO pvData);
コード例 #37
0
        public static void RegisterKeyContainer()
        {
            uint[] keySpecs = { AT_SIGNATURE, AT_KEYEXCHANGE };
            string providerName = "Microsoft Base Smart Card Crypto Provider";
            IntPtr hCryptProvider = new IntPtr();
            
            if (!CryptAcquireContext(ref hCryptProvider, null, providerName, PROV_RSA_FULL, (uint)0))
                throw new RegisterException(new RegisterExceptionEventArgs(RegisterException.ACQUIRE_CONTEXT));
            
            uint bufferSize = 1024;
            StringBuilder containerName = new StringBuilder((int)bufferSize);

            // enumerate all containers
            while (CryptGetProvParam(hCryptProvider, PP_ENUMCONTAINERS, containerName, ref bufferSize, CRYPT_FIRST))
            {
                Debug.WriteLine("Container Name: " + containerName.ToString());
                if (!CryptAcquireContext(ref hCryptProvider, containerName.ToString(), providerName, PROV_RSA_FULL, 0))
                    continue;

                // loop over the key specs
                foreach (uint keySpec in keySpecs)
                {
                    IntPtr hUserKey = new IntPtr();
                    uint certLen = 0;

                    if (!CryptGetUserKey(hCryptProvider, keySpec, ref hUserKey))
                        continue;
                    
                    if (!CryptGetKeyParam(hUserKey, KP_CERTIFICATE, 0, ref certLen, 0)) // get certificate length
                        throw new Exception("Could not retrieve certificate length.");
                    
                    Debug.WriteLine("got certificate length");

                    byte[] rawCert = new byte[certLen];
                    if (!CryptGetKeyParam(hUserKey, KP_CERTIFICATE, rawCert, ref certLen, 0)) // get certificate
                        throw new Exception("Could not retrieve certificate.");
                    
                    Debug.WriteLine("got certificate");
                    IntPtr hCertContext = new IntPtr();
                    hCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, rawCert, certLen);

                    CRYPT_KEY_PROV_INFO ProvInfo = new CRYPT_KEY_PROV_INFO();
                    ProvInfo.ContainerName = containerName.ToString();
                    ProvInfo.ProvName = providerName;
                    ProvInfo.ProvType = PROV_RSA_FULL;
                    ProvInfo.Flags = 0;
                    ProvInfo.KeySpec = AT_SIGNATURE;
                    ProvInfo.ProvParam = 0;
                    ProvInfo.rgProvParam = new IntPtr();

                    X509Certificate2 c = new X509Certificate2(rawCert);
                    string name = c.SubjectName.Name;

                    if (!CertSetCertificateContextProperty(hCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, ref ProvInfo))
                        throw new Exception("Could set certificate's context.");
                    
                    Debug.WriteLine("Context set!");

                    IntPtr hCertStore = CertOpenStoreStringPara(CERT_STORE_PROV_SYSTEM_W, 0, new IntPtr(),
                        CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, "My");

                    if (!CertAddCertificateContextToStore(hCertStore, hCertContext, CERT_STORE_ADD_REPLACE_EXISTING, new IntPtr()))
                        throw new Exception("Could not add certificate to store.");
                }
            }
        }
 private CriticalAllocHandle GetProviderInfo()
 {
     CRYPT_KEY_PROV_INFO id = new CRYPT_KEY_PROV_INFO {
         container = this.keyContainerName,
         providerType = 12,
         paramsCount = 0,
         keySpec = 1
     };
     return CriticalAllocHandleBlob.FromBlob<CRYPT_KEY_PROV_INFO>(id);
 }
コード例 #39
0
        private static SafeCertContextHandle CreateSelfSignedCertificate(CngKey key,
                                                                         bool takeOwnershipOfKey,
                                                                         byte[] subjectName,
                                                                         X509CertificateCreationOptions creationOptions,
                                                                         string signatureAlgorithmOid,
                                                                         DateTime startTime,
                                                                         DateTime endTime)
        {
            // Create an algorithm identifier structure for the signature algorithm
            CRYPT_ALGORITHM_IDENTIFIER nativeSignatureAlgorithm = new CRYPT_ALGORITHM_IDENTIFIER();

            nativeSignatureAlgorithm.pszObjId          = signatureAlgorithmOid;
            nativeSignatureAlgorithm.Parameters        = new CRYPTOAPI_BLOB();
            nativeSignatureAlgorithm.Parameters.cbData = 0;
            nativeSignatureAlgorithm.Parameters.pbData = IntPtr.Zero;

            // Convert the begin and expire dates to system time structures
            SYSTEMTIME nativeStartTime = new SYSTEMTIME(startTime);
            SYSTEMTIME nativeEndTime   = new SYSTEMTIME(endTime);

            CERT_EXTENSIONS nativeExtensions = new CERT_EXTENSIONS();

            nativeExtensions.cExtension = 0;

            // Setup a CRYPT_KEY_PROV_INFO for the key
            CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();

            keyProvInfo.pwszContainerName = key.UniqueName;
            keyProvInfo.pwszProvName      = key.Provider.Provider;
            keyProvInfo.dwProvType        = 0; // NCRYPT
            keyProvInfo.dwFlags           = 0;
            keyProvInfo.cProvParam        = 0;
            keyProvInfo.rgProvParam       = IntPtr.Zero;
            keyProvInfo.dwKeySpec         = 0;

            //
            // Now that all of the needed data structures are setup, we can create the certificate
            //

            SafeCertContextHandle selfSignedCertHandle = null;

            unsafe
            {
                fixed(byte *pSubjectName = &subjectName[0])
                {
                    // Create a CRYPTOAPI_BLOB for the subject of the cert
                    CRYPTOAPI_BLOB nativeSubjectName = new CRYPTOAPI_BLOB();

                    nativeSubjectName.cbData = subjectName.Length;
                    nativeSubjectName.pbData = new IntPtr(pSubjectName);

                    // Now that we've converted all the inputs to native data structures, we can generate
                    // the self signed certificate for the input key.
                    using (SafeNCryptKeyHandle keyHandle = key.Handle)
                    {
                        selfSignedCertHandle = CertCreateSelfSignCertificate(keyHandle,
                                                                             ref nativeSubjectName,
                                                                             creationOptions,
                                                                             ref keyProvInfo,
                                                                             ref nativeSignatureAlgorithm,
                                                                             ref nativeStartTime,
                                                                             ref nativeEndTime,
                                                                             ref nativeExtensions);
                        if (selfSignedCertHandle.IsInvalid)
                        {
                            throw new CryptographicException(Marshal.GetLastWin32Error());
                        }
                    }
                }
            }

            Debug.Assert(selfSignedCertHandle != null, "selfSignedCertHandle != null");

            // Attach a key context to the certificate which will allow Windows to find the private key
            // associated with the certificate if the NCRYPT_KEY_HANDLE is ephemeral.
            // is done.
            using (SafeNCryptKeyHandle keyHandle = key.Handle)
            {
                CERT_KEY_CONTEXT keyContext = new CERT_KEY_CONTEXT();
                keyContext.cbSize     = Marshal.SizeOf(typeof(CERT_KEY_CONTEXT));
                keyContext.hNCryptKey = keyHandle.DangerousGetHandle();
                keyContext.dwKeySpec  = KeySpec.NCryptKey;

                bool attachedProperty = false;
                int  setContextError  = 0;

                // Run in a CER to ensure accurate tracking of the transfer of handle ownership
                RuntimeHelpers.PrepareConstrainedRegions();
                try { }
                finally
                {
                    CertificatePropertySetFlags flags = CertificatePropertySetFlags.None;
                    if (!takeOwnershipOfKey)
                    {
                        // If the certificate is not taking ownership of the key handle, then it should
                        // not release the handle when the context is released.
                        flags |= CertificatePropertySetFlags.NoCryptRelease;
                    }

                    attachedProperty = CertSetCertificateContextProperty(selfSignedCertHandle,
                                                                         CertificateProperty.KeyContext,
                                                                         flags,
                                                                         ref keyContext);
                    setContextError = Marshal.GetLastWin32Error();

                    // If we succesfully transferred ownership of the key to the certificate,
                    // then we need to ensure that we no longer release its handle.
                    if (attachedProperty && takeOwnershipOfKey)
                    {
                        keyHandle.SetHandleAsInvalid();
                    }
                }

                if (!attachedProperty)
                {
                    throw new CryptographicException(setContextError);
                }
            }

            return(selfSignedCertHandle);
        }
コード例 #40
0
        // begin: gost
        public unsafe void SetCspPrivateKey(AsymmetricAlgorithm key)
        {
            if (key == null)
            {
                return;
            }
            CspKeyContainerInfo keyContainerInfo;

            switch (key.SignatureAlgorithm)
            {
            case GostConstants.XmlSignatureAlgorithm2001:
            {
                Gost3410CryptoServiceProvider asymmetricAlgorithm = key as Gost3410CryptoServiceProvider;
                keyContainerInfo = asymmetricAlgorithm.CspKeyContainerInfo;
                break;
            }

            case GostConstants.XmlSignatureAlgorithm2012_256:
            {
                Gost3410_2012_256CryptoServiceProvider asymmetricAlgorithm = key as Gost3410_2012_256CryptoServiceProvider;
                keyContainerInfo = asymmetricAlgorithm.CspKeyContainerInfo;
                break;
            }

            case GostConstants.XmlSignatureAlgorithm2012_512:
            {
                Gost3410_2012_512CryptoServiceProvider asymmetricAlgorithm = key as Gost3410_2012_512CryptoServiceProvider;
                keyContainerInfo = asymmetricAlgorithm.CspKeyContainerInfo;
                break;
            }

            case "RSA":
            {
                RSACryptoServiceProvider asymmetricAlgorithm = key as RSACryptoServiceProvider;
                keyContainerInfo = asymmetricAlgorithm.CspKeyContainerInfo;
                break;
            }

            case "DSA":
            {
                DSACryptoServiceProvider asymmetricAlgorithm = key as DSACryptoServiceProvider;
                keyContainerInfo = asymmetricAlgorithm.CspKeyContainerInfo;
                break;
            }

            default:
            {
                throw new PlatformNotSupportedException();
            }
            }

            SafeLocalAllocHandle ptr = SafeLocalAllocHandle.InvalidHandle;

            fixed(char *keyContainerName = keyContainerInfo.KeyContainerName)
            fixed(char *providerName = keyContainerInfo.ProviderName)
            {
                CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();

                keyProvInfo.pwszContainerName = keyContainerName;
                keyProvInfo.pwszProvName      = providerName;
                keyProvInfo.dwProvType        = keyContainerInfo.ProviderType;
                keyProvInfo.dwFlags           = keyContainerInfo.MachineKeyStore
                    ? CryptAcquireContextFlags.CRYPT_MACHINE_KEYSET
                    : CryptAcquireContextFlags.None;
                keyProvInfo.cProvParam  = 0;
                keyProvInfo.rgProvParam = IntPtr.Zero;
                keyProvInfo.dwKeySpec   = (int)keyContainerInfo.KeyNumber;

                if (!Interop.crypt32.CertSetCertificateContextProperty(
                        _certContext,
                        CertContextPropId.CERT_KEY_PROV_INFO_PROP_ID,
                        CertSetPropertyFlags.None,
                        &keyProvInfo))
                {
                    throw Marshal.GetLastWin32Error().ToCryptographicException();
                }
            }
        }
コード例 #41
0
ファイル: PrivateKeyFile.cs プロジェクト: darbio/MTSharpSSH
        /// <summary>
        /// Associates this private key instance with the corresponding X509 certificate.
        /// </summary>
        /// <param name="certificate">An <see cref="X509Certificate"/> instance to associate the key with.</param>
        /// <param name="exportable"><b>true</b> if the key should be marked as exportable, <b>false</b> otherwise.</param>
        /// <exception cref="CryptographicException">An error occurs while associating the private key with the certificate.</exception>
        public void AssociateWith(X509Certificate certificate, bool exportable)
        {
            if (certificate == null)
                throw new ArgumentNullException("certificate");

            IntPtr hKey = IntPtr.Zero;
            int flags = 0;
            if (exportable)
                flags = CRYPT_EXPORTABLE;
            using (CryptoProviderHandle provider = new CryptoProviderHandle()) {
                if (CryptImportKey(provider.Handle, _blob, _blob.Length, IntPtr.Zero, flags, ref hKey) == 0)
                    throw new CryptographicException("Could not import the private key from the PVK file.");
                CRYPT_KEY_PROV_INFO kpi = new CRYPT_KEY_PROV_INFO();
                kpi.pwszContainerName = provider.Container;
                kpi.pwszProvName = null;
                kpi.dwProvType = provider.ProviderType;
                kpi.dwFlags = 0;
                kpi.cProvParam = 0;
                kpi.rgProvParam = IntPtr.Zero;
                kpi.dwKeySpec = _keyType;
                if (CertSetCertificateContextProperty(certificate.Handle, CERT_KEY_PROV_INFO_PROP_ID, 0, ref kpi) == 0)
                    throw new CryptographicException("Could not associate the private key with the certificate.");
                CryptDestroyKey(hKey);
            }
        }