Exemple #1
0
        /// <summary>
        /// Encypts a string using a key signed by a KeyCredential.
        /// </summary>
        /// <param name="strClearText">Text to encrypt.</param>
        /// <param name="rResult">KeyCredential object used to sign a key to encrypt the text.</param>
        /// <returns>Encrypted text.</returns>
        internal static async Task <string> Encrypt(ProtectedString ps, KeyCredentialRetrievalResult rResult)
        {
            Assembly assembly  = Assembly.GetExecutingAssembly();
            var      attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
            var      id        = attribute.Value;                                         // Any text can be used, it will be signed with the KeyCredential to encrypt the string
            IBuffer  buffMsg   = CryptographicBuffer.ConvertStringToBinary(id, encoding); // converted to an IBuffer

            // The actual Signing of the string
            KeyCredentialOperationResult opResult = await rResult.Credential.RequestSignAsync(buffMsg);

            IBuffer signedData = opResult.Result;

            // Creation of the key with the signed string
            SymmetricKeyAlgorithmProvider provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7);
            CryptographicKey myKey = provider.CreateSymmetricKey(signedData);

            // Encryption of the data using the key created (mKey)
            var     pb            = ps.ReadUtf8();
            IBuffer buffClear     = CryptographicBuffer.CreateFromByteArray(pb);
            IBuffer buffProtected = CryptographicEngine.Encrypt(myKey, buffClear, null);

            buffClear = null;
            MemUtil.ZeroByteArray(pb);
            return(CryptographicBuffer.EncodeToBase64String(buffProtected));
        }
Exemple #2
0
        private static async Task <bool> RequestSignAsync(Guid userId, KeyCredentialRetrievalResult openKeyResult)
        {
            // Calling userKey.RequestSignAsync() prompts the uses to enter the PIN or use Biometrics (Windows Hello).
            // The app would use the private key from the user account to sign the sign-in request (challenge)
            // The client would then send it back to the server and await the servers response.
            IBuffer       challengeMessage          = AuthService.AuthService.Instance.PassportRequestChallenge();
            KeyCredential userKey                   = openKeyResult.Credential;
            KeyCredentialOperationResult signResult = await userKey.RequestSignAsync(challengeMessage);

            if (signResult.Status == KeyCredentialStatus.Success)
            {
                // If the challenge from the server is signed successfully
                // send the signed challenge back to the server and await the servers response
                return(AuthService.AuthService.Instance.SendServerSignedChallenge(
                           userId, Helpers.GetDeviceId(), signResult.Result.ToArray()));
            }
            else if (signResult.Status == KeyCredentialStatus.UserCanceled)
            {
                // User cancelled the Windows Hello PIN entry.
            }
            else if (signResult.Status == KeyCredentialStatus.NotFound)
            {
                // Must recreate Windows Hello key
            }
            else if (signResult.Status == KeyCredentialStatus.SecurityDeviceLocked)
            {
                // Can't use Windows Hello right now, remember that hardware failed and suggest restart
            }
            else if (signResult.Status == KeyCredentialStatus.UnknownError)
            {
                // Can't use Windows Hello right now, try again later
            }

            return(false);
        }
Exemple #3
0
        private async Task <IBuffer> GetPassportAuthenticationMessage(IBuffer message, string accountId)
        {
            KeyCredentialRetrievalResult openKeyResult = await KeyCredentialManager.OpenAsync(accountId);

            if (openKeyResult.Status == KeyCredentialStatus.Success)
            {
                KeyCredential userKey   = openKeyResult.Credential;
                IBuffer       publicKey = userKey.RetrievePublicKey();

                KeyCredentialOperationResult signResult = await userKey.RequestSignAsync(message);

                if (signResult.Status == KeyCredentialStatus.Success)
                {
                    return(signResult.Result);
                }
                else if (signResult.Status == KeyCredentialStatus.UserCanceled)
                {
                    // User cancelled the Passport PIN entry.
                    //
                    // We will return null below this and the username/password
                    // sign in form will show.
                }
                else if (signResult.Status == KeyCredentialStatus.NotFound)
                {
                    // Must recreate Passport key
                }
                else if (signResult.Status == KeyCredentialStatus.SecurityDeviceLocked)
                {
                    // Can't use Passport right now, remember that hardware failed and suggest restart
                }
                else if (signResult.Status == KeyCredentialStatus.UnknownError)
                {
                    // Can't use Passport right now, try again later
                }

                return(null);
            }
            else if (openKeyResult.Status == KeyCredentialStatus.NotFound)
            {
                // Passport key lost, need to recreate it
                //textblock_PassportStatusText.Text = "Microsoft Passport is almost ready!\nPlease go to Windows Settings and set up a PIN to use it.";
                //grid_PassportStatus.Background = new SolidColorBrush(Color.FromArgb(255, 50, 170, 207));
                //button_PassportSignIn.IsEnabled = false;

                m_passportAvailable = false;
            }
            else
            {
                // Can't use Passport right now, try again later
            }
            return(null);
        }
