Exemplo n.º 1
0
        private async Task DeleteExistingFromStore(string storePath)
        {
            if (String.IsNullOrEmpty(storePath))
            {
                return;
            }

            using (DirectoryCertificateStore store = (DirectoryCertificateStore)CertificateStoreIdentifier.OpenStore(storePath))
            {
                X509Certificate2Collection certificates = await store.Enumerate();

                foreach (var certificate in certificates)
                {
                    if (store.GetPrivateKeyFilePath(certificate.Thumbprint) != null)
                    {
                        continue;
                    }

                    List <string> fields = Utils.ParseDistinguishedName(certificate.Subject);

                    if (fields.Contains("CN=UA Local Discovery Server"))
                    {
                        continue;
                    }

                    DirectoryCertificateStore ds = store as DirectoryCertificateStore;

                    if (ds != null)
                    {
                        string path = Utils.GetAbsoluteFilePath(m_application.CertificatePublicKeyPath, true, false, false);

                        if (path != null)
                        {
                            if (String.Compare(path, ds.GetPublicKeyFilePath(certificate.Thumbprint), StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                continue;
                            }
                        }

                        path = Utils.GetAbsoluteFilePath(m_application.CertificatePrivateKeyPath, true, false, false);

                        if (path != null)
                        {
                            if (String.Compare(path, ds.GetPrivateKeyFilePath(certificate.Thumbprint), StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                continue;
                            }
                        }
                    }

                    await store.Delete(certificate.Thumbprint);
                }
            }
        }
        /// <summary>
        /// Returns the token from the cert in the given cert store.
        /// </summary>
        public async static Task <string> ReadAsync(string name, string storeType, string storePath)
        {
            string token = null;

            // handle each store type differently
            switch (storeType)
            {
            case CertificateStoreType.Directory:
            {
                // search a non expired cert with the given subject in the directory cert store and return the token
                using (DirectoryCertificateStore store = new DirectoryCertificateStore())
                {
                    store.Open(storePath);
                    X509CertificateCollection certificates = await store.Enumerate();

                    foreach (X509Certificate2 cert in certificates)
                    {
                        if ((token = CheckForToken(cert, name)) != null)
                        {
                            return(token);
                        }
                    }
                }
                break;
            }

            case CertificateStoreType.X509Store:
            {
                // search a non expired cert with the given subject in the X509 cert store and return the token
                using (X509Store store = new X509Store(storePath, StoreLocation.CurrentUser))
                {
                    store.Open(OpenFlags.ReadOnly);
                    foreach (X509Certificate2 cert in store.Certificates)
                    {
                        if ((token = CheckForToken(cert, name)) != null)
                        {
                            return(token);
                        }
                    }
                }
                break;
            }

            default:
            {
                throw new Exception($"The requested store type '{storeType}' is not supported. Please change.");
            }
            }
            return(null);
        }
        /// <summary>
        /// Creates a cert with the connectionstring (token) and stores it in the given cert store.
        /// </summary>
        public async static Task WriteAsync(string name, string connectionString, string storeType, string storePath)
        {
            if (string.IsNullOrEmpty(connectionString))
            {
                throw new ArgumentException("Token not found in X509Store and no new token provided!");
            }

            SecureRandom            random = new SecureRandom();
            KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, 2048);
            RsaKeyPairGenerator     keyPairGenerator        = new RsaKeyPairGenerator();

            keyPairGenerator.Init(keyGenerationParameters);
            AsymmetricCipherKeyPair keys = keyPairGenerator.GenerateKeyPair();

            ArrayList nameOids = new ArrayList();

            nameOids.Add(X509Name.CN);
            ArrayList nameValues = new ArrayList();

            nameValues.Add(name);
            X509Name subjectDN = new X509Name(nameOids, nameValues);
            X509Name issuerDN  = subjectDN;

            X509V3CertificateGenerator cg = new X509V3CertificateGenerator();

            cg.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random));
            cg.SetIssuerDN(issuerDN);
            cg.SetSubjectDN(subjectDN);
            cg.SetNotBefore(DateTime.Now);
            cg.SetNotAfter(DateTime.Now.AddMonths(12));
            cg.SetPublicKey(keys.Public);
            cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DataEncipherment));

            // encrypt the token with the public key so only the owner of the assoc. private key can decrypt it and
            // "hide" it in the instruction code cert extension
            RSA              rsa       = RSA.Create();
            RSAParameters    rsaParams = new RSAParameters();
            RsaKeyParameters keyParams = (RsaKeyParameters)keys.Public;

            rsaParams.Modulus = new byte[keyParams.Modulus.ToByteArrayUnsigned().Length];
            keyParams.Modulus.ToByteArrayUnsigned().CopyTo(rsaParams.Modulus, 0);

            rsaParams.Exponent = new byte[keyParams.Exponent.ToByteArrayUnsigned().Length];
            keyParams.Exponent.ToByteArrayUnsigned().CopyTo(rsaParams.Exponent, 0);

            rsa.ImportParameters(rsaParams);
            if (rsa != null)
            {
                byte[] bytes = rsa.Encrypt(Encoding.ASCII.GetBytes(connectionString), RSAEncryptionPadding.OaepSHA1);
                if (bytes != null)
                {
                    cg.AddExtension(X509Extensions.InstructionCode, false, bytes);
                }
                else
                {
                    RsaUtils.RSADispose(rsa);
                    throw new CryptographicException("Can not encrypt IoTHub security token using generated public key!");
                }
            }
            RsaUtils.RSADispose(rsa);

            // sign the cert with the private key
            ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHRSA", keys.Private, random);

            Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory);

            // create a PKCS12 store for the cert and its private key
            X509Certificate2 certificate = null;

            using (MemoryStream pfxData = new MemoryStream())
            {
                Pkcs12StoreBuilder builder = new Pkcs12StoreBuilder();
                builder.SetUseDerEncoding(true);
                Pkcs12Store            pkcsStore = builder.Build();
                X509CertificateEntry[] chain     = new X509CertificateEntry[1];
                string passcode = Guid.NewGuid().ToString();
                chain[0] = new X509CertificateEntry(x509);
                pkcsStore.SetKeyEntry(name, new AsymmetricKeyEntry(keys.Private), chain);
                pkcsStore.Save(pfxData, passcode.ToCharArray(), random);

                // create X509Certificate2 object from PKCS12 file
                certificate = CertificateFactory.CreateCertificateFromPKCS12(pfxData.ToArray(), passcode);

                // handle each store type differently
                switch (storeType)
                {
                case CertificateStoreType.Directory:
                {
                    // Add to DirectoryStore
                    using (DirectoryCertificateStore store = new DirectoryCertificateStore())
                    {
                        store.Open(storePath);
                        X509CertificateCollection certificates = await store.Enumerate();

                        // remove any existing cert with our name from the store
                        foreach (X509Certificate2 cert in certificates)
                        {
                            if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase))
                            {
                                await store.Delete(cert.Thumbprint);
                            }
                        }

                        // add new one
                        await store.Add(certificate);
                    }
                    break;
                }

                case CertificateStoreType.X509Store:
                {
                    // Add to X509Store
                    using (X509Store store = new X509Store(storePath, StoreLocation.CurrentUser))
                    {
                        store.Open(OpenFlags.ReadWrite);

                        // remove any existing cert with our name from the store
                        foreach (X509Certificate2 cert in store.Certificates)
                        {
                            if (cert.SubjectName.Decode(X500DistinguishedNameFlags.None | X500DistinguishedNameFlags.DoNotUseQuotes).Equals("CN=" + name, StringComparison.OrdinalIgnoreCase))
                            {
                                store.Remove(cert);
                            }
                        }

                        // add new cert to store
                        try
                        {
                            store.Add(certificate);
                        }
                        catch (Exception e)
                        {
                            throw new Exception($"Not able to add cert to the requested store type '{storeType}' (exception message: '{e.Message}'.");
                        }
                    }
                    break;
                }

                default:
                {
                    throw new Exception($"The requested store type '{storeType}' is not supported. Please change.");
                }
                }
                return;
            }
        }