예제 #1
0
파일: MainPage.xaml.cs 프로젝트: Bigsby/PoC
        private async Task <Certificate> GetClientCertificate()
        {
            //await InstallCertificate(@"Assets\BigsbyRootCert.pfx", "RootCert");
            await InstallCertificate(@"Assets\BigsbyClientCert.pfx", "ClientCert");

            var names    = new List <string>();
            var certList = await CertificateStores.FindAllAsync();

            var certs = certList.ToList();

            var query = new CertificateQuery
            {
                FriendlyName = "ClientCert",
            };

            var queried = (await CertificateStores.FindAllAsync(query)).ToList();

            Certificate clientCert = null;

            // Always choose first enumerated certificate.  Works so long as there is only one cert
            // installed and it's the right one.
            if ((null != certList) && (certList.Count > 0))
            {
                clientCert = certList.First();
            }

            return(queried.First());
        }
예제 #2
0
        private async void DeleteCerts_Click(object sender, RoutedEventArgs e)
        {
            DeleteCertsCompleted.Visibility = Visibility.Collapsed;

            try
            {
                IReadOnlyCollection <Certificate> certs = await CertificateStores.FindAllAsync();

                StringBuilder builder = new StringBuilder();

                // Append count.
                builder.AppendFormat("Count: {0}\r\n", certs.Count);

                foreach (var cert in certs)
                {
                    builder.Append("--------------------\r\n");
                    builder.AppendFormat("Issuer: {0}\r\n", cert.Issuer);
                    builder.AppendFormat("Subject: {0}\r\n", cert.Subject);

                    string thumbprint = CryptographicBuffer.EncodeToHexString(CryptographicBuffer.CreateFromByteArray(cert.GetHashValue()));
                    builder.AppendFormat("Thumbprint: {0}\r\n", thumbprint);

                    // Not working:
                    CertificateStores.IntermediateCertificationAuthorities.Delete(cert);
                }

                CertsBlock.Text = builder.ToString();
            }
            catch (Exception ex)
            {
                DisplayException(ex);
            }

            DeleteCertsCompleted.Visibility = Visibility.Visible;
        }
예제 #3
0
        async Task <Certificate> GetCertificate(MailboxAddress mailbox, bool sign)
        {
            var secure = mailbox as SecureMailboxAddress;
            var query  = new CertificateQuery();
            var now    = DateTimeOffset.UtcNow;

            if (secure != null)
            {
                query.Thumbprint = HexDecode(secure.Fingerprint);
            }
            else
            {
                query.FriendlyName = mailbox.Address;
            }

            // TODO: filter on key usages

            foreach (var certificate in await CertificateStores.FindAllAsync(query))
            {
                if (certificate.ValidFrom > now || certificate.ValidTo < now)
                {
                    continue;
                }

                return(certificate);
            }

            return(null);
        }
예제 #4
0
        private async Task SaveCertKeyPair()
        {
            var       settings   = ApplicationData.Current.RoamingSettings;
            PemWriter certWriter = new PemWriter(new StringWriter());
            PemWriter keyWriter  = new PemWriter(new StringWriter());

            keyWriter.WriteObject(keyPair);
            keyWriter.Writer.Flush();

            // Add the cert to the cert store. This changes the fingerprint so we read it
            // back before we serialize it so we have the up to date cert.
            await AddToWinCertStore();

            // Read the modified cert from the cert store
            IEnumerable <Certificate> certificates = await CertificateStores.FindAllAsync(new CertificateQuery { FriendlyName = "Limelight-Client" });

            cert = new X509CertificateParser().ReadCertificate(certificates.Single().GetCertificateBlob().AsStream());

            certWriter.WriteObject(cert);
            certWriter.Writer.Flush();

            // Line endings MUST be UNIX for the PC to accept the cert properly
            string keyStr = keyWriter.Writer.ToString();

            keyStr = keyStr.Replace("\r\n", "\n");

            string certStr = certWriter.Writer.ToString();

            certStr = certStr.Replace("\r\n", "\n");

            settings.Values["cert"] = certStr;
            settings.Values["key"]  = keyStr;
        }
예제 #5
0
        /// <summary>
        /// Load the cert/key pair from memory
        /// </summary>
        /// <returns>Value indicating success</returns>
        private async Task <bool> LoadCertKeyPair()
        {
            var settings = ApplicationData.Current.RoamingSettings;
            IEnumerable <Certificate> certificates = await CertificateStores.FindAllAsync(new CertificateQuery { FriendlyName = "Limelight-Client" });

            if (settings.Values.ContainsKey("cert") && settings.Values.ContainsKey("key") && certificates.Count() > 0)
            {
                string certStr = ApplicationData.Current.RoamingSettings.Values["cert"].ToString();
                string keyStr  = ApplicationData.Current.RoamingSettings.Values["key"].ToString();

                PemReader certReader = new PemReader(new StringReader(certStr));
                PemReader keyReader  = new PemReader(new StringReader(keyStr));

                keyPair      = (AsymmetricCipherKeyPair)keyReader.ReadObject();
                cert         = (X509Certificate)certReader.ReadObject();
                pemCertBytes = System.Text.Encoding.UTF8.GetBytes(certStr);

                return(true);
            }
            // We didn't load the cert/key pair properly
            else
            {
                return(false);
            }
        }
예제 #6
0
        /// <summary>
        /// Opens the certificate store.
        /// </summary>
        private CertificateStore OpenStore(bool readOnly, bool createAlways, bool throwIfNotExist)
        {
            // check for a valid name.
            if (String.IsNullOrEmpty(m_symbolicName))
            {
                if (throwIfNotExist)
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadConfigurationError,
                              "WindowsCertificateStore object has not been initialized properly.");
                }

                return(null);
            }

            CertificateStore hStore = CertificateStores.GetStoreByName(m_symbolicName);

            if (hStore == null)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadUnexpectedError,
                          "Could not open the certificate store.\r\nType={0}, Name={1}",
                          m_storeType,
                          m_symbolicName);
            }
            else
            {
                // return the handle.
                return(hStore);
            }
        }
