Beispiel #1
0
        /// <summary>
        /// Opens the store.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns>The store.</returns>
        public static ICertificateStore OpenStore(string path)
        {
            ICertificateStore store = CertificateStoreIdentifier.CreateStore(CertificateStoreIdentifier.DetermineStoreType(path));

            store.Open(path);
            return(store);
        }
        /// <summary>
        /// Returns an object that can be used to access the store containing the certificate.
        /// </summary>
        /// <returns>An instance of the <see cref="ICertificateStore"/> poined out by the current value of </returns>
        public ICertificateStore OpenStore()
        {
            ICertificateStore store = CertificateStoreIdentifier.CreateStore(this.StoreType);

            store.Open(this.StorePath);
            return(store);
        }
        /// <summary>
        /// Returns an object to access the store containing the certificates.
        /// </summary>
        /// <remarks>
        /// Opens an instance of the store which contains public keys.
        /// </remarks>
        /// <returns>A disposable instance of the <see cref="ICertificateStore"/>.</returns>
        public virtual ICertificateStore OpenStore()
        {
            ICertificateStore store = CreateStore(this.StoreType);

            store.Open(this.StorePath);
            return(store);
        }
        /// <summary>
        /// Finds a certificate in a store.
        /// </summary>
        /// <param name="needPrivateKey">if set to <c>true</c> the returned certificate must contain the private key.</param>
        /// <returns>An instance of the <see cref="X509Certificate2"/> that is emebeded by this instance or find it in
        /// the selected strore pointed out by the <see cref="StorePath"/> using selected <see cref="SubjectName"/>.</returns>
        public async Task <X509Certificate2> Find(bool needPrivateKey)
        {
            X509Certificate2 certificate = null;

            // check if the entire certificate has been specified.
            if (m_certificate != null && (!needPrivateKey || m_certificate.HasPrivateKey))
            {
                certificate = m_certificate;
            }
            else
            {
                // open store.
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(StoreType))
                {
                    store.Open(StorePath);

                    X509Certificate2Collection collection = await store.Enumerate();

                    certificate = Find(collection, m_thumbprint, m_subjectName, needPrivateKey);

                    if (certificate != null)
                    {
                        m_certificate = certificate;
                    }
                }
            }

            // use the single instance in the certificate cache.
            if (needPrivateKey)
            {
                certificate = m_certificate = CertificateFactory.Load(certificate, true);
            }

            return(certificate);
        }
Beispiel #5
0
        private ICertificateStore CreateStore(string storePath)
        {
            ICertificateStore store = CertificateStoreIdentifier.CreateStore(CertificateStoreIdentifier.DetermineStoreType(storePath));

            store.Open(storePath);
            return(store);
        }
Beispiel #6
0
        /// <summary>
        /// Finds a certificate in a store.
        /// </summary>
        /// <param name="needPrivateKey">if set to <c>true</c> the returned certificate must contain the private key.</param>
        /// <returns>An instance of the <see cref="X509Certificate2"/> that is emebeded by this instance or find it in
        /// the selected strore pointed out by the <see cref="StorePath"/> using selected <see cref="SubjectName"/>.</returns>
        public async Task <X509Certificate2> Find(bool needPrivateKey)
        {
            X509Certificate2 certificate = null;

            // check if the entire certificate has been specified.
            if (m_certificate != null)
            {
                certificate = m_certificate;
            }
            else
            {
                // open store.
                ICertificateStore store = CertificateStoreIdentifier.PickStore(StoreType);

                store.Open(StorePath);

                X509Certificate2Collection collection = await store.Enumerate();

                certificate = Find(collection, m_thumbprint, m_subjectName, needPrivateKey);

                if (certificate != null)
                {
                    m_certificate = certificate;
                }
            }

            return(certificate);
        }
        /// <summary>
        /// Returns an object that can be used to access the store.
        /// </summary>
        public ICertificateStore OpenStore()
        {
            ICertificateStore store = PickStore(this.StoreType);

            store.Open(this.StorePath);
            return(store);
        }