Exemple #4
0
        private async Task <bool> SignInWithHelloAsync()
        {
            LookupUser();

            // Open the existing user key credential.
            KeyCredentialRetrievalResult retrieveResult = await KeyCredentialManager.OpenAsync(userId);

            if (retrieveResult.Status != KeyCredentialStatus.Success)
            {
                return(false);
            }

            KeyCredential userCredential = retrieveResult.Credential;

            // Request a challenge from the server.
            JsonValue jsonChallenge = await JsonRequest.Create()
                                      .AddString("userId", userId)
                                      .AddString("publicKeyHint", publicKeyHint)
                                      .PostAsync("api/Authentication/RequestChallenge");

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

            // Sign the challenge using the user's KeyCredential.
            IBuffer challengeBuffer = CryptographicBuffer.DecodeFromBase64String(jsonChallenge.GetString());
            KeyCredentialOperationResult opResult = await userCredential.RequestSignAsync(challengeBuffer);

            if (opResult.Status != KeyCredentialStatus.Success)
            {
                return(false);
            }

            // Get the signature.
            IBuffer signatureBuffer = opResult.Result;

            // Send the signature back to the server to confirm our identity.
            // The publicKeyHint tells the server which public key to use to verify the signature.
            JsonValue jsonResult = await JsonRequest.Create()
                                   .AddString("userId", userId)
                                   .AddString("publicKeyHint", publicKeyHint)
                                   .AddString("signature", CryptographicBuffer.EncodeToBase64String(signatureBuffer))
                                   .PostAsync("api/Authentication/SubmitResponse");

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

            return(jsonResult.GetBoolean());
        }
        /// <summary>
        /// Sign a challenge using windows hello
        /// </summary>
        /// <param name="accountId">The id of the account to use</param>
        /// <param name="challenge">The challenge to sign</param>
        /// <exception cref="SignOperationFailedException"></exception>
        /// <exception cref="UserCancelledException"></exception>
        /// <exception cref="AccountNotFoundException"></exception>
        /// <exception cref="UnknownException"></exception>
        /// <exception cref="AggregateException"></exception>
        /// <returns>A passport result, storing the signed challenge in its buffer</returns>
        public static byte[] PassportSign(string accountId, byte[] challenge)
        {
            // Try to open the account
            Task <KeyCredentialRetrievalResult> task           = Task.Run(async() => await KeyCredentialManager.OpenAsync(accountId));
            KeyCredentialRetrievalResult        retrieveResult = task.Result;

            // Check the KeyCredentialRetrievalResult status
            switch (retrieveResult.Status)
            {
            case KeyCredentialStatus.Success:
                // Get the users credential
                KeyCredential userCredential = retrieveResult.Credential;

                // Convert the challenge to an IBuffer and sign the challenge
                IBuffer challengeBuffer = CryptographicBuffer.CreateFromByteArray(challenge);
                Task <KeyCredentialOperationResult> opTask = Task.Run(async() =>
                                                                      await userCredential.RequestSignAsync(challengeBuffer));
                KeyCredentialOperationResult opResult = opTask.Result;

                // Check the KeyCredentialOperationResult status
                if (opResult.Status == KeyCredentialStatus.Success)
                {
                    // Get the signature
                    IBuffer signatureBuffer = opResult.Result;

                    // Copy the signature to the PassportResult's buffer
                    CryptographicBuffer.CopyToByteArray(signatureBuffer, out byte[] buffer);
                    // The operation was successful
                    return(buffer);
                }
                else
                {
                    // The sign operation failed
                    throw new SignOperationFailedException();
                }

            case KeyCredentialStatus.UserCanceled:
                // User cancelled the Passport enrollment process
                throw new UserCancelledException();

            case KeyCredentialStatus.NotFound:
                // The account was not found
                throw new AccountNotFoundException();

            default:
                // An unknown error occurred
                throw new UnknownException();
            }
        }
Exemple #6
0
        /// <summary>
        /// Attempts to sign a message using the Passport key on the system for the accountId passed.
        /// </summary>
        /// <param name="message">The message to be signed</param>
        /// <param name="accountId">The account id for the Passport key we are using to sign</param>
        /// <returns>Boolean representing if creating the Passport authentication message succeeded</returns>
        private async Task <IBuffer> GetPassportAuthenticationMessage(IBuffer message, string accountId)
        {
            KeyCredentialRetrievalResult openKeyResult = await KeyCredentialManager.OpenAsync(accountId);

            if (openKeyResult.Status == KeyCredentialStatus.Success)
            {
                KeyCredential userKey   = openKeyResult.Credential;
                IBuffer       publicKey = userKey.RetrievePublicKey();

                KeyCredentialOperationResult signResult = await userKey.RequestSignAsync(message);

                if (signResult.Status == KeyCredentialStatus.Success)
                {
                    return(signResult.Result);
                }
                else if (signResult.Status == KeyCredentialStatus.UserCanceled)
                {
                    // User cancelled the Passport PIN entry.
                    //
                    // We will return null below this and the username/password
                    // sign in form will show.
                }
                else if (signResult.Status == KeyCredentialStatus.NotFound)
                {
                    // Must recreate Passport key
                }
                else if (signResult.Status == KeyCredentialStatus.SecurityDeviceLocked)
                {
                    // Can't use Passport right now, remember that hardware failed and suggest restart
                }
                else if (signResult.Status == KeyCredentialStatus.UnknownError)
                {
                    // Can't use Passport right now, try again later
                }

                return(null);
            }
            else if (openKeyResult.Status == KeyCredentialStatus.NotFound)
            {
                // Passport key lost, need to recreate it
            }
            else
            {
                // Can't use Passport right now, try again later
            }
            return(null);
        }
        /// <summary>
        /// 认证用户授权
        /// </summary>
        /// <returns></returns>
        public static async Task <AuthenticatorState> VerifyUserAsync()
        {
            if (await CheckSupportAsync().ConfigureAwait(false))
            {
                if (ApplicationData.Current.LocalSettings.Values["WindowsHelloPublicKeyForUser"] is string PublicKey)
                {
                    KeyCredentialRetrievalResult RetrievalResult = await KeyCredentialManager.OpenAsync(CredentialName);

                    switch (RetrievalResult.Status)
                    {
                    case KeyCredentialStatus.Success:
                    {
                        KeyCredentialOperationResult OperationResult = await RetrievalResult.Credential.RequestSignAsync(CryptographicBuffer.ConvertStringToBinary(ChallengeText, BinaryStringEncoding.Utf8));

                        if (OperationResult.Status == KeyCredentialStatus.Success)
                        {
                            var Algorithm = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaSignPkcs1Sha256);
                            var Key       = Algorithm.ImportPublicKey(CryptographicBuffer.DecodeFromHexString(PublicKey));
                            return(CryptographicEngine.VerifySignature(Key, CryptographicBuffer.ConvertStringToBinary(ChallengeText, BinaryStringEncoding.Utf8), OperationResult.Result) ? AuthenticatorState.VerifyPassed : AuthenticatorState.VerifyFailed);
                        }
                        else
                        {
                            return(AuthenticatorState.UnknownError);
                        }
                    }

                    case KeyCredentialStatus.NotFound:
                    {
                        return(AuthenticatorState.CredentialNotFound);
                    }

                    default:
                    {
                        return(AuthenticatorState.UnknownError);
                    }
                    }
                }
                else
                {
                    return(AuthenticatorState.UserNotRegistered);
                }
            }
            else
            {
                return(AuthenticatorState.WindowsHelloUnsupport);
            }
        }
        public async Task <bool> AuthenticateAsync()
        {
            // Waits that the app's window gets the focus. This allows to avoid having the icon in the task bar
            // blinking orange when windows hello starts. It might distracts the user.
            await _windowFocusAwaiter.Task.ConfigureAwait(false);

            if (!await IsWindowsHelloEnabledAsync()
                .ConfigureAwait(true)) // run on the current context.
            {
                _logger.LogEvent(AuthenticateEvent, "Success == False; Windows Hello isn't enabled.");
                return(false);
            }

            // Get credentials for current user and app
            KeyCredentialRetrievalResult result = await KeyCredentialManager.OpenAsync(KeyCredentialManagerName);

            if (result.Credential != null)
            {
                // Prompt the user to authenticate.
                KeyCredentialOperationResult signResult = await result.Credential.RequestSignAsync(CryptographicBuffer.ConvertStringToBinary(KeyCredentialManagerName, BinaryStringEncoding.Utf8));

                if (signResult.Status == KeyCredentialStatus.Success)
                {
                    _logger.LogEvent(AuthenticateEvent, "Success == True");
                    return(true);
                }

                _logger.LogEvent(AuthenticateEvent, "Success == False");
                return(false);
            }

            // No previous saved credentials found, let's create them (this will also prompt the user to authenticate).
            KeyCredentialRetrievalResult creationResult = await KeyCredentialManager.RequestCreateAsync(KeyCredentialManagerName, KeyCredentialCreationOption.ReplaceExisting);

            _logger.LogEvent(AuthenticateEvent, $"Success == {creationResult.Status == KeyCredentialStatus.Success}");
            return(creationResult.Status == KeyCredentialStatus.Success);
        }
Exemple #9
0
        /// <summary>
        /// Decypts a string using a key signed by a KeyCredential.
        /// </summary>
        /// <param name="strProtected">Text to decrypt.</param>
        /// <param name="rResult">KeyCredential object used to sign a key to encrypt the text.</param>
        /// <returns>Decrypted text.</returns>
        internal static async Task <ProtectedString> Decrypt(string strProtected, KeyCredentialRetrievalResult rResult)
        {
            // The same text must be used to decrypt the data
            Assembly assembly  = Assembly.GetExecutingAssembly();
            var      attribute = (GuidAttribute)assembly.GetCustomAttributes(typeof(GuidAttribute), true)[0];
            var      id        = attribute.Value;
            IBuffer  buffMsg   = CryptographicBuffer.ConvertStringToBinary(id, encoding);

            // Start a background thread to ensure Windows Security prompt is opened in foreground
            var _ = Task.Factory.StartNew(() => EnsureForeground());

            // The actual Signing of the string
            KeyCredentialOperationResult opResult = await rResult.Credential.RequestSignAsync(buffMsg);

            if (opResult.Status == KeyCredentialStatus.Success)
            {
                IBuffer signedData = opResult.Result;

                // Creation of the key with the signed string
                SymmetricKeyAlgorithmProvider provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesEcbPkcs7);
                CryptographicKey myKey = provider.CreateSymmetricKey(signedData);

                // Decryption of the data using the key created (mKey)
                IBuffer buffProtected = CryptographicBuffer.DecodeFromBase64String(strProtected);
                CryptographicBuffer.CopyToByteArray(CryptographicEngine.Decrypt(myKey, buffProtected, null), out var ba);
                ProtectedString ps = new ProtectedString(true, ba);
                MemUtil.ZeroByteArray(ba);
                return(ps);
            }
            else
            {
                WinHelloUnlockExt.opened = true;
                WinHelloErrors(opResult.Status, "Error decrypting the data: ");
                return(null);
            }
        }
        private async void Path_Auth()
        {
            // check if KeyCredentialManager can be used
            if (await KeyCredentialManager.IsSupportedAsync() == false)
            {
                await(new MessageDialog("KeyCredentialManager not supported")).ShowAsync();
                return;
            }

            // retrieve private key for sign
            KeyCredentialRetrievalResult res =
                await KeyCredentialManager.OpenAsync("key1");

            if (res.Status == KeyCredentialStatus.Success)
            {
                //
                // If it is present, we request sign for some data
                //

                // convert string to binary buffer
                var inputbuf =
                    CryptographicBuffer.ConvertStringToBinary(
                        "Test Data 1", BinaryStringEncoding.Utf8);

                // sign using retrieved private key
                // (Windows Hello is diplayed here !)
                KeyCredentialOperationResult signRes = await res.Credential.RequestSignAsync(inputbuf);

                //KeyCredentialAttestationResult signRes = await res.Credential.GetAttestationAsync();

                /*
                 * // get the base64 encoded data to cryptographically sign
                 * string base64encSignature =
                 * CryptographicBuffer.EncodeToBase64String(signRes.Result);
                 * await (new MessageDialog(base64encSignature)).ShowAsync();
                 */
                if (signRes.Status == KeyCredentialStatus.Success)
                {
                    // ナビゲーション フレームを使用して前のページに戻ります
                    if (this.Frame != null && this.Frame.CanGoBack)
                    {
                        this.Frame.GoBack();
                    }
                    else if (this.Frame != null)
                    {
                        //this.Frame.Navigate(typeof(Browser.MainBrowser));
                        this.Frame.Navigate(typeof(Browser.Browser1));
                    }
                }
                else
                {
                    // get the base64 encoded data to cryptographically sign
                    //string base64encSignature = CryptographicBuffer.EncodeToBase64String(signRes.Result);
                    await(new MessageDialog("キャンセルしました")).ShowAsync();
                    //await (new MessageDialog(base64encSignature)).ShowAsync();
                }
            }
            else if (res.Status == KeyCredentialStatus.NotFound)
            {
                //
                // If the credential is not found, we create it.
                //

                // Create the credential
                // (Windows Hello is diplayed here !)
                KeyCredentialRetrievalResult createRes =
                    await KeyCredentialManager.RequestCreateAsync("key1",
                                                                  KeyCredentialCreationOption.ReplaceExisting);

                if (createRes.Status == KeyCredentialStatus.Success)
                {
                    // ナビゲーション フレームを使用して前のページに戻ります
                    if (this.Frame != null && this.Frame.CanGoBack)
                    {
                        this.Frame.GoBack();
                    }
                    else if (this.Frame != null)
                    {
                        //this.Frame.Navigate(typeof(Browser.MainBrowser));
                        this.Frame.Navigate(typeof(Browser.Browser1));
                    }
                }
                else
                {
                    // get the base64 encoded data to cryptographically sign
                    //string base64encSignature = CryptographicBuffer.EncodeToBase64String(signRes.Result);
                    await(new MessageDialog("キャンセルしました")).ShowAsync();
                    //await (new MessageDialog(base64encSignature)).ShowAsync();
                }

                /*
                 * // if the status is success, retrieve the public key.
                 * if (createRes.Status == KeyCredentialStatus.Success)
                 * {
                 * var pubKey = createRes.Credential.RetrievePublicKey();
                 * AsymmetricKeyAlgorithmProvider alg =
                 *  AsymmetricKeyAlgorithmProvider.OpenAlgorithm(
                 *    AsymmetricAlgorithmNames.RsaPkcs1);
                 * CryptographicKey ckey = alg.ImportPublicKey(pubKey);
                 * // for ex, CryptographicEngine.VerifySignature() using this CryptographicKey
                 * // (This time, just showing the keysize)
                 * var dialog = new MessageDialog(string.Format("Key size is {0}", ckey.KeySize));
                 * await dialog.ShowAsync();
                 * }
                 */
            }
            else
            {
                await(new MessageDialog("Unknown error !")).ShowAsync();
            }
        }