예제 #7
0
        /// <summary>
        /// Gets the Xml as a string from the URL provided
        /// </summary>
        /// <returns>The server info XML as a string</returns>
        private async Task GetXml()
        {
            HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();

            filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
            filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);

            IEnumerable <Certificate> certificates = await CertificateStores.FindAllAsync(new CertificateQuery { FriendlyName = "Limelight-Client" });

            filter.ClientCertificate = certificates.Single();

            client = new Windows.Web.Http.HttpClient(filter);
            Debug.WriteLine(uri);
            if (rawXmlString == null)
            {
                try
                {
                    rawXmlString = await client.GetStringAsync(uri);
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e.Message);
                }
                Debug.WriteLine(rawXmlString);

                // Up to the caller to deal with exceptions resulting here
                this.rawXml = XDocument.Parse(rawXmlString);
            }
        }
예제 #8
0
        private IReadOnlyList <Certificate> GetCertificatesFromWinRTStore(X509Certificate2 dotNetCertificate)
        {
            var query = new CertificateQuery
            {
                Thumbprint        = dotNetCertificate.GetCertHash(),
                IncludeDuplicates = false
            };

            return(CertificateStores.FindAllAsync(query).AsTask().GetAwaiter().GetResult());
        }
예제 #9
0
        private async void ButtonClientCert_Click(object sender, RoutedEventArgs args)
        {
            using (new ControlDisabler(ButtonClientCert))
            {
                var picker = new FileOpenPicker
                {
                    ViewMode = PickerViewMode.List,
                    SuggestedStartLocation = PickerLocationId.Downloads,
                };
                picker.FileTypeFilter.Add(".pfx");
                var file = await picker.PickSingleFileAsync();

                if (file == null)
                {
                    return;
                }
                var fileStream = await file.OpenReadAsync();

                var certData = await new StreamReader(fileStream.AsStreamForRead()).ReadToEndAsync();
                if (certData.IndexOf("-----BEGIN PKCS12-----") == -1)
                {
                    await new ErrorContentDialog("Selected file is not a base64 PKCS12 certificate. Please use a certificate created using `certtool --load-certificate user.cert.pem --load-privkey user.key.pem --to-p12 --outfile user.pfx`")
                    .ShowAsync();
                    return;
                }
                var passwordDialog = new CertPasswordContentDialog();
                if (await passwordDialog.ShowAsync() != ContentDialogResult.Primary)
                {
                    return;
                }
                var pass = passwordDialog.Password;
                try
                {
                    // we're importing it with a temporary name to see if it's valid; "real" importing doesn't happen until save is pressed.
                    await CertificateEnrollmentManager.ImportPfxDataAsync(certData, pass, ExportOption.NotExportable, KeyProtectionLevel.NoConsent, InstallOptions.None, Constants.ClientCertTempName);
                }
                catch (Exception e)
                {
                    await new ErrorContentDialog(e)
                    .ShowAsync();
                    return;
                }
                var certs = await CertificateStores.FindAllAsync(new CertificateQuery { FriendlyName = Constants.ClientCertTempName });

                if (!certs.Where(c => c.HasPrivateKey).Any())
                {
                    await new ErrorContentDialog("Selected certificate contains no private key. Please use a certificate created using `certtool --load-certificate user.cert.pem --load-privkey user.key.pem --to-p12 --outfile user.pfx`")
                    .ShowAsync();
                    return;
                }
                // everything looks good, remember values for saving
                clientCert           = certData;
                clientCertPassphrase = pass;
            }
        }
예제 #10
0
        private async void DoGet(bool ignoreCertErrors, string key, string value, string friendlyName)
        {
            ResponseHeadersBlock.Text = String.Empty;
            CertErrorsBlock.Text      = String.Empty;
            ResponseContentBlock.Text = String.Empty;

            HttpRequestMessage request = null;

            try
            {
                request = new HttpRequestMessage(
                    HttpMethod.Get,
                    new Uri(UriBox2.Text));

                HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();

                if (ignoreCertErrors)
                {
                    filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
                    filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
                    filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
                }

                if (!String.IsNullOrEmpty(friendlyName))
                {
                    CertificateQuery query = new CertificateQuery();
                    query.FriendlyName = friendlyName;
                    IReadOnlyCollection <Certificate> certs = await CertificateStores.FindAllAsync(query);

                    filter.ClientCertificate = certs.ElementAt(0);
                }

                HttpClient client = new HttpClient(filter);

                if (!String.IsNullOrEmpty(key))
                {
                    client.DefaultRequestHeaders.Add(key, value);
                }

                HttpResponseMessage response = await client.SendRequestAsync(request);

                ResponseHeadersBlock.Text = response.ReasonPhrase;
                ResponseContentBlock.Text = await response.Content.ReadAsStringAsync();
            }
            catch (Exception ex)
            {
                ResponseHeadersBlock.Text = ex.ToString();

                // Something like: 'Untrusted, InvalidName, RevocationFailure'
                CertErrorsBlock.Text = String.Join(
                    ", ",
                    request.TransportInformation.ServerCertificateErrors);
            }
        }
