internal static unsafe X509Certificate2 CreateDummyCertificate(CspParameters parameters) { System.Security.Cryptography.SafeCertContextHandle invalidHandle = System.Security.Cryptography.SafeCertContextHandle.InvalidHandle; SafeCryptProvHandle hCryptProv = SafeCryptProvHandle.InvalidHandle; uint dwFlags = 0U; if ((parameters.Flags & CspProviderFlags.UseMachineKeyStore) != CspProviderFlags.NoFlags) { dwFlags |= 32U; } if ((parameters.Flags & CspProviderFlags.UseDefaultKeyContainer) != CspProviderFlags.NoFlags) { dwFlags |= 4026531840U; } if ((parameters.Flags & CspProviderFlags.NoPrompt) != CspProviderFlags.NoFlags) { dwFlags |= 64U; } if (!CAPI.CryptAcquireContext(ref hCryptProv, parameters.KeyContainerName, parameters.ProviderName, (uint)parameters.ProviderType, dwFlags)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } CAPI.CRYPT_KEY_PROV_INFO cryptKeyProvInfo = new CAPI.CRYPT_KEY_PROV_INFO(); cryptKeyProvInfo.pwszProvName = parameters.ProviderName; cryptKeyProvInfo.pwszContainerName = parameters.KeyContainerName; cryptKeyProvInfo.dwProvType = (uint)parameters.ProviderType; cryptKeyProvInfo.dwKeySpec = (uint)parameters.KeyNumber; cryptKeyProvInfo.dwFlags = (parameters.Flags & CspProviderFlags.UseMachineKeyStore) == CspProviderFlags.UseMachineKeyStore ? 32U : 0U; SafeLocalAllocHandle localAllocHandle1 = CAPI.LocalAlloc(64U, new IntPtr(Marshal.SizeOf(typeof(CAPI.CRYPT_KEY_PROV_INFO)))); Marshal.StructureToPtr((object)cryptKeyProvInfo, localAllocHandle1.DangerousGetHandle(), false); CAPI.CRYPT_ALGORITHM_IDENTIFIER algorithmIdentifier = new CAPI.CRYPT_ALGORITHM_IDENTIFIER(); algorithmIdentifier.pszObjId = "1.3.14.3.2.29"; SafeLocalAllocHandle localAllocHandle2 = CAPI.LocalAlloc(64U, new IntPtr(Marshal.SizeOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER)))); Marshal.StructureToPtr((object)algorithmIdentifier, localAllocHandle2.DangerousGetHandle(), false); X500DistinguishedName distinguishedName = new X500DistinguishedName("cn=CMS Signer Dummy Certificate"); System.Security.Cryptography.SafeCertContextHandle selfSignCertificate; fixed(byte *numPtr = distinguishedName.RawData) selfSignCertificate = CAPI.CAPIUnsafe.CertCreateSelfSignCertificate(hCryptProv, new IntPtr((void *)&new CAPI.CRYPTOAPI_BLOB() { cbData = (uint)distinguishedName.RawData.Length, pbData = new IntPtr((void *)numPtr) }), 1U, localAllocHandle1.DangerousGetHandle(), localAllocHandle2.DangerousGetHandle(), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); Marshal.DestroyStructure(localAllocHandle1.DangerousGetHandle(), typeof(CAPI.CRYPT_KEY_PROV_INFO)); localAllocHandle1.Dispose(); Marshal.DestroyStructure(localAllocHandle2.DangerousGetHandle(), typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER)); localAllocHandle2.Dispose(); if (selfSignCertificate == null || selfSignCertificate.IsInvalid) { throw new CryptographicException(Marshal.GetLastWin32Error()); } X509Certificate2 x509Certificate2 = new X509Certificate2(selfSignCertificate.DangerousGetHandle()); selfSignCertificate.Dispose(); return(x509Certificate2); }
internal static bool GetPrivateKeyInfo(SafeCertContextHandle safeCertContext, ref CspParameters parameters) { SafeLocalAllocHandle ptr = SafeLocalAllocHandle.InvalidHandle; uint cbData = 0; if (!CAPI.CAPISafe.CertGetCertificateContextProperty(safeCertContext, CAPI.CERT_KEY_PROV_INFO_PROP_ID, ptr, ref cbData)) { int dwErrorCode = Marshal.GetLastWin32Error(); if (dwErrorCode == CAPI.CRYPT_E_NOT_FOUND) { return(false); } else { throw new CryptographicException(Marshal.GetLastWin32Error()); } } ptr = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(cbData)); if (!CAPI.CAPISafe.CertGetCertificateContextProperty(safeCertContext, CAPI.CERT_KEY_PROV_INFO_PROP_ID, ptr, ref cbData)) { int dwErrorCode = Marshal.GetLastWin32Error(); if (dwErrorCode == CAPI.CRYPT_E_NOT_FOUND) { return(false); } else { throw new CryptographicException(Marshal.GetLastWin32Error()); } } CAPI.CRYPT_KEY_PROV_INFO pKeyProvInfo = (CAPI.CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(ptr.DangerousGetHandle(), typeof(CAPI.CRYPT_KEY_PROV_INFO)); parameters.ProviderName = pKeyProvInfo.pwszProvName; parameters.KeyContainerName = pKeyProvInfo.pwszContainerName; parameters.ProviderType = (int)pKeyProvInfo.dwProvType; parameters.KeyNumber = (int)pKeyProvInfo.dwKeySpec; parameters.Flags = (CspProviderFlags)((pKeyProvInfo.dwFlags & CAPI.CRYPT_MACHINE_KEYSET) == CAPI.CRYPT_MACHINE_KEYSET ? CspProviderFlags.UseMachineKeyStore : 0); ptr.Dispose(); return(true); }
internal static bool GetPrivateKeyInfo(System.Security.Cryptography.SafeCertContextHandle safeCertContext, ref CspParameters parameters) { SafeLocalAllocHandle invalidHandle = SafeLocalAllocHandle.InvalidHandle; uint pcbData = 0U; if (!CAPI.CAPISafe.CertGetCertificateContextProperty(safeCertContext, 2U, invalidHandle, out pcbData)) { if (Marshal.GetLastWin32Error() == -2146885628) { return(false); } else { throw new CryptographicException(Marshal.GetLastWin32Error()); } } else { SafeLocalAllocHandle pvData = CAPI.LocalAlloc(0U, new IntPtr((long)pcbData)); if (!CAPI.CAPISafe.CertGetCertificateContextProperty(safeCertContext, 2U, pvData, out pcbData)) { if (Marshal.GetLastWin32Error() == -2146885628) { return(false); } else { throw new CryptographicException(Marshal.GetLastWin32Error()); } } else { CAPI.CRYPT_KEY_PROV_INFO cryptKeyProvInfo = (CAPI.CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(pvData.DangerousGetHandle(), typeof(CAPI.CRYPT_KEY_PROV_INFO)); parameters.ProviderName = cryptKeyProvInfo.pwszProvName; parameters.KeyContainerName = cryptKeyProvInfo.pwszContainerName; parameters.ProviderType = (int)cryptKeyProvInfo.dwProvType; parameters.KeyNumber = (int)cryptKeyProvInfo.dwKeySpec; parameters.Flags = ((int)cryptKeyProvInfo.dwFlags & 32) == 32 ? CspProviderFlags.UseMachineKeyStore : CspProviderFlags.NoFlags; pvData.Dispose(); return(true); } } }
/// <summary> /// If the certificate has private key, this cert can be used for signing, if it does not, /// try to access private key stored in the CSP, if CSP provider or key container name /// is not provided, certificate can't be used for signing. /// </summary> /// <param name="certificate">Certificate</param> /// <param name="cryptoProviderName">Crypto provider name</param> /// <param name="keyContainerName">Key container name</param> /// <param name="providerType">Provider type</param> /// <returns></returns> public static bool SetPrivateKeyIfNeeded(X509Certificate2 certificate, string cryptoProviderName, string keyContainerName, int providerType = -1) { if (Certificate.HasPrivateKey(certificate)) { // We got a .pfx file. // Silently ignore CSP name or key container if either was provided with a .pfx fle. return(true); } // If provider and key container names are specified, try to access private key. if (cryptoProviderName != null && keyContainerName != null) { try { bool result = true; if (providerType == PROV_UNINITIALIZED) { providerType = Certificate.GetCspType(cryptoProviderName); } if (providerType == PROV_UNINITIALIZED) { return(false); } // The following code will modify state of certificates from x509Store, // make sure to assign private keys only to certificates that were created from a .cer files if (providerType != 0) { CspParameters parameters; parameters = new CspParameters { ProviderName = cryptoProviderName, ProviderType = providerType, KeyContainerName = keyContainerName, KeyNumber = (int)KeyNumber.Signature, // Make sure key creation is not attempted. Flags = CspProviderFlags.UseExistingKey }; if (IsMachineCryptKey(cryptoProviderName, (uint)providerType, keyContainerName)) { // Search only Machine key store for this private key, if not set we search only user store. parameters.Flags |= CspProviderFlags.UseMachineKeyStore; } certificate.PrivateKey = new RSACryptoServiceProvider(parameters); } else { CAPI.CRYPT_KEY_PROV_INFO keyProvInfo = new CAPI.CRYPT_KEY_PROV_INFO { pwszProvName = cryptoProviderName, pwszContainerName = keyContainerName, dwProvType = (uint)providerType, dwKeySpec = (int)KeyNumber.Signature, dwFlags = IsMachineNCryptKey(cryptoProviderName, keyContainerName) ? NCryptMethods.NCRYPT_MACHINE_KEY_FLAG : (uint)0 }; using (SafeLocalAllocHandle pKeyProvInfo = CAPI.LocalAlloc(CAPI.LPTR, (uint)Marshal.SizeOf(typeof(CAPI.CRYPT_KEY_PROV_INFO)))) { Marshal.StructureToPtr(keyProvInfo, pKeyProvInfo.DangerousGetHandle(), false); result = CAPI.CertSetKeyProviderInfoProperty(certificate.Handle, pKeyProvInfo); Marshal.DestroyStructure(pKeyProvInfo.DangerousGetHandle(), typeof(CAPI.CRYPT_KEY_PROV_INFO)); } } return(result); } catch (Exception e) { if (Misc.IsCriticalException(e)) { throw; } // Caller displays an error message. System.Diagnostics.Debug.WriteLine(e.Message); } } return(false); }