Exemple #11
0
        public static async Task <bool> SignInWithHelloAsync(string userId, KeyCredentialRetrievalResult retrieveResult = null)
        {
            // Open the existing user key credential.
            if (retrieveResult == null)
            {
                retrieveResult = await KeyCredentialManager.OpenAsync(userId);
            }

            if (retrieveResult.Status != KeyCredentialStatus.Success)
            {
                return(false);
            }

            KeyCredential userCredential = retrieveResult.Credential;

            string publicKeyHint = CalculatePublicKeyHint(userCredential.RetrievePublicKey());

            var challengeResult = await PlayFab.PlayFabClientAPI.GetWindowsHelloChallengeAsync(new GetWindowsHelloChallengeRequest
            {
                PublicKeyHint = publicKeyHint,
                TitleId       = PlayFab.PlayFabSettings.TitleId
            });

            if (challengeResult.Error != null)
            {
                // TODO: Failed to get a challenge, handle the error
                MessageDialog message = new MessageDialog($"Error during getting challenge: {challengeResult.Error.Error}");
                await message.ShowAsync();

                return(false);
            }

            // Sign the challenge using the user's KeyCredential.
            IBuffer challengeBuffer = CryptographicBuffer.DecodeFromBase64String(challengeResult.Result.Challenge);
            KeyCredentialOperationResult opResult = await userCredential.RequestSignAsync(challengeBuffer);

            if (opResult.Status != KeyCredentialStatus.Success)
            {
                MessageDialog message = new MessageDialog("Failed to have user sign the challenge string.");
                await message.ShowAsync();

                return(false);
            }

            // Get the signature.
            IBuffer signatureBuffer = opResult.Result;

            // Send the signature back to the server to confirm our identity.
            // The publicKeyHint tells the server which public key to use to verify the signature.
            var loginResult = await PlayFab.PlayFabClientAPI.LoginWithWindowsHelloAsync(new LoginWithWindowsHelloRequest
            {
                ChallengeSignature = CryptographicBuffer.EncodeToBase64String(signatureBuffer),
                PublicKeyHint      = publicKeyHint
            });

            if (loginResult.Error != null)
            {
                MessageDialog message = new MessageDialog($"Error during login: {loginResult.Error.Error}");
                await message.ShowAsync();

                return(false);
            }

            return(true);
        }