예제 #11
0
        private async Task <Certificate> FindCertificate(IDictionary <string, string> challengeData)
        {
            CertificateQuery            query        = new CertificateQuery();
            IReadOnlyList <Certificate> certificates = null;
            string errMessage = null;

            if (challengeData.ContainsKey("CertAuthorities"))
            {
                errMessage = "Cert Authorities:" + challengeData["CertAuthorities"];
                PlatformPlugin.Logger.Verbose(null, "Looking up certificate matching authorities:" + challengeData["CertAuthorities"]);
                string[] certAuthorities = challengeData["CertAuthorities"].Split(';');
                foreach (var certAuthority in certAuthorities)
                {
                    //reverse the tokenized string and replace "," with " + "
                    string[] dNames = certAuthority.Split(new[] { "," }, StringSplitOptions.None);
                    string   distinguishedIssuerName = dNames[dNames.Length - 1];
                    for (int i = dNames.Length - 2; i >= 0; i--)
                    {
                        distinguishedIssuerName += " + " + dNames[i].Trim();
                    }

                    query.IssuerName = distinguishedIssuerName;
                    certificates     = await CertificateStores.FindAllAsync(query);

                    if (certificates.Count > 0)
                    {
                        break;
                    }
                }
            }
            else
            {
                errMessage = "Cert Thumbprint:" + challengeData["CertThumbprint"];
                PlatformPlugin.Logger.Verbose(null, "Looking up certificate matching thumbprint:" + challengeData["CertThumbprint"]);
                query.Thumbprint = HexStringToByteArray(challengeData["CertThumbprint"]);
                certificates     = await CertificateStores.FindAllAsync(query);
            }

            if (certificates == null || certificates.Count == 0)
            {
                throw new AdalException(AdalError.DeviceCertificateNotFound,
                                        string.Format(AdalErrorMessage.DeviceCertificateNotFoundTemplate, errMessage));
            }

            return(certificates[0]);
        }
예제 #12
0
        private static void ValidateClientCertificate(X509Certificate2 certificate)
        {
#if FEATURE_NETNATIVE
            var query = new CertificateQuery
            {
                Thumbprint        = certificate.GetCertHash(),
                IncludeDuplicates = false,
                StoreName         = "MY"
            };

            if (CertificateStores.FindAllAsync(query).AsTask().GetAwaiter().GetResult().Count == 0)
            {
                throw ExceptionHelper.PlatformNotSupported("Certificate could not be found in the MY store.");
            }
            ;
#endif // FEATURE_NETNATIVE
        }
예제 #13
0
        public async Task <Certificate> GetAsync()
        {
            var certUsername = await _storage.GetTextAsync(StorageKeyNames.RegisteredCertSubject);

            if (certUsername != null)
            {
                var certs = await CertificateStores.FindAllAsync(new CertificateQuery()
                {
                    IssuerName = "ca_msso",
                });

                var cert = certs.FirstOrDefault(c => c.Subject == certUsername);
                return(cert);
            }

            return(null);
        }
        /// <summary>
        /// Queries the device certificates and tries to retrieve one suitable for authenticating with the NAM.
        ///
        /// Will look for issuer "Schaeffler Group Sub CA01" (for newer devices) or just "Schaeffler*" (for older devices)
        /// </summary>
        /// <returns>A certificate suitable for NAM authentication.</returns>
        private Certificate GetDeviceCertificate()
        {
            // get certificate by issuer name
            Debug.WriteLine("Finding certificates...");
            var certificateTask = CertificateStores.FindAllAsync().AsTask();

            certificateTask.Wait();

            // get certificates (with private keys) issued by Schaeffler, prefer newer ones
            var possibleCertificates = from cert in certificateTask.Result
                                       where cert.HasPrivateKey && (cert.Issuer == "Schaeffler Group Sub CA01" || cert.Issuer.StartsWith("Schaeffler"))
                                       orderby cert.ValidFrom
                                       select cert;

            var certificate = possibleCertificates.FirstOrDefault();

            return(certificate);
        }
        private async Task <Certificate> FindCertificateFromStoreAsync()
        {
            // Find the client certificate for authentication. If not found, it means it has not been installed.
            CertificateQuery query = new CertificateQuery();

            query.IssuerName   = ClientCertIssuerName;
            query.FriendlyName = ClientCertFriendlyName;

            IReadOnlyList <Certificate> certs = await CertificateStores.FindAllAsync(query);

            if (certs.Count == 0)
            {
                return(null);
            }

            // This sample installs only one certificate, so if we find one, it must be ours.
            return(certs[0]);
        }
예제 #16
0
        /// <summary>
        /// Returns a certificate with a given name
        /// </summary>
        /// <param name="certName">Name of cert we are going to look for</param>
        /// <returns>null if the cert isn't there, otherwise the cert that was found.</returns>
        public static async Task <Certificate> FindCert(string certName)
        {
            // Work around for the TplEventListener not working correctly.
            // https://social.msdn.microsoft.com/Forums/windowsapps/en-US/3e505e04-7f30-4313-aa47-275eaef333dd/systemargumentexception-use-of-undefined-keyword-value-1-for-event-taskscheduled-in-async?forum=wpdevelop
            await Task.Delay(1);

            // Do the CERT query

            var query = new CertificateQuery();

            query.FriendlyName = certName;
            var certificates = await CertificateStores.FindAllAsync(query);

            if (certificates.Count != 1)
            {
                return(null);
            }
            return(certificates[0]);
        }
예제 #17
0
        /// <summary>
        /// Gets the Xml as a string from the URL provided
        /// </summary>
        /// <returns>The server info XML as a string</returns>
        private async Task GetXml()
        {
            // Return if we've already been here
            if (ranQuery)
            {
                return;
            }
            else
            {
                ranQuery = true;
            }

            HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();

            filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
            filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);

            // Allow the crypto provider to generate the cert if needed
            await new WindowsCryptoProvider().InitializeCryptoProviderKeys();

            IEnumerable <Certificate> certificates = await CertificateStores.FindAllAsync(new CertificateQuery { FriendlyName = "Limelight-Client" });

            filter.ClientCertificate = certificates.Single();

            client = new Windows.Web.Http.HttpClient(filter);
            Debug.WriteLine(uri);

            try
            {
                rawXmlString = await client.GetStringAsync(uri);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
                return;
            }

            Debug.WriteLine(rawXmlString);

            // Up to the caller to deal with exceptions resulting here
            this.rawXml = XDocument.Parse(rawXmlString);
        }