Beispiel #8
0
        /// <summary>
        /// Returns an object that can be used to access the store.
        /// </summary>
        public ICertificateStore OpenStore()
        {
            ICertificateStore store = CreateStore(this.StoreType);
            Task t = Task.Run(() => store.Open(this.StorePath));

            t.Wait();
            return(store);
        }
        public async Task <X509CertificateCollection> KeyVaultSigningRequestAsync()
        {
            Skip.If(!_fixture.KeyVaultInitOk);
            X509CertificateCollection certCollection = new X509CertificateCollection();

            string[] groups = await _keyVault.GetCertificateGroupIds();

            foreach (string group in groups)
            {
                var certificateGroupConfiguration = await _keyVault.GetCertificateGroupConfiguration(group);

                ApplicationTestData randomApp      = _fixture.RandomGenerator.RandomApplicationTestData();
                X509Certificate2    csrCertificate = CertificateFactory.CreateCertificate(
                    null, null, null,
                    randomApp.ApplicationRecord.ApplicationUri,
                    null,
                    randomApp.Subject,
                    randomApp.DomainNames.ToArray(),
                    certificateGroupConfiguration.DefaultCertificateKeySize,
                    DateTime.UtcNow.AddDays(-10),
                    certificateGroupConfiguration.DefaultCertificateLifetime,
                    certificateGroupConfiguration.DefaultCertificateHashSize
                    );
                byte[] certificateRequest = CertificateFactory.CreateSigningRequest(csrCertificate, randomApp.DomainNames);

                X509Certificate2 newCert = await _keyVault.SigningRequestAsync(
                    group,
                    randomApp.ApplicationRecord.ApplicationUri,
                    certificateRequest);

                // get issuer cert used for signing
                X509Certificate2Collection issuerCerts = await _keyVault.GetIssuerCACertificateChainAsync(group);

#if WRITECERT
                // save cert for debugging
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(CertificateStoreType.Directory))
                {
                    Assert.NotNull(store);
                    store.Open("d:\\unittest");
                    await store.Add(newCert);

                    foreach (var cert in issuerCerts)
                    {
                        await store.Add(cert);
                    }
                }
#endif
                Assert.NotNull(issuerCerts);
                Assert.True(issuerCerts.Count >= 1);
                X509TestUtils.VerifySignedApplicationCert(randomApp, newCert, issuerCerts);
                certCollection.Add(newCert);
            }
            return(certCollection);
        }
Beispiel #10
0
        /// <summary>
        /// Loads the private key for the certificate with an optional password.
        /// </summary>
        public async Task <X509Certificate2> LoadPrivateKeyEx(ICertificatePasswordProvider passwordProvider)
        {
            if (this.StoreType != CertificateStoreType.X509Store)
            {
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(StoreType))
                {
                    if (store.SupportsLoadPrivateKey)
                    {
                        store.Open(this.StorePath, false);
                        string password = passwordProvider?.GetPassword(this);
                        m_certificate = await store.LoadPrivateKey(this.Thumbprint, this.SubjectName, password).ConfigureAwait(false);

                        return(m_certificate);
                    }
                }
            }
            return(await Find(true).ConfigureAwait(false));
        }
Beispiel #11
0
        /// <summary>
        /// Gets the private key file path.
        /// </summary>
        public string GetPrivateKeyFilePath()
        {
            X509Certificate2 certificate = Find(false);

            if (certificate == null)
            {
                return(null);
            }

            ICertificateStore store = CertificateStoreIdentifier.CreateStore(this.StoreType);

            try {
                store.Open(this.StorePath);
                return(store.GetPrivateKeyFilePath(certificate.Thumbprint));
            } finally {
                store.Close();
            }
        }
