/*
         * Private Helper method
         * will import certificate into App's key store
         */
        private async Task <Certificate> ImportCertificateHelperAsync(string certFolder, string certFileName)
        {
            StorageFolder packageLocation   = Windows.ApplicationModel.Package.Current.InstalledLocation;
            StorageFolder certificateFolder = await packageLocation.GetFolderAsync(certFolder);

            StorageFile certificate = await certificateFolder.GetFileAsync(certFileName);

            IBuffer buffer = await Windows.Storage.FileIO.ReadBufferAsync(certificate);

            string encodedString = Windows.Security.Cryptography.CryptographicBuffer.EncodeToBase64String(buffer);

            System.Diagnostics.Debug.WriteLine("Encoded Certificate: " + encodedString);

            await CertificateEnrollmentManager.ImportPfxDataAsync(
                encodedString,
                certificatePassword,
                ExportOption.NotExportable,
                KeyProtectionLevel.NoConsent,
                InstallOptions.DeleteExpired,
                "userCert");

            IReadOnlyList <Windows.Security.Cryptography.Certificates.Certificate> certs = await Windows.Security.Cryptography.Certificates.CertificateStores.FindAllAsync(new Windows.Security.Cryptography.Certificates.CertificateQuery()
            {
                FriendlyName = "userCert"
            });

            this.certificate = certs.FirstOrDefault();

            System.Diagnostics.Debug.WriteLine("Certificate ready for user (CN): " + this.certificate.Subject);

            return(certs.FirstOrDefault());
        }
예제 #2
0
        private async void InstallClientCert_Click(object sender, RoutedEventArgs e)
        {
            InstallClientCertCompleted.Visibility = Visibility.Collapsed;

            try
            {
                Uri uri  = new Uri("ms-appx:///Assets/tempClientCert.pfx");
                var file = await StorageFile.GetFileFromApplicationUriAsync(uri);

                IBuffer buffer = await FileIO.ReadBufferAsync(file);

                //byte[] bytes;
                //CryptographicBuffer.CopyToByteArray(buffer, out bytes);

                string pfxData = CryptographicBuffer.EncodeToBase64String(buffer);

                // UserCertificateEnrollmentManager requires 'Shared User certificates' capability.
                //await CertificateEnrollmentManager.UserCertificateEnrollmentManager.ImportPfxDataAsync(...);

                await CertificateEnrollmentManager.ImportPfxDataAsync(
                    pfxData,
                    String.Empty, // password
                    ExportOption.Exportable,
                    KeyProtectionLevel.NoConsent,
                    InstallOptions.None,
                    "tempClientCert");
            }
            catch (Exception ex)
            {
                DisplayException(ex);
            }

            InstallClientCertCompleted.Visibility = Visibility.Visible;
        }
        /// <summary>
        /// Import an existing pfx certificate
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void ImportPfx_Click(object sender, RoutedEventArgs e)
        {
            TextBlock outputTextBlock = rootPage.FindName("OutputTextBlock") as TextBlock;

            try
            {
                outputTextBlock.Text = "Importing PFX certificate ...";

                // Load the pfx certificate from resource string.
                ResourceLoader rl             = new ResourceLoader();
                string         pfxCertificate = rl.GetString("Certificate");

                string password     = "******"; //password to access the certificate in PFX format
                string friendlyName = "test pfx certificate";

                //call Certificate Enrollment funciton importPFXData to install the certificate
                await CertificateEnrollmentManager.ImportPfxDataAsync(pfxCertificate,
                                                                      password,
                                                                      ExportOption.NotExportable,
                                                                      KeyProtectionLevel.NoConsent,
                                                                      InstallOptions.None,
                                                                      friendlyName);

                outputTextBlock.Text += "\nCertificate installation succeeded. The certificate is in the appcontainer Personal certificate store";
            }
            catch (Exception ex)
            {
                outputTextBlock.Text += "\nCertificate installation failed with error: " + ex.ToString();
            }
        }