예제 #18
0
        /// <summary cref="ICertificateStore.Enumerate()" />
        public async Task <X509Certificate2Collection> Enumerate()
        {
            X509Certificate2Collection certificates = new X509Certificate2Collection();

            // get the certificates.
            IReadOnlyList <Certificate> list = await CertificateStores.FindAllAsync();

            for (int ii = 0; ii < list.Count; ii++)
            {
                // add the certificate.
                IBuffer buffer = list[ii].GetCertificateBlob();
                byte[]  cert   = new byte[buffer.Length];
                CryptographicBuffer.CopyToByteArray(buffer, out cert);

                X509Certificate2 certificate = new X509Certificate2(cert);
                certificates.Add(certificate);
            }

            return(certificates);
        }
예제 #19
0
        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                CertificateQuery q = new CertificateQuery();
                q.HardwareOnly = true;
                q.IssuerName   = "Citizen CA";
                IReadOnlyList <Certificate> certs = await CertificateStores.FindAllAsync(q);

                FileOpenPicker openPicker = new FileOpenPicker();
                openPicker.ViewMode = PickerViewMode.Thumbnail;
                openPicker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
                openPicker.FileTypeFilter.Add(".p12");
                openPicker.FileTypeFilter.Add(".acc-p12");

                StorageFile file = await openPicker.PickSingleFileAsync();
            } catch
            {
            }
        }
        private void loadCertificates()
        {
            certificatesListCB.Items.Clear();
            var task = CertificateStores.FindAllAsync();

            task.AsTask().Wait();
            var certlist = task.GetResults();

            LoadCertList(certlist);

            if (certificatesListCB.Items.Count == 0)
            {
                certificatesListCB.Items.Add(NOCERTS);
                certificatesListCB.IsEnabled = false;
            }
            else
            {
                certificatesListCB.IsEnabled = true;
            }
            certificatesListCB.SelectedIndex = 0;
        }
예제 #21
0
        private async void QueryCerts_Click(object sender, RoutedEventArgs e)
        {
            QueryCertsCompleted.Visibility = Visibility.Collapsed;

            try
            {
                IReadOnlyCollection <Certificate> certs = await CertificateStores.FindAllAsync();

                StringBuilder builder = new StringBuilder();

                // Append count.
                builder.AppendFormat("Count: {0}\r\n", certs.Count);

                foreach (var cert in certs)
                {
                    builder.Append("--------------------\r\n");
                    builder.AppendFormat("EnhancedKeyUsages: {0}\r\n", String.Join(", ", cert.EnhancedKeyUsages));
                    builder.AppendFormat("FriendlyName: {0}\r\n", cert.FriendlyName);
                    builder.AppendFormat("HasPrivateKey: {0}\r\n", cert.HasPrivateKey);
                    builder.AppendFormat("IsStronglyProtected: {0}\r\n", cert.IsStronglyProtected);
                    builder.AppendFormat("Issuer: {0}\r\n", cert.Issuer);
                    builder.AppendFormat("SerialNumber: {0}\r\n", BitConverter.ToString(cert.SerialNumber));
                    builder.AppendFormat("Subject: {0}\r\n", cert.Subject);
                    builder.AppendFormat("ValidFrom: {0}\r\n", cert.ValidFrom);
                    builder.AppendFormat("ValidTo: {0}\r\n", cert.ValidTo);

                    string thumbprint = CryptographicBuffer.EncodeToHexString(CryptographicBuffer.CreateFromByteArray(cert.GetHashValue()));
                    builder.AppendFormat("Thumbprint: {0}\r\n", thumbprint);
                }

                CertsBlock.Text = builder.ToString();
            }
            catch (Exception ex)
            {
                DisplayException(ex);
            }

            QueryCertsCompleted.Visibility = Visibility.Visible;
        }
예제 #22
0
        /// <summary>
        /// Gets the private key for the certificate matching the specified selector.
        /// </summary>
        /// <remarks>
        /// Gets the private key for the first certificate that matches the specified selector.
        /// </remarks>
        /// <returns>The private key on success; otherwise <c>null</c>.</returns>
        /// <param name="selector">The search criteria for the private key.</param>
        protected virtual async Task <AsymmetricKeyParameter> GetPrivateKeyAsync(IX509Selector selector)
        {
            // first we need to find the certificate...
            var match = selector as X509CertStoreSelector;
            var query = new CertificateQuery();

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

            if (match.Certificate != null)
            {
                query.Thumbprint = HexDecode(match.Certificate.GetFingerprint());
            }

            if (match.Issuer != null)
            {
                query.IssuerName = match.Issuer.ToString();
            }

            var certificates = await CertificateStores.FindAllAsync(query);

            var certificate = certificates.FirstOrDefault();

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

            // now get the key

            // TODO: what hash algo/padding do we want? does it matter?
            var key = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(certificate, HashAlgorithmNames.Sha256, CryptographicPadding.RsaPkcs1V15);

            var buffer = key.Export(CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey);

            return(LoadPrivateKey(buffer));
        }