Beispiel #12
0
        /// <summary>
        /// Finds a certificate in a store.
        /// </summary>
        /// <param name="needPrivateKey">if set to <c>true</c> the returned certificate must contain the private key.</param>
        /// <returns>An instance of the <see cref="X509Certificate2"/> that is embedded by this instance or find it in
        /// the selected store pointed out by the <see cref="StorePath"/> using selected <see cref="SubjectName"/>.</returns>
        public async Task <X509Certificate2> Find(bool needPrivateKey)
        {
            X509Certificate2 certificate = null;

            // check if the entire certificate has been specified.
            if (m_certificate != null && (!needPrivateKey || m_certificate.HasPrivateKey))
            {
                certificate = m_certificate;
            }
            else
            {
                // open store.
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(StoreType))
                {
                    store.Open(StorePath, false);

                    X509Certificate2Collection collection = await store.Enumerate().ConfigureAwait(false);

                    certificate = Find(collection, m_thumbprint, m_subjectName, needPrivateKey);

                    if (certificate != null)
                    {
                        if (needPrivateKey && store.SupportsLoadPrivateKey)
                        {
                            var message = new StringBuilder();
                            message.AppendLine("Loaded a certificate with private key from store {0}.");
                            message.AppendLine("Ensure to call LoadPrivateKeyEx with password provider before calling Find(true).");
                            Utils.LogWarning(message.ToString(), StoreType);
                        }

                        m_certificate = certificate;
                    }
                }
            }

            // use the single instance in the certificate cache.
            if (needPrivateKey)
            {
                certificate = m_certificate = CertificateFactory.Load(certificate, true);
            }

            return(certificate);
        }