예제 #4
0
        private async void ButtonSave_Click(object sender, RoutedEventArgs args)
        {
            using (new ControlDisabler(ButtonSave))
            {
                if (clientCert != null)
                {
                    try
                    {
                        await CertificateEnrollmentManager.ImportPfxDataAsync(clientCert, clientCertPassphrase, ExportOption.NotExportable, KeyProtectionLevel.NoConsent, InstallOptions.None, Constants.ClientCertFriendlyName);

                        clientCert = null;
                    }
                    catch (Exception e)
                    {
                        await new ErrorContentDialog(e).ShowAsync();
                        return;
                    }
                }
                var settings = new Storage.Settings {
                    Server       = serverAddress.Text,
                    Organization = authOrg.Text,
                    User         = authUser.Text,
                    Key          = authKey.Password,
                };
                settings.Store();
                if (Window.Current.Content is Frame rootFrame && rootFrame.CanGoBack)
                {
                    rootFrame.GoBack();
                }
            }
        }
예제 #5
0
        private async Task AddToWinCertStore()
        {
            Pkcs12Store store        = new Pkcs12Store();
            string      friendlyName = "Limelight-Client";
            var         certEntry    = new X509CertificateEntry(cert);

            store.SetCertificateEntry(friendlyName, certEntry);

            var keyEntry = new AsymmetricKeyEntry(keyPair.Private);

            store.SetKeyEntry(friendlyName, keyEntry, new[] { certEntry });

            // Copy the Pkcs12Store to a stream using an arbitrary password
            const string password = "******";
            var          stream   = new MemoryStream();

            store.Save(stream, password.ToCharArray(), new SecureRandom());

            // Write to .PFX string
            byte[] arr = stream.ToArray();

            IBuffer buf = arr.AsBuffer();
            string  pfx = CryptographicBuffer.EncodeToBase64String(buf);

            await CertificateEnrollmentManager.ImportPfxDataAsync(pfx, password, ExportOption.NotExportable, KeyProtectionLevel.NoConsent, InstallOptions.None, friendlyName);
        }
예제 #6
0
        private async void SetClientCertificate(ClientCertificate certificate)
        {
            if (certificate == null)
            {
                return;
            }

            try
            {
                var bytes = Convert.FromBase64String(certificate.RawData);
            }
            catch (Exception ex)
            {
                throw new HttpRequestException(FailureMessages.InvalidRawData, ex);
            }

            this.ClientCertificateOptions = ClientCertificateOption.Automatic;

            await CertificateEnrollmentManager.ImportPfxDataAsync(certificate.RawData,
                                                                  certificate.Passphrase,       // the password is blank, but you can specify one here
                                                                  ExportOption.NotExportable,   // there is no reason to keep the certificate Exportable
                                                                  KeyProtectionLevel.NoConsent, // whether any consent is required
                                                                  InstallOptions.DeleteExpired, // no installation options
                                                                  Package.Current.DisplayName);
        }
        private async Task <Certificate> InstallClientCertificateAsync()
        {
            // Load the certificate from the clientCert.pfx file packaged with this sample.
            // This certificate has been signed with a trusted root certificate installed on the server.
            // The installation is done by running the setupServer.ps1 file, which should have been done
            // before running the app.
            // WARNING: Including a pfx file in the app package violates the Windows Store
            // certification requirements. We are shipping the pfx file with the package for demonstrating
            // the usage of client certificates. Apps that will be published through Windows Store
            // need to use other approaches to obtain a client certificate.
            StorageFile clientCertFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri(ClientCertUriPath));

            IBuffer buffer = await FileIO.ReadBufferAsync(clientCertFile);

            AppendOutputLine("Reading certificate succeeded.");

            string clientCertData = Windows.Security.Cryptography.CryptographicBuffer.EncodeToBase64String(buffer);

            try
            {
                // Install the certificate to the app's certificate store.
                // The app certificate store is removed when the app is uninstalled.

                //To install a certificate to the CurrentUser\MY store, which is not app specific,
                // you need to use CertificateEnrollmentManager.UserCertificateEnrollmentManager.ImportPfxDataAsync().
                // In order to call that method, an app must have the "sharedUserCertificates" capability.
                // There are two ways to add this capability:
                //
                // 1. You can double click on the Package.appxmanifest file from the
                // solution explorer, select the "Capabilities" tab in the opened page, and then check the
                // "Shared User Certificates" box from the capabilities list.
                // 2. You can right click on the Package.appxmanifest file from the
                // solution explorer, select "View Code", and add "sharedUserCertificates" under the <Capabilities>
                // element directly.
                // Package.appxmanifest in this sample shows this capability commented out.
                //
                // The certificate will remain even when the app is uninstalled.
                await CertificateEnrollmentManager.ImportPfxDataAsync(
                    clientCertData,
                    ClientCertPassword,
                    ExportOption.Exportable,
                    KeyProtectionLevel.NoConsent,
                    InstallOptions.DeleteExpired,
                    ClientCertFriendlyName);

                AppendOutputLine("Installing certificate succeeded.");

                // Return the certificate we just instaled.
                return(await FindCertificateFromStoreAsync());
            }
            catch (Exception ex)
            {
                // This can happen if the certificate has already expired.
                AppendOutputLine("Installing certificate failed with" + ex.Message);
                return(null);
            }
        }