예제 #23
0
        /// <summary>
        /// Finds a certificate in the store.
        /// </summary>
        /// <param name="hStore">The handle for the store to search.</param>
        /// <param name="thumbprint">The thumbprint of the certificate to find.</param>
        /// <returns>The context for the matching certificate.</returns>
        private static async Task <IBuffer> FindCertificate(string thumbprint)
        {
            byte[] byteThumbprint = new byte[thumbprint.Length];
            for (int i = 0; i < thumbprint.Length; i++)
            {
                byteThumbprint[i] = (byte)thumbprint[i];
            }

            CertificateQuery query = new CertificateQuery();

            query.Thumbprint = byteThumbprint;
            IReadOnlyList <Certificate> list = await CertificateStores.FindAllAsync(query);

            if (list.Count > 0)
            {
                return(list[0].GetCertificateBlob());
            }
            else
            {
                return(null);
            }
        }
예제 #24
0
        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            IReadOnlyList <Certificate> certificates = await CertificateStores.FindAllAsync();

            foreach (Certificate certificate in certificates)
            {
                var item = new ListViewItem
                {
                    Content = $"Subject: {certificate.Subject}, Serial Number: {CryptographicBuffer.EncodeToHexString(CryptographicBuffer.CreateFromByteArray(certificate.SerialNumber))}",
                    Tag     = certificate
                };

                if (certificate.IsPerUser)
                {
                    UserCertificateListView.Items.Add(item);
                }
                else
                {
                    AppCertificateListView.Items.Add(item);
                }
            }
        }
예제 #25
0
        /// <summary cref="ICertificateStore.Add(X509Certificate2)" />
        public async Task Add(X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            // check for existing certificate.
            byte[] thumbprint = new byte[certificate.Thumbprint.Length];
            for (int i = 0; i < certificate.Thumbprint.Length; i++)
            {
                thumbprint[i] = (byte)certificate.Thumbprint[i];
            }

            CertificateQuery query = new CertificateQuery();

            query.Thumbprint = thumbprint;
            IReadOnlyList <Certificate> pCertContext = await CertificateStores.FindAllAsync(query);

            if (pCertContext.Count != 0)
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadUnexpectedError,
                          "Certificate is already in the store.\r\nType={0}, Name={1}, Subject={2}",
                          m_storeType,
                          m_symbolicName,
                          certificate.Subject);
            }

            lock (m_lock)
            {
                // add certificate.
                CertificateFactory.AddCertificateToWindowsStore(
                    m_storeType == WindowsStoreType.LocalMachine,
                    m_symbolicName,
                    certificate);
            }
        }
예제 #26
0
        private async Task EnsureDeleteOldCertificates()
        {
            UserCertificateStore certificateStore = CertificateStores.GetUserStoreByName(StandardCertificateStoreNames.Personal);
            var certificateFinder = await CertificateStores.FindAllAsync(new CertificateQuery()
            {
                IncludeDuplicates = true, IncludeExpiredCertificates = true
            });

            foreach (Certificate oldCertificate in certificateFinder)
            {
                if (oldCertificate.Issuer.StartsWith("Azure IoT Edison Intermediate"))
                {
                    try
                    {
                        await certificateStore.RequestDeleteAsync(oldCertificate);
                    }
                    catch (Exception e)
                    {
                        DebugHelper.LogWarning($"An old certificate could not be deleted: {e.Message}");
                    }
                }
            }
        }
