Example #1
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));
                    }
                }
            }
        }
Example #2
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);
                }
            }
        }
 public unsafe X509Certificate2 GenerateCertificate(X509Certificate2 issuingCertificate, PrivateKey privateKey, X500DistinguishedName dn, string[] dnsNames, 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);
     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 signatureAlgorithm = new CRYPT_ALGORITHM_IDENTIFIER
             {
                 pszObjId = issuingCertificate.SignatureAlgorithm.Value
             };
             using (var signingKey = ExtractKey(issuingCertificate))
             {
                 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), 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 = signatureAlgorithm;
                         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, KeySpec.NONE, EncodingType.X509_ASN_ENCODING, CERT_INFO_TYPE, ref certInfo, ref signatureAlgorithm, IntPtr.Zero, IntPtr.Zero, ref size))
                         {
                             throw new Win32Exception(Marshal.GetLastWin32Error());
                         }
                         var buffer = Marshal.AllocHGlobal((int) size);
                         if (!Crypt32.CryptSignAndEncodeCertificate(signingKey.Handle, KeySpec.NONE, EncodingType.X509_ASN_ENCODING, CERT_INFO_TYPE, ref certInfo, ref signatureAlgorithm, 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.Handle.IsNCryptKey ? KeySpec.NONE : KeySpec.AT_KEYEXCHANGE,
                             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);
         }
     }
 }
 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.Handle.IsNCryptKey ? KeySpec.NONE : KeySpec.AT_KEYEXCHANGE,
                     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);
             }
         }
     }
 }
 public Freezer(MarshalX509ExtensionCollection collection)
 {
     _collection         = collection;
     _collection._frozen = true;
 }
 public Freezer(MarshalX509ExtensionCollection collection)
 {
     _collection = collection;
     _collection._frozen = true;
 }