예제 #8
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;
            }
        }
예제 #9
0
        /// <summary>
        /// Import an existing pfx certificate
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void RunSample_Click(object sender, RoutedEventArgs e)
        {
            CheckBox    storeSelectionCheckbox = rootPage.FindName("UserStoreCheckBox") as CheckBox;
            TextBlock   outputTextBlock        = rootPage.FindName("OutputTextBlock") as TextBlock;
            PasswordBox pfxPasswordBox         = rootPage.FindName("PfxPasswordBox") as PasswordBox;

            if (String.IsNullOrEmpty(pfxCertificate))
            {
                outputTextBlock.Text = "Please select a valid PFX file\n";
                return;
            }

            try
            {
                // Import PFX
                outputTextBlock.Text = "Importing PFX certificate ...";

                string friendlyName = "test pfx certificate";
                pfxPassword = pfxPasswordBox.Password;

                if (true == storeSelectionCheckbox.IsChecked)
                {
                    // target store is User's Certificate Store
                    // call User Certificate Enrollment function importPfxData to install the certificate
                    await CertificateEnrollmentManager.UserCertificateEnrollmentManager.ImportPfxDataAsync(
                        pfxCertificate,
                        pfxPassword,
                        ExportOption.NotExportable,
                        KeyProtectionLevel.NoConsent,
                        InstallOptions.None,
                        friendlyName);

                    outputTextBlock.Text += "\nCertificate installation succeeded. The certificate is in the User's certificate store";
                }
                else
                {
                    // target store is App's certificate store
                    // call Certificate Enrollment function importPFXData to install the certificate
                    await CertificateEnrollmentManager.ImportPfxDataAsync(
                        pfxCertificate,
                        pfxPassword,
                        ExportOption.NotExportable,
                        KeyProtectionLevel.NoConsent,
                        InstallOptions.None,
                        friendlyName);

                    outputTextBlock.Text += "\nCertificate installation succeeded. The certificate is in the App's certificate store";
                }
            }
            catch (Exception ex)
            {
                outputTextBlock.Text += "\nCertificate installation failed with error: " + ex.ToString();
            }
        }
예제 #10
0
        public void ManagementClientReturnsLocationList()
        {
            // Import certificate
            CertificateEnrollmentManager.ImportPfxDataAsync(_certificateString, _certificatePassword, ExportOption.NotExportable,
                                                            KeyProtectionLevel.NoConsent, InstallOptions.None,
                                                            "test").AsTask().Wait();

            var credentials = new CertificateCloudCredentials(_subscription);
            var client      = new ManagementClient(credentials);
            var result      = client.Locations.List();

            Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
            Assert.IsTrue(result.Locations.Count > 0);
        }
예제 #11
0
        private async void SetClientCertificate(ClientCertificate certificate)
        {
            if (certificate == null)
            {
                return;
            }

            this.ClientCertificateOptions = ClientCertificateOption.Automatic;

            await CertificateEnrollmentManager.ImportPfxDataAsync(certificate.RawData,
                                                                  certificate.Passphrase,       // the password is blank, but you can specify one here
                                                                  ExportOption.NotExportable,   // there is no reason to keep the certificate Exportable
                                                                  KeyProtectionLevel.NoConsent, // whether any consent is required
                                                                  InstallOptions.DeleteExpired, // no installation options
                                                                  Package.Current.DisplayName);
        }