예제 #27
0
        /// <summary cref="ICertificateStore.Delete(string)" />
        public async Task <bool> Delete(string thumbprint)
        {
            // open store.
            CertificateStore hStore = OpenStore(false, false, false);

            if (hStore == null)
            {
                return(false);
            }

            // find certificate.
            byte[] byteThumbprint = new byte[thumbprint.Length];
            for (int i = 0; i < thumbprint.Length; i++)
            {
                byteThumbprint[i] = (byte)thumbprint[i];
            }

            CertificateQuery query = new CertificateQuery();

            query.Thumbprint = byteThumbprint;
            IReadOnlyList <Certificate> list = await CertificateStores.FindAllAsync(query);

            // delete certificate.
            if (list.Count > 0)
            {
                lock (m_lock)
                {
                    hStore.Delete(list[0]);
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #28
0
        private void EnumerateCertificateList()
        {
            CertificateList.Visibility = Visibility.Visible;
            CertificateList.Items.Clear();
            var task = CertificateStores.FindAllAsync();

            task.AsTask().Wait();
            var certlist = task.GetResults();

            LoadCertList(certlist);

            if (CertificateList.Items.Count == 0)
            {
                VerifyCert.IsEnabled = false;
                RunSample.IsEnabled  = false;
                CertificateList.Items.Add("No certificates found");
            }
            else
            {
                VerifyCert.IsEnabled = true;
                RunSample.IsEnabled  = true;
            }
            CertificateList.SelectedIndex = 0;
        }
        public override async Task PairAsync(string ipAddress, TextBox outputTextBox)
        {
            // Create SHA256 hash digest. This is not supported by server version < 7
            // (need to use SHA1 for those cases) but that doesn't really matter right now.
            IDigest hashAlgorithm  = new Sha256Digest();
            int     hashDigestSize = hashAlgorithm.GetDigestSize();

            // Create and salt pin
            byte[] salt = this.GenerateRandomBytes(16);
            string pin  = GenerateRandomPin();

            byte[] saltAndPin = SaltPin(salt, pin);

            // Asymmetric key pair
            RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();

            keyPairGenerator.Init(new KeyGenerationParameters(this.SecureRandom, 2048));
            AsymmetricCipherKeyPair keyPair = keyPairGenerator.GenerateKeyPair();

            // Certificate issuer and name
            X509Name name = new X509Name("CN=NVIDIA GameStream Client");

            // Certificate serial number
            byte[]     serialBytes = this.GenerateRandomBytes(8);
            BigInteger serial      = new BigInteger(serialBytes).Abs();

            // Expires in 20 years
            DateTime now        = DateTime.UtcNow;
            DateTime expiration = now.AddYears(20);

            X509V3CertificateGenerator generator = new X509V3CertificateGenerator();

            generator.SetSubjectDN(name);
            generator.SetIssuerDN(name);
            generator.SetSerialNumber(serial);
            generator.SetNotBefore(now);
            generator.SetNotAfter(expiration);
            generator.SetPublicKey(keyPair.Public);

            BouncyCastleX509Certificate certificate =
                generator.Generate(
                    new Asn1SignatureFactory("SHA1WithRSA", keyPair.Private));

            // Create PKCS12 certificate bytes.
            Pkcs12Store          store            = new Pkcs12Store();
            X509CertificateEntry certificateEntry = new X509CertificateEntry(certificate);
            string friendlyName = "Moonlight Xbox";
            string password     = "******";

            store.SetCertificateEntry(friendlyName, certificateEntry);
            store.SetKeyEntry(
                friendlyName,
                new AsymmetricKeyEntry(keyPair.Private),
                new X509CertificateEntry[] { certificateEntry });
            string pfxData;

            using (MemoryStream memoryStream = new MemoryStream(512))
            {
                store.Save(memoryStream, password.ToCharArray(), this.SecureRandom);
                pfxData = CryptographicBuffer.EncodeToBase64String(memoryStream.ToArray().AsBuffer());
            }

            await CertificateEnrollmentManager.ImportPfxDataAsync(
                pfxData,
                password,
                ExportOption.NotExportable,
                KeyProtectionLevel.NoConsent,
                InstallOptions.DeleteExpired,
                friendlyName);

            // Read the UWP cert from the cert store
            Certificate uwpCertificate =
                (await CertificateStores.FindAllAsync(
                     new CertificateQuery {
                FriendlyName = friendlyName
            }))[0];

            string keyString;

            using (StringWriter keyWriter = new StringWriter())
            {
                PemWriter pemWriter = new PemWriter(keyWriter);
                pemWriter.WriteObject(keyPair);
                keyString = keyWriter.ToString();

                // Line endings must be UNIX style for GFE to accept the certificate.
                keyString = keyString.Replace(Environment.NewLine, "\n");
            }

            string certString;

            using (StringWriter certWriter = new StringWriter())
            {
                PemWriter pemWriter = new PemWriter(certWriter);
                pemWriter.WriteObject(certificate);
                certString = certWriter.ToString();

                // Line endings must be UNIX style for GFE to accept the certificate.
                certString = certString.Replace(Environment.NewLine, "\n");
            }

            byte[] pemCertBytes = Encoding.UTF8.GetBytes(certString);
            byte[] uniqueId     = GenerateRandomBytes(8);

            // Create the HTTP client.
            HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();

            filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
            filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
            filter.ClientCertificate = uwpCertificate;

            HttpClient httpClient = new HttpClient(filter);

            // Unpair before doing anything else in this test app.
            string uriString =
                string.Format(
                    "http://{0}:47989/unpair?uniqueid={1}&uuid={2}",
                    ipAddress,
                    BytesToHex(uniqueId),
                    Guid.NewGuid().ToString("N"));

            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(uriString)))
            {
                using (HttpResponseMessage response = await httpClient.SendRequestAsync(request))
                {
                    outputTextBox.Text = $"Unpair status code: {response.StatusCode}\n";
                    string responseContent = await response.Content.ReadAsStringAsync();

                    outputTextBox.Text += responseContent + "\n";
                }
            }

            await Task.Delay(2000);

            outputTextBox.Text = $"Enter pin: {pin}";

            // Get server certificate.
            // TODO: Call should have no timeout because it requires the user to enter a pin.
            PairResponse pairResponse = null;

            uriString =
                string.Format(
                    "http://{0}:47989/pair?uniqueid={1}&uuid={2}&devicename=roth&updateState=1&phrase=getservercert&salt={3}&clientcert={4}",
                    ipAddress,
                    BytesToHex(uniqueId),
                    Guid.NewGuid().ToString("N"),
                    BytesToHex(salt),
                    BytesToHex(pemCertBytes));
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(uriString)))
            {
                using (HttpResponseMessage response = await httpClient.SendRequestAsync(request))
                {
                    outputTextBox.Text = $"Get server cert status code: {response.StatusCode}\n";
                    string responseContent = await response.Content.ReadAsStringAsync();

                    outputTextBox.Text += responseContent + "\n";
                    using (StringReader reader = new StringReader(responseContent))
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(PairResponse));
                        pairResponse = serializer.Deserialize(new StringReader(responseContent)) as PairResponse;
                    }
                }
            }

            if (pairResponse == null || pairResponse.Paired != 1)
            {
                outputTextBox.Text += "Pairing failed.\n";
                return;
            }

            if (string.IsNullOrEmpty(pairResponse.PlainCert))
            {
                outputTextBox.Text += "Pairing already in progress.\n";
                return;
            }

            // Parse server certificate
            byte[] serverCertBytes = HexToBytes(pairResponse.PlainCert);
            BouncyCastleX509Certificate serverCertificate = new X509CertificateParser().ReadCertificate(serverCertBytes);

            // Hash the salt and pin and use it to generate an AES key.
            byte[]            hashedSaltAndPin = HashData(hashAlgorithm, saltAndPin);
            ICipherParameters aesKey           = GenerateCipherKey(hashedSaltAndPin);

            // Generate a random challenge and encrypt it using AES.
            byte[] challenge          = GenerateRandomBytes(16);
            byte[] encryptedChallenge = DoAesCipher(true, aesKey, challenge);

            await Task.Delay(2000);

            // Send the encrypted challenge to the server.
            // TODO: Call should have a timeout.
            uriString =
                string.Format(
                    "http://{0}:47989/pair?uniqueid={1}&uuid={2}&devicename=roth&updateState=1&clientchallenge={3}",
                    ipAddress,
                    BytesToHex(uniqueId),
                    Guid.NewGuid().ToString("N"),
                    BytesToHex(encryptedChallenge));
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(uriString)))
            {
                using (HttpResponseMessage response = await httpClient.SendRequestAsync(request))
                {
                    outputTextBox.Text = $"Send challenge status code: {response.StatusCode}\n";
                    string responseContent = await response.Content.ReadAsStringAsync();

                    outputTextBox.Text += responseContent + "\n";
                    using (StringReader reader = new StringReader(responseContent))
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(PairResponse));
                        pairResponse = serializer.Deserialize(new StringReader(responseContent)) as PairResponse;
                    }
                }
            }

            if (pairResponse == null || pairResponse.Paired != 1)
            {
                outputTextBox.Text += "Pairing failed.\n";
                return;
            }

            // Decode the server's response and subsequent challenge.
            byte[] encryptedServerChallengeResponse = HexToBytes(pairResponse.ChallengeResponse);
            byte[] decryptedServerChallengeResponse = DoAesCipher(false, aesKey, encryptedServerChallengeResponse);

            byte[] serverResponse  = new byte[hashDigestSize];
            byte[] serverChallenge = new byte[16];
            Array.Copy(decryptedServerChallengeResponse, serverResponse, hashDigestSize);
            Array.Copy(decryptedServerChallengeResponse, hashDigestSize, serverChallenge, 0, 16);

            // Using another 16 byte secret, compute a challenge response hash using the secret,
            // our certificate signature, and the challenge.
            byte[] clientSecret          = GenerateRandomBytes(16);
            byte[] challengeResponseHash =
                HashData(
                    hashAlgorithm,
                    ConcatenateByteArrays(serverChallenge, certificate.GetSignature(), clientSecret));
            byte[] encryptedChallengeResponse = DoAesCipher(true, aesKey, challengeResponseHash);

            await Task.Delay(2000);

            // Send the challenge response to the server.
            // TODO: Call should have a timeout.
            uriString =
                string.Format(
                    "http://{0}:47989/pair?uniqueid={1}&uuid={2}&devicename=roth&updateState=1&serverchallengeresp={3}",
                    ipAddress,
                    BytesToHex(uniqueId),
                    Guid.NewGuid().ToString("N"),
                    BytesToHex(encryptedChallengeResponse));
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(uriString)))
            {
                using (HttpResponseMessage response = await httpClient.SendRequestAsync(request))
                {
                    outputTextBox.Text = $"Send challenge response status code: {response.StatusCode}\n";
                    string responseContent = await response.Content.ReadAsStringAsync();

                    outputTextBox.Text += responseContent + "\n";
                    using (StringReader reader = new StringReader(responseContent))
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(PairResponse));
                        pairResponse = serializer.Deserialize(new StringReader(responseContent)) as PairResponse;
                    }
                }
            }

            if (pairResponse == null || pairResponse.Paired != 1)
            {
                outputTextBox.Text += "Pairing failed.\n";
                // TODO: Unpair here by calling http://<blah>/unpair?uniqueid={1}&uuid={2}.
                return;
            }

            // Get the server's signed secret.
            byte[] serverSecretResponse = HexToBytes(pairResponse.PairingSecret);
            byte[] serverSecret         = new byte[16];
            byte[] serverSignature      = new byte[256];
            Array.Copy(serverSecretResponse, serverSecret, serverSecret.Length);
            Array.Copy(serverSecretResponse, serverSecret.Length, serverSignature, 0, serverSignature.Length);

            if (!VerifySignature(serverSecret, serverSignature, serverCertificate.GetPublicKey()))
            {
                outputTextBox.Text += "Pairing failed.\n";
                // TODO: Unpair as above.
                return;
            }

            // Ensure the server challenge matched what we expected (the PIN was correct).
            byte[] serverChallengeResponseHash =
                HashData(
                    hashAlgorithm,
                    ConcatenateByteArrays(
                        challenge,
                        serverCertificate.GetSignature(),
                        serverSecret));
            if (!serverChallengeResponseHash.SequenceEqual(serverResponse))
            {
                outputTextBox.Text += "Pairing failed due to wrong pin.\n";
                // TODO: Unpair as above.
                return;
            }

            await Task.Delay(2000);

            // Send the server our signed secret
            // TODO: Call should have a timeout.
            byte[] signedSecret        = SignData(clientSecret, keyPair.Private);
            byte[] clientPairingSecret =
                ConcatenateByteArrays(
                    clientSecret,
                    signedSecret);
            uriString =
                string.Format(
                    "http://{0}:47989/pair?uniqueid={1}&uuid={2}&devicename=roth&updateState=1&clientpairingsecret={3}",
                    ipAddress,
                    BytesToHex(uniqueId),
                    Guid.NewGuid().ToString("N"),
                    BytesToHex(clientPairingSecret));
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(uriString)))
            {
                using (HttpResponseMessage response = await httpClient.SendRequestAsync(request))
                {
                    outputTextBox.Text = $"Send client pairing secret status code: {response.StatusCode}\n";
                    string responseContent = await response.Content.ReadAsStringAsync();

                    outputTextBox.Text += responseContent + "\n";
                    using (StringReader reader = new StringReader(responseContent))
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(PairResponse));
                        pairResponse = serializer.Deserialize(new StringReader(responseContent)) as PairResponse;
                    }
                }
            }

            if (pairResponse == null || pairResponse.Paired != 1)
            {
                outputTextBox.Text += "Pairing failed.\n";
                // TODO: Unpair as above.
                return;
            }

            await Task.Delay(2000);

            // Do the initial challenge (seems neccessary for us to show as paired).
            // TODO: Call should have a timeout.
            uriString =
                string.Format(
                    "https://{0}:47984/pair?uniqueid={1}&uuid={2}&devicename=roth&updateState=1&phrase=pairchallenge",
                    ipAddress,
                    BytesToHex(uniqueId),
                    Guid.NewGuid().ToString("N"));
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, new Uri(uriString)))
            {
                using (HttpResponseMessage response = await httpClient.SendRequestAsync(request))
                {
                    outputTextBox.Text = $"Send pair challenge status code: {response.StatusCode}\n";
                    string responseContent = await response.Content.ReadAsStringAsync();

                    outputTextBox.Text += responseContent + "\n";
                    using (StringReader reader = new StringReader(responseContent))
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(PairResponse));
                        pairResponse = serializer.Deserialize(new StringReader(responseContent)) as PairResponse;
                    }
                }
            }

            if (pairResponse == null || pairResponse.Paired != 1)
            {
                outputTextBox.Text += "Pairing failed.\n";
                // TODO: Unpair as above.
                return;
            }

            await Task.Delay(2000);

            outputTextBox.Text = "Pairing succeeded!\n";
        }