Beispiel #13
0
        /// <summary>
        /// Extension to add a certificate to a <see cref="ICertificateStore"/>.
        /// </summary>
        /// <remarks>
        /// Saves also the private key, if available.
        /// If written to a Pfx file, the password is used for protection.
        /// </remarks>
        /// <param name="certificate">The certificate to store.</param>
        /// <param name="storeType">Type of certificate store (Directory) <see cref="CertificateStoreType"/>.</param>
        /// <param name="storePath">The store path (syntax depends on storeType).</param>
        /// <param name="password">The password to use to protect the certificate.</param>
        /// <returns></returns>
        public static X509Certificate2 AddToStore(
            this X509Certificate2 certificate,
            string storeType,
            string storePath,
            string password = null)
        {
            // add cert to the store.
            if (!String.IsNullOrEmpty(storePath) && !String.IsNullOrEmpty(storeType))
            {
                using (ICertificateStore store = Opc.Ua.CertificateStoreIdentifier.CreateStore(storeType))
                {
                    if (store == null)
                    {
                        throw new ArgumentException("Invalid store type");
                    }

                    store.Open(storePath);
                    store.Add(certificate, password).Wait();
                    store.Close();
                }
            }
            return(certificate);
        }
    /// <summary>
    /// Creates a self signed application instance certificate.
    /// </summary>
    /// <param name="storeType">Type of certificate store (Directory) <see cref="CertificateStoreType"/>.</param>
    /// <param name="storePath">The store path (syntax depends on storeType).</param>
    /// <param name="password">The password to use to protect the certificate.</param>
    /// <param name="applicationUri">The application uri (created if not specified).</param>
    /// <param name="applicationName">Name of the application (optional if subjectName is specified).</param>
    /// <param name="subjectName">The subject used to create the certificate (optional if applicationName is specified).</param>
    /// <param name="domainNames">The domain names that can be used to access the server machine (defaults to local computer name if not specified).</param>
    /// <param name="keySize">Size of the key (1024, 2048 or 4096).</param>
    /// <param name="startTime">The start time.</param>
    /// <param name="lifetimeInMonths">The lifetime of the key in months.</param>
    /// <param name="hashSizeInBits">The hash size in bits.</param>
    /// <param name="isCA">if set to <c>true</c> then a CA certificate is created.</param>
    /// <param name="issuerCAKeyCert">The CA cert with the CA private key.</param>
    /// <returns>The certificate with a private key.</returns>
    public static X509Certificate2 CreateCertificate(
        string storeType,
        string storePath,
        string password,
        string applicationUri,
        string applicationName,
        string subjectName,
        IList <String> domainNames,
        ushort keySize,
        DateTime startTime,
        ushort lifetimeInMonths,
        ushort hashSizeInBits,
        bool isCA = false,
        X509Certificate2 issuerCAKeyCert = null,
        byte[] publicKey = null)
    {
        if (issuerCAKeyCert != null)
        {
            if (!issuerCAKeyCert.HasPrivateKey)
            {
                throw new NotSupportedException("Cannot sign with a CA certificate without a private key.");
            }
        }

        if (publicKey != null && issuerCAKeyCert == null)
        {
            throw new NotSupportedException("Cannot use a public key without a CA certificate with a private key.");
        }

        // set default values.
        X509Name subjectDN = SetSuitableDefaults(
            ref applicationUri,
            ref applicationName,
            ref subjectName,
            ref domainNames,
            ref keySize,
            ref lifetimeInMonths);

        using (var cfrg = new CertificateFactoryRandomGenerator())
        {
            // cert generators
            SecureRandom random           = new SecureRandom(cfrg);
            X509V3CertificateGenerator cg = new X509V3CertificateGenerator();

            // Serial Number
            BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random);
            cg.SetSerialNumber(serialNumber);

            // subject and issuer DN
            X509Name issuerDN = null;
            if (issuerCAKeyCert != null)
            {
                issuerDN = new CertificateFactoryX509Name(issuerCAKeyCert.Subject);
            }
            else
            {
                // self signed
                issuerDN = subjectDN;
            }
            cg.SetIssuerDN(issuerDN);
            cg.SetSubjectDN(subjectDN);

            // valid for
            cg.SetNotBefore(startTime);
            cg.SetNotAfter(startTime.AddMonths(lifetimeInMonths));

            // set Private/Public Key
            AsymmetricKeyParameter subjectPublicKey;
            AsymmetricKeyParameter subjectPrivateKey;
            if (publicKey == null)
            {
                var keyGenerationParameters = new KeyGenerationParameters(random, keySize);
                var keyPairGenerator        = new RsaKeyPairGenerator();
                keyPairGenerator.Init(keyGenerationParameters);
                AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
                subjectPublicKey  = subjectKeyPair.Public;
                subjectPrivateKey = subjectKeyPair.Private;
            }
            else
            {
                // special case, if a cert is signed by CA, the private key of the cert is not needed
                subjectPublicKey  = PublicKeyFactory.CreateKey(publicKey);
                subjectPrivateKey = null;
            }
            cg.SetPublicKey(subjectPublicKey);

            // add extensions
            // Subject key identifier
            cg.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, false,
                            new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectPublicKey)));

            // Basic constraints
            cg.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(isCA));

            // Authority Key identifier references the issuer cert or itself when self signed
            AsymmetricKeyParameter issuerPublicKey;
            BigInteger             issuerSerialNumber;
            if (issuerCAKeyCert != null)
            {
                issuerPublicKey    = GetPublicKeyParameter(issuerCAKeyCert);
                issuerSerialNumber = GetSerialNumber(issuerCAKeyCert);
            }
            else
            {
                issuerPublicKey    = subjectPublicKey;
                issuerSerialNumber = serialNumber;
            }

            cg.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false,
                            new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerPublicKey),
                                                       new GeneralNames(new GeneralName(issuerDN)), issuerSerialNumber));

            if (!isCA)
            {
                // Key usage
                cg.AddExtension(X509Extensions.KeyUsage, true,
                                new KeyUsage(KeyUsage.DataEncipherment | KeyUsage.DigitalSignature |
                                             KeyUsage.NonRepudiation | KeyUsage.KeyCertSign | KeyUsage.KeyEncipherment));

                // Extended Key usage
                cg.AddExtension(X509Extensions.ExtendedKeyUsage, true,
                                new ExtendedKeyUsage(new List <DerObjectIdentifier>()
                {
                    new DerObjectIdentifier("1.3.6.1.5.5.7.3.1"), // server auth
                    new DerObjectIdentifier("1.3.6.1.5.5.7.3.2"), // client auth
                }));

                // subject alternate name
                List <GeneralName> generalNames = new List <GeneralName>();
                generalNames.Add(new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri));
                generalNames.AddRange(CreateSubjectAlternateNameDomains(domainNames));
                cg.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(generalNames.ToArray()));
            }
            else
            {
                // Key usage CA
                cg.AddExtension(X509Extensions.KeyUsage, true,
                                new KeyUsage(KeyUsage.CrlSign | KeyUsage.DigitalSignature | KeyUsage.KeyCertSign));
            }

            // sign certificate
            AsymmetricKeyParameter signingKey;
            if (issuerCAKeyCert != null)
            {
                // signed by issuer
                signingKey = GetPrivateKeyParameter(issuerCAKeyCert);
            }
            else
            {
                // self signed
                signingKey = subjectPrivateKey;
            }
            ISignatureFactory signatureFactory =
                new Asn1SignatureFactory(GetRSAHashAlgorithm(hashSizeInBits), signingKey, random);
            Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory);

            // convert to X509Certificate2
            X509Certificate2 certificate = null;
            if (subjectPrivateKey == null)
            {
                // create the cert without the private key
                certificate = new X509Certificate2(x509.GetEncoded());
            }
            else
            {
                // note: this cert has a private key!
                certificate = CreateCertificateWithPrivateKey(x509, null, subjectPrivateKey, random);
            }

            Utils.Trace(Utils.TraceMasks.Security, "Created new certificate: {0}", certificate.Thumbprint);

            // add cert to the store.
            if (!String.IsNullOrEmpty(storePath) && !String.IsNullOrEmpty(storeType))
            {
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(storeType))
                {
                    if (store == null)
                    {
                        throw new ArgumentException("Invalid store type");
                    }

                    store.Open(storePath);
                    store.Add(certificate, password).Wait();
                    store.Close();
                }
            }

            return(certificate);
        }
    }