예제 #12
0
        public async Task InstallAsync(string certResponse)
        {
            #region Bouncy castle PKCS #12 cert file generation
            var data = Convert.FromBase64String(certResponse);

            var parser = new X509CertificateParser();
            var cert   = parser.ReadCertificate(data);

            Pkcs12Store          store     = new Pkcs12StoreBuilder().Build();
            X509CertificateEntry certEntry = new X509CertificateEntry(cert);
            store.SetCertificateEntry(cert.SubjectDN.ToString(), certEntry); // use DN as the Alias.

            AsymmetricKeyEntry keyEntry = new AsymmetricKeyEntry(_privateKey);
            store.SetKeyEntry(cert.SubjectDN.ToString() + "_key", keyEntry, new X509CertificateEntry[] { certEntry }); //

            string pfx      = string.Empty;
            string password = "";
            using (MemoryStream ms = new MemoryStream())
            {
                store.Save(ms, password.ToCharArray(), _random);

                ms.Position = 0;
                await _storage.SetAsync("accessCert", ms.GetWindowsRuntimeBuffer());

                StreamReader streamReader = new StreamReader(ms);
                // Write to .PFX string
                byte[] arr = ms.ToArray();

                pfx = CryptographicBuffer.EncodeToBase64String(arr.AsBuffer());
            }
            #endregion
            await _storage.SetAsync(StorageKeyNames.PrivateKey, pfx);

            await CertificateEnrollmentManager.ImportPfxDataAsync(pfx, password, ExportOption.NotExportable, KeyProtectionLevel.NoConsent, InstallOptions.None, "MAG_CERT");

            // Store the registered cert subject
            if (cert.SubjectDN != null)
            {
                var valueList = cert.SubjectDN.GetValueList(X509Name.CN);
                if (valueList.Count > 0)
                {
                    await _storage.SetAsync(StorageKeyNames.RegisteredCertSubject, (string)valueList[0]);
                }
            }
        }
예제 #13
0
파일: MainPage.xaml.cs 프로젝트: Bigsby/PoC
        private static async Task InstallCertificate(string filePath, string friendlyName)
        {
            //string certPath = @"Assets\BigsbyClientCert.pfx";
            StorageFile file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(filePath);

            IBuffer buffer = await FileIO.ReadBufferAsync(file);

            string certData = CryptographicBuffer.EncodeToBase64String(buffer);

            // Will ask the user if they want this app to install the certificate if its not already installed.
            await CertificateEnrollmentManager.ImportPfxDataAsync(
                certData,
                "",
                ExportOption.NotExportable,
                KeyProtectionLevel.NoConsent,
                InstallOptions.None,
                friendlyName);
        }
예제 #14
0
        public async Task <Certificate> GetIfExistsAsync()
        {
            var Certificate = await GetAsync();

            try
            {
                if (Certificate == null)
                {
                    string pfx = await _storage.GetTextAsync(StorageKeyNames.PrivateKey);

                    if (pfx != null)
                    {
                        await CertificateEnrollmentManager.ImportPfxDataAsync(pfx, string.Empty, ExportOption.NotExportable, KeyProtectionLevel.NoConsent, InstallOptions.None, "MAG_CERT");
                    }
                    Certificate = await GetAsync();
                }
            }
            catch (Exception)
            {
            }
            return(Certificate);
        }
예제 #15
0
        // Load a client certificate for accessing a PKI-secured server
        private async void LoadClientCertButton_Click(object sender, RoutedEventArgs e)
        {
            // Show the progress bar and a message
            ProgressStatus.Visibility = Visibility.Visible;
            MessagesTextBlock.Text    = "Loading certificate ...";

            try
            {
                // Import the certificate by providing:
                //   -the encoded certificate string,
                //   -the password (entered by the user)
                //   -certificate options (export, key protection, install)
                //   -a friendly name (the name of the pfx file)
                await CertificateEnrollmentManager.ImportPfxDataAsync(
                    _certificateString,
                    CertPasswordBox.Password,
                    ExportOption.Exportable,
                    KeyProtectionLevel.NoConsent,
                    InstallOptions.None,
                    _certificateName);

                // Report success
                MessagesTextBlock.Text = "Client certificate was successfully imported";
            }
            catch (Exception ex)
            {
                // Report error
                MessagesTextBlock.Text = "Error loading certificate: " + ex.Message;
            }
            finally
            {
                // Hide progress bar and the password controls
                ProgressStatus.Visibility = Visibility.Collapsed;
                HideCertLogin(null, null);
            }
        }
        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";
        }