예제 #30
0
        private async void ButtonSync_Click(object sender, RoutedEventArgs args)
        {
            using (new ControlDisabler(ButtonSync))
            {
                var settings = Storage.Settings.Load();
                if (!settings.Valid)
                {
                    await new ErrorContentDialog("Sync not configured, please adjust settings.").ShowAsync();
                    return;
                }
                var certs = await CertificateStores.FindAllAsync(new CertificateQuery { FriendlyName = Constants.ClientCertFriendlyName });

                var cert = certs.Where(c => c.HasPrivateKey).FirstOrDefault();
                if (cert == null)
                {
                    await new ErrorContentDialog("No client certificate configured, please adjust settings.").ShowAsync();
                    return;
                }
                var syncBacklog = await Storage.SqliteStorage.GetSyncBacklog();

                // FIXME: this whole initial sync special case is very ugly - surely there's an easier way to do it in an idempotent way?
                var isInitialSync    = syncBacklog.SyncKey == null;
                var initialSyncPhase = 0;
                // TODO: Handle exceptions
                while (true)
                {
                    Protocol.Message response;
                    using (var stream = new StreamSocket())
                    {
                        stream.Control.ClientCertificate = cert;
                        try
                        {
                            await stream.ConnectAsync(settings.Endpoint, SocketProtectionLevel.Tls12).AsTask().WithTimeout(Constants.SyncTimeoutMillis);

                            // TODO: listen for response in background, see https://docs.microsoft.com/en-us/windows/uwp/launch-resume/support-your-app-with-background-tasks & https://docs.microsoft.com/en-us/windows/uwp/networking/network-communications-in-the-background
                            var request = new Protocol.Message(new Dictionary <string, string>
                            {
                                { "type", "sync" },
                                { "org", settings.Organization },
                                { "user", settings.User },
                                { "key", settings.Key },
                                { "client", "WPTaskClient 0.1.0" },
                                { "protocol", "v1" },
                            }, isInitialSync && initialSyncPhase == 0 ? "" : syncBacklog.ToString()); // must not send local changes on initial sync
                            await request.ToStream(stream.OutputStream.AsStreamForWrite()).WithTimeout(Constants.SyncTimeoutMillis);

                            response = await Protocol.Message.FromStream(stream.InputStream.AsStreamForRead()).WithTimeout(Constants.SyncTimeoutMillis);
                        }
                        catch (TimeoutException)
                        {
                            await new ErrorContentDialog("timeout during sync").ShowAsync();
                            return;
                        }
                    }
                    if (!response.Header.TryGetValue("code", out string code))
                    {
                        await new ErrorContentDialog("No status in sync response!").ShowAsync();
                        return;
                    }
                    if (code == "201") // no change
                    {
                        return;
                    }
                    if (code != "200")
                    {
                        if (response.Header.TryGetValue("status", out string status))
                        {
                            await new ErrorContentDialog(string.Format("Sync response had status {0}: {1}!", code, status)).ShowAsync();
                        }
                        else
                        {
                            await new ErrorContentDialog(string.Format("Sync response had status {0}!", code)).ShowAsync();
                        }
                        return;
                    }
                    string syncKey = null;
                    try
                    {
                        foreach (var line in response.Body.Split('\n')) // I wish there was an easy lazy way to do this (a lazy lazy way, if you will)
                        {
                            if (line.Length == 0)
                            {
                                continue;
                            }
                            if (line[0] == '{')
                            {
                                Data.Task task;
                                try
                                {
                                    task = Data.Task.FromJson(JsonObject.Parse(line));
                                }
                                catch (Exception e)
                                {
                                    await new ErrorContentDialog(e).ShowAsync();
                                    return;
                                }
                                // TODO: Batch
                                await Storage.SqliteStorage.UpsertTask(task, false);
                            }
                            else if (GUIDRegex.IsMatch(line))
                            {
                                syncKey = line;
                            }
                            else
                            {
                                await new ErrorContentDialog(string.Format("unexpected line: {0}", line)).ShowAsync();
                                return;
                            }
                        }
                    }
                    finally
                    {
                        await UpdateTasks();
                    }
                    if (syncKey == null)
                    {
                        await new ErrorContentDialog("Sync response contained no sync key!").ShowAsync();
                        return;
                    }
                    await Storage.SqliteStorage.SetSyncKey(syncKey);

                    syncBacklog.SyncKey = syncKey;

                    if (isInitialSync && initialSyncPhase < 1)
                    {
                        initialSyncPhase++;
                        // run again, this time syncing our initial local changes
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }