示例#1
0
        /// <summary>
        /// Take an existing certificate, clone its details and resign with a new root CA
        /// </summary>
        /// <param name="toClone">The certificate to clone</param>
        /// <param name="rootCert">The root CA certificate to sign with</param>
        /// <param name="newSerial">True to generate a new serial for this certificate</param>
        /// <param name="rsaKeySize">The size of the RSA key to generate</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns></returns>
        public static X509Certificate2 CloneAndSignCertificate(X509Certificate toClone, X509Certificate2 rootCert, bool newSerial, int rsaKeySize, CertificateHashAlgorithm hashAlgorithm)
        {
            X509Certificate2 cert2 = new X509Certificate2(toClone);
            X509ExtensionCollection extensions = new X509ExtensionCollection();

            foreach (var ext in cert2.Extensions)
            {
                // Remove CRL distribution locations and authority information, they tend to break SSL negotiation
                if ((ext.Oid.Value != szOID_CRL_DISTRIBUTION) && (ext.Oid.Value != szOID_AUTHORITY_INFO))
                {
                    extensions.Add(ext);
                }
            }

            return builder.CreateCert(rootCert, cert2.SubjectName, newSerial ? null : cert2.GetSerialNumber(),
                false, rsaKeySize, hashAlgorithm, cert2.NotBefore, cert2.NotAfter, extensions);
        }
示例#2
0
        private static string HashAlgorithmToOID(CertificateHashAlgorithm hashAlgorithm)
        {
            switch (hashAlgorithm)
            {
            case CertificateHashAlgorithm.Sha1:
                return(CryptoApiMethods.szOID_RSA_SHA1RSA);

            case CertificateHashAlgorithm.Sha256:
                return(CryptoApiMethods.szOID_RSA_SHA256RSA);

            case CertificateHashAlgorithm.Sha384:
                return(CryptoApiMethods.szOID_RSA_SHA384RSA);

            case CertificateHashAlgorithm.Sha512:
                return(CryptoApiMethods.szOID_RSA_SHA512RSA);

            case CertificateHashAlgorithm.Md5:
                return(CryptoApiMethods.szOID_RSA_MD5RSA);

            default:
                throw new ArgumentException(Properties.Resources.NativeCertificateBuilder_InvalidHashAlgorithm, "hashAlgorithm");
            }
        }
        private static string HashAlgorithmToName(CertificateHashAlgorithm hashAlgorithm)
        {
            switch (hashAlgorithm)
            {
            case CertificateHashAlgorithm.Sha1:
                return("SHA1WITHRSA");

            case CertificateHashAlgorithm.Sha256:
                return("SHA256WITHRSA");

            case CertificateHashAlgorithm.Sha384:
                return("SHA384WITHRSA");

            case CertificateHashAlgorithm.Sha512:
                return("SHA512WITHRSA");

            case CertificateHashAlgorithm.Md5:
                return("MD5WITHRSA");

            default:
                throw new ArgumentException("hashAlgorithm");
            }
        }
示例#4
0
        private static string HashAlgorithmToName(CertificateHashAlgorithm hashAlgorithm)
        {
            switch (hashAlgorithm)
            {
            case CertificateHashAlgorithm.Sha1:
                return("SHA1WITHRSA");

            case CertificateHashAlgorithm.Sha256:
                return("SHA256WITHRSA");

            case CertificateHashAlgorithm.Sha384:
                return("SHA384WITHRSA");

            case CertificateHashAlgorithm.Sha512:
                return("SHA512WITHRSA");

            case CertificateHashAlgorithm.Md5:
                return("MD5WITHRSA");

            default:
                throw new ArgumentException(Properties.Resources.NativeCertificateBuilder_InvalidHashAlgorithm, "hashAlgorithm");
            }
        }
示例#5
0
 /// <summary>
 /// Create a new certificate
 /// </summary>
 /// <param name="issuer">Issuer certificate, if null then self-sign</param>
 /// <param name="subjectName">Subject name</param>
 /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
 /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
 /// <param name="keySize">Size of RSA key</param>
 /// <param name="hashAlgorithm">The hash algorithm for the certificate</param>
 /// <param name="notBefore">Start date of certificate</param>
 /// <param name="notAfter">End date of certificate</param>
 /// <param name="extensions">Array of extensions, if null then no extensions</param>
 /// <returns>The created X509 certificate</returns>
 public static X509Certificate2 CreateCert(X509Certificate2 issuer, X500DistinguishedName subjectName,
                                           byte[] serialNumber, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, X509ExtensionCollection extensions)
 {
     return(CertificateBuilder.CreateCert(issuer, subjectName, serialNumber, keySize, hashAlgorithm, notBefore, notAfter, extensions));
 }