Beispiel #15
0
        public async Task VerifyAppCertDirectoryStore()
        {
            var appCertificate = GetTestCert();

            Assert.NotNull(appCertificate);
            Assert.True(appCertificate.HasPrivateKey);

            string password = Guid.NewGuid().ToString();

            // pki directory root for app cert
            var pkiRoot   = Path.GetTempPath() + Path.GetRandomFileName() + Path.DirectorySeparatorChar;
            var storePath = pkiRoot + "own";
            var storeType = CertificateStoreType.Directory;

            appCertificate.AddToStore(
                storeType, storePath, password
                );

            using (var publicKey = new X509Certificate2(appCertificate.RawData))
            {
                Assert.NotNull(publicKey);
                Assert.False(publicKey.HasPrivateKey);

                var id = new CertificateIdentifier()
                {
                    Thumbprint = publicKey.Thumbprint,
                    StorePath  = storePath,
                    StoreType  = storeType
                };

                {
                    // check no password fails to load
                    var nullKey = await id.LoadPrivateKey(null).ConfigureAwait(false);

                    Assert.IsNull(nullKey);
                }

                {
                    // check invalid password fails to load
                    var nullKey = await id.LoadPrivateKey("123").ConfigureAwait(false);

                    Assert.IsNull(nullKey);
                }

                {
                    // check invalid password fails to load
                    var nullKey = await id.LoadPrivateKeyEx(new CertificatePasswordProvider("123")).ConfigureAwait(false);

                    Assert.IsNull(nullKey);
                }

                var privateKey = await id.LoadPrivateKeyEx(new CertificatePasswordProvider(password)).ConfigureAwait(false);

                Assert.NotNull(privateKey);
                Assert.True(privateKey.HasPrivateKey);

                X509Utils.VerifyRSAKeyPair(publicKey, privateKey, true);

                using (ICertificateStore store = Opc.Ua.CertificateStoreIdentifier.CreateStore(storeType))
                {
                    store.Open(storePath);
                    await store.Delete(publicKey.Thumbprint).ConfigureAwait(false);
                }
            }
        }
 /// <summary>
 /// Returns an object that can be used to access the store.
 /// </summary>
 public ICertificateStore OpenStore()
 {
     ICertificateStore store = CreateStore(this.StoreType);
     store.Open(this.StorePath);
     return store;
 }