예제 #17
0
        /// <summary>
        /// Basic settings are configured on the view that is attached to this VM.
        /// </summary>
        /// <param name="screen"></param>
        public BasicSettingsViewModel(IScreen screen)
        {
            HostScreen = screen;

            // Look for a currently loaded cert and update the status...
            // We can't start this b.c. the ToProperty is lazy - and it won't
            // fire until Status is data-bound!
            LookupCertStatus = ReactiveCommand.CreateAsyncTask(a => SecurityUtils.FindCert(SecurityUtils.CERNCertName));
            LookupCertStatus
            .Select(c => c == null ? "No Cert Loaded" : string.Format("Loaded (expires {0})", c.ValidTo.ToLocalTime().ToString("yyyy-MM-dd HH:mm")))
            .ToProperty(this, x => x.Status, out _status, "", RxApp.MainThreadScheduler);

            LookupCertStatus
            .ExecuteAsync()
            .Subscribe();

            // Error and status messages...
            var errors = new Subject <string>();

            errors
            .ToProperty(this, x => x.Error, out _error, "", RxApp.MainThreadScheduler);

            // Given a file and a password, see if we can install it as a cert
            // in our internal repository.
            LoadFiles = ReactiveCommand.Create();
            LoadFiles
            .Subscribe(x => errors.OnNext(""));

            var files = LoadFiles
                        .Cast <Tuple <IReadOnlyList <StorageFile>, string> >();

            files
            .Where(finfo => finfo.Item1 == null || finfo.Item1.Count != 1)
            .Select(f => "Invalid certificate file")
            .Subscribe(errors);

            files
            .Where(finfo => finfo.Item1 != null && finfo.Item1.Count == 1)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Select(mf =>
            {
                // We use this double subscribe because the readBufferAsync and ImportPfxDataAsync often return exceptions.
                // If we let the exception bubble all the way up, it terminates the sequence. Which means if the user entered
                // the wrong password they wouldn't get a chance to try again!
                return(Observable.Return(mf)
                       .SelectMany(async f =>
                {
                    // 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);

                    var fs = f.Item1[0] as StorageFile;
                    var buffer = await FileIO.ReadBufferAsync(fs);
                    var cert = CryptographicBuffer.EncodeToBase64String(buffer);

                    await CertificateEnrollmentManager.ImportPfxDataAsync(cert, f.Item2, ExportOption.NotExportable, KeyProtectionLevel.NoConsent, InstallOptions.DeleteExpired, SecurityUtils.CERNCertName);
                    return Unit.Default;
                }));
            })
            .Subscribe(c => c.Subscribe(
                           g => LookupCertStatus.ExecuteAsync().Subscribe(),
                           e => errors.OnNext(e.Message.TakeFirstLine())
                           ));

            // Set/Get the file expiration policy.
            CacheDecayOptions = ExpirationOptions.GetListExpirationOptions();

            // Get the list of indico api keys we are watching
            // and hook up the MV for doing the api key manipulation
            ApiKeysForIndico = new ReactiveList <IndicoApiKey>();
            ApiKeysForIndico.AddRange(IndicoApiKeyAccess.LoadAllKeys());
            IndicoApiKeyAccess.IndicoApiKeysUpdated
            .Subscribe(_ =>
            {
                using (ApiKeysForIndico.SuppressChangeNotifications())
                {
                    ApiKeysForIndico.Clear();
                    ApiKeysForIndico.AddRange(IndicoApiKeyAccess.LoadAllKeys());
                }
            });

            ShowIndicoApiKey = ReactiveCommand.Create();
            ShowIndicoApiKey
            .Cast <IndicoApiKey>()
            .Select(x => new AddOrUpdateIndicoApiKeyViewModel(x))
            .ToProperty(this, x => x.IndicoApiKey, out _indicoApiKeyVM, new AddOrUpdateIndicoApiKeyViewModel(null));
        }