示例#6
0
        /// <summary>
        /// Generate a self-signed CA certificate
        /// </summary>
        /// <param name="subject">The X500 subject string</param>
        /// <param name="rsaKeySize">The size of the RSA key to generate</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>An X509Certificate2 object containing the full certificate</returns>
        public static X509Certificate2 GenerateCACert(string subject, int rsaKeySize, CertificateHashAlgorithm hashAlgorithm)
        {
            X509ExtensionCollection exts = new X509ExtensionCollection();
            DateTime dt = DateTime.Now.AddYears(-1);

            exts.Add(new X509BasicConstraintsExtension(true, false, 0, false));

            return(CertificateBuilder.CreateCert(null, new X500DistinguishedName(subject),
                                                 null, rsaKeySize, hashAlgorithm, dt, dt.AddYears(10), exts));
        }
示例#7
0
        /// <summary>
        /// Take an existing certificate, clone its details and resign with a new root CA
        /// </summary>
        /// <param name="toClone">The certificate to clone</param>
        /// <param name="rootCert">The root CA certificate to sign with</param>
        /// <param name="newSerial">True to generate a new serial for this certificate</param>
        /// <param name="rsaKeySize">The size of the RSA key to generate</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns></returns>
        public static X509Certificate2 CloneAndSignCertificate(X509Certificate toClone, X509Certificate2 rootCert, bool newSerial, int rsaKeySize, CertificateHashAlgorithm hashAlgorithm)
        {
            X509Certificate2        cert2      = new X509Certificate2(toClone.Export(X509ContentType.Cert));
            X509ExtensionCollection extensions = new X509ExtensionCollection();

            foreach (var ext in cert2.Extensions)
            {
                // Remove CRL distribution locations and authority information, they tend to break SSL negotiation
                if ((ext.Oid.Value != szOID_CRL_DISTRIBUTION) && (ext.Oid.Value != szOID_AUTHORITY_INFO))
                {
                    extensions.Add(ext);
                }
            }

            return(CertificateBuilder.CreateCert(rootCert, cert2.SubjectName, newSerial ? null : cert2.GetSerialNumber(),
                                                 rsaKeySize, hashAlgorithm, cert2.NotBefore, cert2.NotAfter, extensions));
        }
示例#8
0
        /// <summary>
        /// Create a new certificate
        /// </summary>
        /// <param name="issuer">Issuer certificate, if null then self-sign</param>
        /// <param name="subjectName">Subject name</param>
        /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
        /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="keySize">Size of RSA key</param>
        /// <param name="notBefore">Start date of certificate</param>
        /// <param name="notAfter">End date of certificate</param>
        /// <param name="extensions">Array of extensions, if null then no extensions</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>The created X509 certificate</returns>
        public SystemX509.X509Certificate2 CreateCert(SystemX509.X509Certificate2 issuer, SystemX509.X500DistinguishedName subjectName,
                                                      byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore,
                                                      DateTime notAfter, SystemX509.X509ExtensionCollection extensions)
        {
            X509V3CertificateGenerator builder    = new X509V3CertificateGenerator();
            AsymmetricAlgorithm        subjectKey = CreateRSAKey(keySize, signature);
            AsymmetricAlgorithm        signKey    = issuer == null ? subjectKey : issuer.PrivateKey;

            if (signKey == null)
            {
                throw new ArgumentException(Properties.Resources.CreateCert_NoPrivateKey);
            }

            AsymmetricCipherKeyPair bcSubjectKey = GetRsaKeyPair((RSACryptoServiceProvider)subjectKey);
            AsymmetricCipherKeyPair bcSignKey    = GetRsaKeyPair((RSACryptoServiceProvider)signKey);

            X509Name issuerNameObj = issuer == null?X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData))
                                         : X509Name.GetInstance(Asn1Object.FromByteArray(issuer.SubjectName.RawData));

            X509Name subjectNameObj = X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData));

            BigInteger subjectSerial = new BigInteger(1, serialNumber != null ? serialNumber : Guid.NewGuid().ToByteArray());
            BigInteger issuerSerial  = issuer == null ? subjectSerial : new BigInteger(1, issuer.GetSerialNumber());

            builder.SetIssuerDN(issuerNameObj);
            builder.SetSubjectDN(subjectNameObj);
            builder.SetSerialNumber(subjectSerial);
            builder.SetSignatureAlgorithm(HashAlgorithmToName(hashAlgorithm));
            builder.SetNotBefore(notBefore.ToUniversalTime());
            builder.SetNotAfter(notAfter.ToUniversalTime());
            builder.SetPublicKey(bcSubjectKey.Public);

            SubjectPublicKeyInfo   info         = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSignKey.Public);
            AuthorityKeyIdentifier authKeyId    = new AuthorityKeyIdentifier(info, new GeneralNames(new GeneralName(issuerNameObj)), issuerSerial);
            SubjectKeyIdentifier   subjectKeyid = new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSubjectKey.Public));

            builder.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, true, authKeyId);
            builder.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, true, subjectKeyid);

            if (extensions != null)
            {
                foreach (SystemX509.X509Extension ext in extensions)
                {
                    if (!ext.Oid.Value.Equals(X509Extensions.AuthorityKeyIdentifier.Id) &&
                        !ext.Oid.Value.Equals(X509Extensions.SubjectKeyIdentifier.Id) &&
                        !ext.Oid.Value.Equals(szOID_AUTHORITY_KEY_IDENTIFIER2))
                    {
                        Asn1InputStream istm = new Org.BouncyCastle.Asn1.Asn1InputStream(ext.RawData);
                        Asn1Object      obj  = istm.ReadObject();
                        builder.AddExtension(ext.Oid.Value, ext.Critical, obj);
                    }
                }
            }

            X509Certificate cert = builder.Generate(bcSignKey.Private);

            SystemX509.X509Certificate2 ret = new SystemX509.X509Certificate2(cert.GetEncoded(), (string)null, SystemX509.X509KeyStorageFlags.Exportable);

            ret.PrivateKey = subjectKey;

            return(ret);
        }
        private static string HashAlgorithmToOID(CertificateHashAlgorithm hashAlgorithm)
        {
            switch (hashAlgorithm)
            {

                case CertificateHashAlgorithm.Sha1:
                    return CryptoApiMethods.szOID_RSA_SHA1RSA;
                case CertificateHashAlgorithm.Sha256:
                    return CryptoApiMethods.szOID_RSA_SHA256RSA;
                case CertificateHashAlgorithm.Sha384:
                    return CryptoApiMethods.szOID_RSA_SHA384RSA;
                case CertificateHashAlgorithm.Sha512:
                    return CryptoApiMethods.szOID_RSA_SHA512RSA;
                case CertificateHashAlgorithm.Md5:
                    return CryptoApiMethods.szOID_RSA_MD5RSA;
                default:
                    throw new ArgumentException(Properties.Resources.NativeCertificateBuilder_InvalidHashAlgorithm, "hashAlgorithm");
            }
        }
示例#10
0
        /// <summary>
        /// Create a new certificate
        /// </summary>
        /// <param name="issuer">Issuer certificate, if null then self-sign</param>
        /// <param name="subjectName">Subject name</param>
        /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
        /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="keySize">Size of RSA key</param>
        /// <param name="notBefore">Start date of certificate</param>
        /// <param name="notAfter">End date of certificate</param>
        /// <param name="extensions">Array of extensions, if null then no extensions</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>The created X509 certificate</returns>
        public SystemX509.X509Certificate2 CreateCert(SystemX509.X509Certificate2 issuer, SystemX509.X500DistinguishedName subjectName,
            byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore,
            DateTime notAfter, SystemX509.X509ExtensionCollection extensions)
        {
            X509V3CertificateGenerator builder = new X509V3CertificateGenerator();
            AsymmetricAlgorithm subjectKey = CreateRSAKey(keySize, signature);
            AsymmetricAlgorithm signKey = issuer == null ? subjectKey : issuer.PrivateKey;

            if (signKey == null)
            {
                throw new ArgumentException(Properties.Resources.CreateCert_NoPrivateKey);
            }

            AsymmetricCipherKeyPair bcSubjectKey = GetRsaKeyPair((RSACryptoServiceProvider)subjectKey);
            AsymmetricCipherKeyPair bcSignKey = GetRsaKeyPair((RSACryptoServiceProvider)signKey);

            X509Name issuerNameObj = issuer == null ? X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData))
                : X509Name.GetInstance(Asn1Object.FromByteArray(issuer.SubjectName.RawData));
            X509Name subjectNameObj = X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData));

            BigInteger subjectSerial = new BigInteger(1, serialNumber != null ? serialNumber : Guid.NewGuid().ToByteArray());
            BigInteger issuerSerial = issuer == null ? subjectSerial : new BigInteger(1, issuer.GetSerialNumber());

            builder.SetIssuerDN(issuerNameObj);
            builder.SetSubjectDN(subjectNameObj);
            builder.SetSerialNumber(subjectSerial);
            builder.SetSignatureAlgorithm(HashAlgorithmToName(hashAlgorithm));
            builder.SetNotBefore(notBefore.ToUniversalTime());
            builder.SetNotAfter(notAfter.ToUniversalTime());
            builder.SetPublicKey(bcSubjectKey.Public);

            SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSignKey.Public);
            AuthorityKeyIdentifier authKeyId = new AuthorityKeyIdentifier(info, new GeneralNames(new GeneralName(issuerNameObj)), issuerSerial);
            SubjectKeyIdentifier subjectKeyid = new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSubjectKey.Public));

            builder.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, true, authKeyId);
            builder.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, true, subjectKeyid);

            if (extensions != null)
            {
                foreach (SystemX509.X509Extension ext in extensions)
                {
                    if (!ext.Oid.Value.Equals(X509Extensions.AuthorityKeyIdentifier.Id)
                        && !ext.Oid.Value.Equals(X509Extensions.SubjectKeyIdentifier.Id)
                        && !ext.Oid.Value.Equals(szOID_AUTHORITY_KEY_IDENTIFIER2))
                    {
                        Asn1InputStream istm = new Org.BouncyCastle.Asn1.Asn1InputStream(ext.RawData);
                        Asn1Object obj = istm.ReadObject();
                        builder.AddExtension(ext.Oid.Value, ext.Critical, obj);
                    }
                }
            }

            X509Certificate cert = builder.Generate(bcSignKey.Private);

            SystemX509.X509Certificate2 ret = new SystemX509.X509Certificate2(cert.GetEncoded(), (string)null, SystemX509.X509KeyStorageFlags.Exportable);

            ret.PrivateKey = subjectKey;

            return ret;
        }
 private static ISignatureFactory CreateSignatureFactory(CertificateHashAlgorithm hash_algorithm, AsymmetricCipherKeyPair key, SecureRandom random)
 {
     return(new Asn1SignatureFactory(HashAlgorithmToName(hash_algorithm), key.Private, random));
 }
示例#12
0
        /// <summary>
        /// Generate a self-signed CA certificate
        /// </summary>
        /// <param name="subject">The X500 subject string</param>
        /// <param name="rsaKeySize">The size of the RSA key to generate</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>An X509Certificate2 object containing the full certificate</returns>
        public static X509Certificate2 GenerateCACert(string subject, int rsaKeySize, CertificateHashAlgorithm hashAlgorithm)
        {
            X509ExtensionCollection exts = new X509ExtensionCollection();
            DateTime dt = DateTime.Now.AddYears(-1);

            exts.Add(new X509BasicConstraintsExtension(true, false, 0, false));

            return builder.CreateCert(null, new X500DistinguishedName(subject), null, false, rsaKeySize, hashAlgorithm, dt, dt.AddYears(10), exts);
        }
示例#13
0
        /// <summary>
        /// Encode and sign a CERT_INFO structure
        /// </summary>
        /// <param name="key">Key to sign the certificate with</param>
        /// <param name="certInfo">The CERT_INFO structure to sign</param>
        /// <param name="hashAlgorithm"></param>
        /// <returns></returns>
        private byte[] EncodeAndSignCertInfo(RSACryptoServiceProvider key, CryptoApiMethods.CERT_INFO certInfo, CertificateHashAlgorithm hashAlgorithm)
        {
            byte[] ret = null;
            CryptoApiMethods.SafeCryptProviderHandle hProv = new CryptoApiMethods.SafeCryptProviderHandle();

            try
            {
                hProv = OpenRSAProvider(key.CspKeyContainerInfo.ProviderName, key.CspKeyContainerInfo.KeyContainerName);

                ret = EncodeAndSignCertInfo(hProv, certInfo, key.CspKeyContainerInfo.KeyNumber == KeyNumber.Signature ? true : false, hashAlgorithm);
            }
            finally
            {
                if (!hProv.IsInvalid)
                {
                    hProv.Close();
                }
            }

            return(ret);
        }
示例#14
0
        /// <summary>
        /// Encode and sign a CERT_INFO structure
        /// </summary>
        /// <param name="hProv"></param>
        /// <param name="certInfo"></param>
        /// <param name="signature">True encodes with a AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="hashAlgorithm"></param>
        /// <returns></returns>
        private byte[] EncodeAndSignCertInfo(CryptoApiMethods.SafeCryptProviderHandle hProv, CryptoApiMethods.CERT_INFO certInfo, bool signature, CertificateHashAlgorithm hashAlgorithm)
        {
            CryptoApiMethods.CALG keyType = signature ? CryptoApiMethods.CALG.AT_SIGNATURE : CryptoApiMethods.CALG.AT_KEYEXCHANGE;
            byte[] ret         = null;
            uint   certLen     = 0;
            IntPtr certInfoPtr = IntPtr.Zero;

            CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER();
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign;
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA;
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA;
            SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm);

            try
            {
                certInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(certInfo));
                Marshal.StructureToPtr(certInfo, certInfoPtr, false);

                if (!CryptoApiMethods.CryptSignAndEncodeCertificate(hProv, keyType, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                                    new IntPtr((int)CryptoApiMethods.StructType.X509_CERT_TO_BE_SIGNED), certInfoPtr, SignatureAlgorithm, IntPtr.Zero, null, ref certLen))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                ret = new byte[certLen];

                if (!CryptoApiMethods.CryptSignAndEncodeCertificate(hProv, keyType, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                                                                    new IntPtr((int)CryptoApiMethods.StructType.X509_CERT_TO_BE_SIGNED), certInfoPtr, SignatureAlgorithm, IntPtr.Zero, ret, ref certLen))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                Marshal.DestroyStructure(certInfoPtr, certInfo.GetType());
                Marshal.FreeHGlobal(certInfoPtr);
            }

            return(ret);
        }
示例#15
0
        /// <summary>
        /// Create a new certificate
        /// </summary>
        /// <param name="issuer">Issuer certificate, if null then self-sign</param>
        /// <param name="subjectName">Subject name</param>
        /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
        /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="keySize">Size of RSA key</param>
        /// <param name="notBefore">Start date of certificate</param>
        /// <param name="notAfter">End date of certificate</param>
        /// <param name="extensions">Array of extensions, if null then no extensions</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>The created X509 certificate</returns>
        public X509Certificate2 CreateCert(X509Certificate2 issuer, X500DistinguishedName subjectName, byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, X509ExtensionCollection extensions)
        {
            CryptoApiMethods.CERT_INFO certInfo = new CryptoApiMethods.CERT_INFO();
            RSACryptoServiceProvider key = CreateRSAKey(keySize, signature);
            IntPtr publicKeyInfoPtr = IntPtr.Zero;
            X509Certificate2 cert = null;
            List<X509Extension> newExts = null;

            if (extensions != null)
            {
                foreach (X509Extension ext in extensions)
                {
                    if (ext.RawData == null)
                    {
                        throw new ArgumentException(Properties.Resources.CreateCert_NeedEncodedData);
                    }
                }
            }

            try
            {
                if (serialNumber == null)
                {
                    serialNumber = Guid.NewGuid().ToByteArray();
                }

                certInfo.dwVersion = (uint)CryptoApiMethods.CertVersion.CERT_V3;
                certInfo.SerialNumber = new CryptoApiMethods.CRYPTOAPI_BLOB(serialNumber);
                certInfo.Subject = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData);

                if (issuer == null)
                {
                    // Self-signed
                    certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData);
                }
                else
                {
                    certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(issuer.SubjectName.RawData);
                }

                // Never seems to need these set to anything valid?
                certInfo.SubjectUniqueId = new CryptoApiMethods.CRYPT_BIT_BLOB();
                certInfo.IssuerUniqueId = new CryptoApiMethods.CRYPT_BIT_BLOB();

                certInfo.NotBefore = DateTimeToFileTime(notBefore);
                certInfo.NotAfter = DateTimeToFileTime(notAfter);

                certInfo.SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER();
                // Doesn't seem to work properly with standard szOID_RSA_SHA1RSA
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign;
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA;
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA;
                certInfo.SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm);

                // Add extension fields
                publicKeyInfoPtr = ExportPublicKeyInfo(key);
                certInfo.SubjectPublicKeyInfo = (CryptoApiMethods.CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(publicKeyInfoPtr, typeof(CryptoApiMethods.CERT_PUBLIC_KEY_INFO));

                newExts = new List<X509Extension>();

                if (extensions != null)
                {
                    // Filter out some extensions we don't want
                    newExts.AddRange(
                        extensions.Cast<X509Extension>().Where(
                        x =>
                           !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER)
                        && !x.Oid.Value.Equals(CryptoApiMethods.szOID_SUBJECT_KEY_IDENTIFIER)
                        && !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER2)));
                }

                if (issuer != null)
                {
                    newExts.Add(CreateAuthorityKeyInfo2(issuer.GetSerialNumber(), issuer.SubjectName, (RSACryptoServiceProvider)issuer.PrivateKey));
                }
                else
                {
                    newExts.Add(CreateAuthorityKeyInfo2(serialNumber, subjectName, key));
                }

                newExts.Add(new X509SubjectKeyIdentifierExtension(HashPublicKeyInfo(key), false));

                certInfo.rgExtension = MarshalExtensions(newExts.ToArray());
                certInfo.cExtension = (uint)newExts.Count;

                byte[] certData = EncodeAndSignCertInfo(issuer != null ? issuer.PrivateKey as RSACryptoServiceProvider : key, certInfo, hashAlgorithm);

                cert = new X509Certificate2(certData, (string)null, X509KeyStorageFlags.Exportable);
                cert.PrivateKey = key;
            }
            finally
            {
                if (certInfo.rgExtension != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(certInfo.rgExtension);
                }

                if (certInfo.Subject != null)
                {
                    certInfo.Subject.Release();
                }

                if (certInfo.Issuer != null)
                {
                    certInfo.Issuer.Release();
                }

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

            return cert;
        }
示例#16
0
        /// <summary>
        /// Encode and sign a CERT_INFO structure
        /// </summary>
        /// <param name="hProv"></param>
        /// <param name="certInfo"></param>
        /// <param name="signature">True encodes with a AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="hashAlgorithm"></param>
        /// <returns></returns>
        private byte[] EncodeAndSignCertInfo(CryptoApiMethods.SafeCryptProviderHandle hProv, CryptoApiMethods.CERT_INFO certInfo, bool signature, CertificateHashAlgorithm hashAlgorithm)
        {
            CryptoApiMethods.CALG keyType = signature ? CryptoApiMethods.CALG.AT_SIGNATURE : CryptoApiMethods.CALG.AT_KEYEXCHANGE;
            byte[] ret = null;
            uint certLen = 0;
            IntPtr certInfoPtr = IntPtr.Zero;
            CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER();
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign;
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA;
            //SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA;
            SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm);

            try
            {
                certInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(certInfo));
                Marshal.StructureToPtr(certInfo, certInfoPtr, false);

                if (!CryptoApiMethods.CryptSignAndEncodeCertificate(hProv, keyType, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                    new IntPtr((int)CryptoApiMethods.StructType.X509_CERT_TO_BE_SIGNED), certInfoPtr, SignatureAlgorithm, IntPtr.Zero, null, ref certLen))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                ret = new byte[certLen];

                if (!CryptoApiMethods.CryptSignAndEncodeCertificate(hProv, keyType, CryptoApiMethods.CertEncoding.X509_ASN_ENCODING,
                    new IntPtr((int)CryptoApiMethods.StructType.X509_CERT_TO_BE_SIGNED), certInfoPtr, SignatureAlgorithm, IntPtr.Zero, ret, ref certLen))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                Marshal.DestroyStructure(certInfoPtr, certInfo.GetType());
                Marshal.FreeHGlobal(certInfoPtr);
            }

            return ret;
        }
示例#17
0
        /// <summary>
        /// Encode and sign a CERT_INFO structure
        /// </summary>
        /// <param name="key">Key to sign the certificate with</param>
        /// <param name="certInfo">The CERT_INFO structure to sign</param>
        /// <param name="hashAlgorithm"></param>
        /// <returns></returns>
        private byte[] EncodeAndSignCertInfo(RSACryptoServiceProvider key, CryptoApiMethods.CERT_INFO certInfo, CertificateHashAlgorithm hashAlgorithm)
        {
            byte[] ret = null;
            CryptoApiMethods.SafeCryptProviderHandle hProv = new CryptoApiMethods.SafeCryptProviderHandle();

            try
            {
                hProv = OpenRSAProvider(key.CspKeyContainerInfo.ProviderName, key.CspKeyContainerInfo.KeyContainerName);

                ret = EncodeAndSignCertInfo(hProv, certInfo, key.CspKeyContainerInfo.KeyNumber == KeyNumber.Signature ? true : false, hashAlgorithm);
            }
            finally
            {
                if (!hProv.IsInvalid)
                {
                    hProv.Close();
                }
            }

            return ret;
        }
示例#18
0
        /// <summary>
        /// Generate a self signed certificate including a private key
        /// </summary>
        /// <param name="subject">The X500 subject string</param>
        /// <param name="rsaKeySize">Specify the RSA key size in bits</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>An X509Certificate2 object containing the full certificate</returns>
        public static X509Certificate2 GenerateSelfSignedCert(string subject, int rsaKeySize, CertificateHashAlgorithm hashAlgorithm)
        {
            DateTime dt = DateTime.Now;

            return(CertificateBuilder.CreateCert(null, new X500DistinguishedName(subject), null, rsaKeySize, hashAlgorithm, dt, dt.AddYears(10), null));
        }
示例#19
0
        private static string HashAlgorithmToName(CertificateHashAlgorithm hashAlgorithm)
        {
            switch (hashAlgorithm)
            {

                case CertificateHashAlgorithm.Sha1:
                    return "SHA1WITHRSA";
                case CertificateHashAlgorithm.Sha256:
                    return "SHA256WITHRSA";
                case CertificateHashAlgorithm.Sha384:
                    return "SHA384WITHRSA";
                case CertificateHashAlgorithm.Sha512:
                    return "SHA512WITHRSA";
                case CertificateHashAlgorithm.Md5:
                    return "MD5WITHRSA";
                default:
                    throw new ArgumentException(Properties.Resources.NativeCertificateBuilder_InvalidHashAlgorithm, "hashAlgorithm");
            }
        }
示例#20
0
        /// <summary>
        /// Create a new certificate
        /// </summary>
        /// <param name="issuer">Issuer certificate, if null then self-sign</param>
        /// <param name="subjectName">Subject name</param>
        /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
        /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="keySize">Size of RSA key</param>
        /// <param name="notBefore">Start date of certificate</param>
        /// <param name="notAfter">End date of certificate</param>
        /// <param name="extensions">Array of extensions, if null then no extensions</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>The created X509 certificate</returns>
        public X509Certificate2 CreateCert(X509Certificate2 issuer, X500DistinguishedName subjectName, byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, X509ExtensionCollection extensions)
        {
            CryptoApiMethods.CERT_INFO certInfo   = new CryptoApiMethods.CERT_INFO();
            RSACryptoServiceProvider   key        = CreateRSAKey(keySize, signature);
            IntPtr               publicKeyInfoPtr = IntPtr.Zero;
            X509Certificate2     cert             = null;
            List <X509Extension> newExts          = null;

            if (extensions != null)
            {
                foreach (X509Extension ext in extensions)
                {
                    if (ext.RawData == null)
                    {
                        throw new ArgumentException(Properties.Resources.CreateCert_NeedEncodedData);
                    }
                }
            }

            try
            {
                if (serialNumber == null)
                {
                    serialNumber = Guid.NewGuid().ToByteArray();
                }

                certInfo.dwVersion    = (uint)CryptoApiMethods.CertVersion.CERT_V3;
                certInfo.SerialNumber = new CryptoApiMethods.CRYPTOAPI_BLOB(serialNumber);
                certInfo.Subject      = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData);

                if (issuer == null)
                {
                    // Self-signed
                    certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(subjectName.RawData);
                }
                else
                {
                    certInfo.Issuer = new CryptoApiMethods.CRYPTOAPI_BLOB(issuer.SubjectName.RawData);
                }

                // Never seems to need these set to anything valid?
                certInfo.SubjectUniqueId = new CryptoApiMethods.CRYPT_BIT_BLOB();
                certInfo.IssuerUniqueId  = new CryptoApiMethods.CRYPT_BIT_BLOB();

                certInfo.NotBefore = DateTimeToFileTime(notBefore);
                certInfo.NotAfter  = DateTimeToFileTime(notAfter);

                certInfo.SignatureAlgorithm = new CryptoApiMethods.CRYPT_ALGORITHM_IDENTIFIER();
                // Doesn't seem to work properly with standard szOID_RSA_SHA1RSA
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_OIWSEC_sha1RSASign;
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA1RSA;
                //certInfo.SignatureAlgorithm.pszObjId = CryptoApiMethods.szOID_RSA_SHA512RSA;
                certInfo.SignatureAlgorithm.pszObjId = HashAlgorithmToOID(hashAlgorithm);

                // Add extension fields
                publicKeyInfoPtr = ExportPublicKeyInfo(key);
                certInfo.SubjectPublicKeyInfo = (CryptoApiMethods.CERT_PUBLIC_KEY_INFO)Marshal.PtrToStructure(publicKeyInfoPtr, typeof(CryptoApiMethods.CERT_PUBLIC_KEY_INFO));

                newExts = new List <X509Extension>();

                if (extensions != null)
                {
                    // Filter out some extensions we don't want
                    newExts.AddRange(
                        extensions.Cast <X509Extension>().Where(
                            x =>
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER) &&
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_SUBJECT_KEY_IDENTIFIER) &&
                            !x.Oid.Value.Equals(CryptoApiMethods.szOID_AUTHORITY_KEY_IDENTIFIER2)));
                }

                if (issuer != null)
                {
                    newExts.Add(CreateAuthorityKeyInfo2(issuer.GetSerialNumber(), issuer.SubjectName, (RSACryptoServiceProvider)issuer.PrivateKey));
                }
                else
                {
                    newExts.Add(CreateAuthorityKeyInfo2(serialNumber, subjectName, key));
                }

                newExts.Add(new X509SubjectKeyIdentifierExtension(HashPublicKeyInfo(key), false));

                certInfo.rgExtension = MarshalExtensions(newExts.ToArray());
                certInfo.cExtension  = (uint)newExts.Count;

                byte[] certData = EncodeAndSignCertInfo(issuer != null ? issuer.PrivateKey as RSACryptoServiceProvider : key, certInfo, hashAlgorithm);

                cert            = new X509Certificate2(certData, (string)null, X509KeyStorageFlags.Exportable);
                cert.PrivateKey = key;
            }
            finally
            {
                if (certInfo.rgExtension != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(certInfo.rgExtension);
                }

                if (certInfo.Subject != null)
                {
                    certInfo.Subject.Release();
                }

                if (certInfo.Issuer != null)
                {
                    certInfo.Issuer.Release();
                }

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

            return(cert);
        }
示例#21
0
        /// <summary>
        /// Generate a self signed certificate including a private key
        /// </summary>
        /// <param name="subject">The X500 subject string</param>
        /// <param name="signature">True create a cert with an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
        /// <param name="rsaKeySize">Specify the RSA key size in bits</param>
        /// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        /// <returns>An X509Certificate2 object containing the full certificate</returns>
        public static X509Certificate2 GenerateSelfSignedCert(string subject, bool signature, int rsaKeySize, CertificateHashAlgorithm hashAlgorithm)
        {
            DateTime dt = DateTime.Now;

            return builder.CreateCert(null, new X500DistinguishedName(subject), null, signature, rsaKeySize, hashAlgorithm, dt, dt.AddYears(10), null);
        }
        ///// <summary>
        ///// Create a new certificate
        ///// </summary>
        ///// <param name="issuer">Issuer certificate, if null then self-sign</param>
        ///// <param name="subjectName">Subject name</param>
        ///// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
        ///// <param name="keySize">Size of RSA key</param>
        ///// <param name="notBefore">Start date of certificate</param>
        ///// <param name="notAfter">End date of certificate</param>
        ///// <param name="extensions">Array of extensions, if null then no extensions</param>
        ///// <param name="hashAlgorithm">Specify the signature hash algorithm</param>
        ///// <returns>The created X509 certificate</returns>
        public static SystemX509.X509Certificate2 CreateCert(SystemX509.X509Certificate2 issuer, SystemX509.X500DistinguishedName subjectName,
                                                             byte[] serialNumber, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore,
                                                             DateTime notAfter, SystemX509.X509ExtensionCollection extensions)
        {
            SecureRandom random = new SecureRandom();
            X509V3CertificateGenerator builder      = new X509V3CertificateGenerator();
            AsymmetricCipherKeyPair    bcSubjectKey = CreateRSAKey(keySize, random);
            AsymmetricCipherKeyPair    bcSignKey    = issuer == null ? bcSubjectKey : issuer.GetBCPrivateKey();

            if (bcSignKey == null)
            {
                throw new ArgumentException("issuer");
            }

            X509Name issuerNameObj = issuer == null?X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData))
                                         : X509Name.GetInstance(Asn1Object.FromByteArray(issuer.SubjectName.RawData));

            X509Name subjectNameObj = X509Name.GetInstance(Asn1Object.FromByteArray(subjectName.RawData));

            BigInteger subjectSerial = new BigInteger(1, serialNumber != null ? serialNumber : Guid.NewGuid().ToByteArray());
            BigInteger issuerSerial  = issuer == null ? subjectSerial : new BigInteger(1, issuer.GetSerialNumber());

            builder.SetIssuerDN(issuerNameObj);
            builder.SetSubjectDN(subjectNameObj);
            builder.SetSerialNumber(subjectSerial);
            builder.SetNotBefore(notBefore.ToUniversalTime());
            builder.SetNotAfter(notAfter.ToUniversalTime());
            builder.SetPublicKey(bcSubjectKey.Public);

            SubjectPublicKeyInfo   info         = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSignKey.Public);
            AuthorityKeyIdentifier authKeyId    = new AuthorityKeyIdentifier(info, new GeneralNames(new GeneralName(issuerNameObj)), issuerSerial);
            SubjectKeyIdentifier   subjectKeyid = new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(bcSubjectKey.Public));

            builder.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, true, authKeyId);
            builder.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, true, subjectKeyid);

            if (extensions != null)
            {
                foreach (SystemX509.X509Extension ext in extensions)
                {
                    if (!ext.Oid.Value.Equals(X509Extensions.AuthorityKeyIdentifier.Id) &&
                        !ext.Oid.Value.Equals(X509Extensions.SubjectKeyIdentifier.Id) &&
                        !ext.Oid.Value.Equals(szOID_AUTHORITY_KEY_IDENTIFIER2))
                    {
                        Asn1InputStream istm = new Asn1InputStream(ext.RawData);
                        Asn1Object      obj  = istm.ReadObject();
                        builder.AddExtension(ext.Oid.Value, ext.Critical, obj);
                    }
                }
            }

            X509Certificate cert = builder.Generate(CreateSignatureFactory(hashAlgorithm, bcSignKey, random));

            Pkcs12StoreBuilder   pkcs  = new Pkcs12StoreBuilder();
            Pkcs12Store          store = pkcs.Build();
            X509CertificateEntry entry = new X509CertificateEntry(cert);

            store.SetCertificateEntry("main", entry);

            AsymmetricKeyEntry key_entry = new AsymmetricKeyEntry(bcSubjectKey.Private);

            store.SetKeyEntry("main", key_entry, new[] { entry });
            MemoryStream stm = new MemoryStream();

            store.Save(stm, new char[0], new SecureRandom());
            return(new SystemX509.X509Certificate2(stm.ToArray(), String.Empty, SystemX509.X509KeyStorageFlags.Exportable));
        }
示例#23
0
 /// <summary>
 /// Create a new certificate
 /// </summary>
 /// <param name="issuer">Issuer certificate, if null then self-sign</param>
 /// <param name="subjectName">Subject name</param>
 /// <param name="serialNumber">Serial number of certificate, if null then will generate a new one</param>
 /// <param name="signature">If true create an AT_SIGNATURE key, otherwise AT_EXCHANGE</param>
 /// <param name="keySize">Size of RSA key</param>
 /// <param name="hashAlgorithm">The hash algorithm for the certificate</param>
 /// <param name="notBefore">Start date of certificate</param>
 /// <param name="notAfter">End date of certificate</param>
 /// <param name="extensions">Array of extensions, if null then no extensions</param>
 /// <returns>The created X509 certificate</returns>
 public static X509Certificate2 CreateCert(X509Certificate2 issuer, X500DistinguishedName subjectName, 
     byte[] serialNumber, bool signature, int keySize, CertificateHashAlgorithm hashAlgorithm, DateTime notBefore, DateTime notAfter, X509ExtensionCollection extensions)
 {
     return builder.CreateCert(issuer, subjectName, serialNumber, signature, keySize, hashAlgorithm, notBefore, notAfter, extensions);
 }