Exemple #1
0
        /// <summary>
        /// Creates a Passport key on the machine using the _account id passed.
        /// </summary>
        /// <param name="accountId">The _account id associated with the _account that we are enrolling into Passport</param>
        /// <returns>Boolean representing if creating the Passport key succeeded</returns>
        public static async Task <bool> CreatePassportKeyAsync(string accountId)
        {
            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync(accountId, KeyCredentialCreationOption.ReplaceExisting);

            switch (keyCreationResult.Status)
            {
            case KeyCredentialStatus.Success:
                // In the real world authentication would take place on a server.
                // So every time a user migrates or creates a new Microsoft Passport account Passport details should be pushed to the server.
                // The details that would be pushed to the server include:
                // The public key, keyAttesation if available,
                // certificate chain for attestation endorsement key if available,
                // status code of key attestation result: keyAttestationIncluded or
                // keyAttestationCanBeRetrievedLater and keyAttestationRetryType
                // As this sample has no concept of a server it will be skipped for now
                // for information on how to do this refer to the second Passport sample

                //For this sample just return true
                return(true);

            case KeyCredentialStatus.UserCanceled:
                //Debug.WriteLine("User cancelled sign-in process.");
                break;

            case KeyCredentialStatus.NotFound:
                // User needs to setup Microsoft Passport
                //Debug.WriteLine("Microsoft Passport is not setup!\nPlease go to Windows Settings and set up a PIN to use it.");
                break;

            default:
                break;
            }

            return(false);
        }
        /// <summary>
        /// Get the public key of the windiws hello account
        /// </summary>
        /// <param name="accountId">The id of the account to use</param>
        /// <exception cref="UserCancelledException"></exception>
        /// <exception cref="AccountNotFoundException"></exception>
        /// <exception cref="UnknownException"></exception>
        /// <exception cref="AggregateException"></exception>
        /// <returns>A passport result, storing the public key in its buffer</returns>
        public static byte[] GetPublicKey(string accountId)
        {
            // Try to get the account
            Task <KeyCredentialRetrievalResult> task            = Task.Run(async() => await KeyCredentialManager.OpenAsync(accountId));
            KeyCredentialRetrievalResult        retrievalResult = task.Result;

            // Check the KeyCredentialRetrievalResult status
            switch (retrievalResult.Status)
            {
            case KeyCredentialStatus.Success:
                // Get the user's credential
                KeyCredential userCredential = retrievalResult.Credential;

                // Get the public key
                IBuffer publicKey = userCredential.RetrievePublicKey();

                // Copy the public key to the PassportResult's buffer
                CryptographicBuffer.CopyToByteArray(publicKey, out byte[] buffer);

                // The operation was successful
                return(buffer);

            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 #3
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 #4
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 #5
0
        public static async Task <bool> CreatePassportKeyAsync(Guid userId, string username)
        {
            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync(username, KeyCredentialCreationOption.ReplaceExisting);

            switch (keyCreationResult.Status)
            {
            case KeyCredentialStatus.Success:
                Debug.WriteLine("Successfully made key");
                await GetKeyAttestationAsync(userId, keyCreationResult);

                return(true);

            case KeyCredentialStatus.UserCanceled:
                Debug.WriteLine("User cancelled sign-in process.");
                break;

            case KeyCredentialStatus.NotFound:
                // User needs to setup Windows Hello
                Debug.WriteLine("Windows Hello is not setup!\nPlease go to Windows Settings and set up a PIN to use it.");
                break;

            default:
                break;
            }

            return(false);
        }
Exemple #6
0
        private async void tryToCloseWinHello()
        {
            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync("WinHello", KeyCredentialCreationOption.ReplaceExisting);

            var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();

            if (keyCreationResult.Status == KeyCredentialStatus.Success)
            {
                Password.winHelloStatus = false;
                LockButton.IsEnabled    = false;
                Password.WriteWinHelloData();
            }
            else if (keyCreationResult.Status == KeyCredentialStatus.NotFound)
            {
                Password.winHelloStatus = true;
                WHToggle.IsOn           = true;
                MessageDialog message = new MessageDialog(resourceLoader.GetString("WHError1"));
                await message.ShowAsync();
            }
            else if (keyCreationResult.Status == KeyCredentialStatus.UnknownError)
            {
                Password.winHelloStatus = true;
                WHToggle.IsOn           = true;
                MessageDialog message = new MessageDialog(resourceLoader.GetString("WHError2"));
                await message.ShowAsync();
            }
            else
            {
                Password.winHelloStatus = true;
                WHToggle.IsOn           = true;
            }
        }
        private async Task <IBuffer> CreatePassportKeyCredentialAsync()
        {
            // Create a new KeyCredential for the user on the device.
            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync(userId, KeyCredentialCreationOption.ReplaceExisting);

            if (keyCreationResult.Status == KeyCredentialStatus.Success)
            {
                // User has autheniticated with Windows Hello and the key credential is created.
                KeyCredential userKey = keyCreationResult.Credential;
                return(userKey.RetrievePublicKey());
            }
            else if (keyCreationResult.Status == KeyCredentialStatus.NotFound)
            {
                MessageDialog message = new MessageDialog("To proceed, Windows Hello needs to be configured in Windows Settings (Accounts -> Sign-in options)");
                await message.ShowAsync();

                return(null);
            }
            else if (keyCreationResult.Status == KeyCredentialStatus.UnknownError)
            {
                MessageDialog message = new MessageDialog("The key credential could not be created. Please try again.");
                await message.ShowAsync();

                return(null);
            }

            return(null);
        }
        /// <summary>
        /// 请求注册用户
        /// </summary>
        /// <returns></returns>
        public static async Task <AuthenticatorState> RegisterUserAsync()
        {
            if (await CheckSupportAsync().ConfigureAwait(false))
            {
                KeyCredentialRetrievalResult CredentiaResult = await KeyCredentialManager.RequestCreateAsync(CredentialName, KeyCredentialCreationOption.ReplaceExisting);

                switch (CredentiaResult.Status)
                {
                case KeyCredentialStatus.Success:
                {
                    string PublicKey = CryptographicBuffer.EncodeToHexString(CredentiaResult.Credential.RetrievePublicKey());
                    ApplicationData.Current.LocalSettings.Values["WindowsHelloPublicKeyForUser"] = PublicKey;
                    return(AuthenticatorState.RegisterSuccess);
                }

                case KeyCredentialStatus.UserCanceled:
                {
                    return(AuthenticatorState.UserCanceled);
                }

                default:
                {
                    return(AuthenticatorState.UnknownError);
                }
                }
            }
            else
            {
                return(AuthenticatorState.WindowsHelloUnsupport);
            }
        }
Exemple #9
0
        /// <summary>
        /// Creates a Passport key on the machine using the _account id passed.
        /// </summary>
        /// <param name="accountId">The _account id associated with the _account that we are enrolling into Passport</param>
        /// <returns>Boolean representing if creating the Passport key succeeded</returns>
        public static async Task <bool> CreatePassportKeyAsync(Guid userId, string username)
        {
            Debug.WriteLine("Before calling KeyCredentialManager.RequestCreateAsync");

            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync(username, KeyCredentialCreationOption.ReplaceExisting);

            Debug.WriteLine("After calling KeyCredentialManager.RequestCreateAsync");

            switch (keyCreationResult.Status)
            {
            case KeyCredentialStatus.Success:
                Debug.WriteLine("Successfully made key");

                // In the real world authentication would take place on a server.
                // So every time a user migrates or creates a new Microsoft Passport account Passport details should be pushed to the server.
                // The details that would be pushed to the server include:
                // The public key, keyAttesation if available,
                // certificate chain for attestation endorsement key if available,
                // status code of key attestation result: keyAttestationIncluded or
                // keyAttestationCanBeRetrievedLater and keyAttestationRetryType
                // As this sample has no concept of a server it will be skipped for now
                // for information on how to do this refer to the second Passport sample

                //For this sample just return true
                await GetKeyAttestationAsync(userId, keyCreationResult);

                return(true);

            case KeyCredentialStatus.UserCanceled:
                Debug.WriteLine("User cancelled sign-in process.");
                break;

            case KeyCredentialStatus.NotFound:
                // User needs to setup Microsoft Passport
                Debug.WriteLine("Microsoft Passport is not setup!\nPlease go to Windows Settings and set up a PIN to use it.");
                break;

            case KeyCredentialStatus.CredentialAlreadyExists:
                Debug.WriteLine("Credential already exists!");
                break;

            case KeyCredentialStatus.UnknownError:
                Debug.WriteLine("Unknown error generating credentials key");
                break;

            default:
                Debug.WriteLine("Some error making the credentials key!");
                break;
            }

            return(false);
        }
Exemple #10
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());
        }
Exemple #11
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);
        }
        public static async Task <bool> CreatePassportKeyAsync()
        {
            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync("temp", KeyCredentialCreationOption.ReplaceExisting);

            if (keyCreationResult.Status == KeyCredentialStatus.Success)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #13
0
        public static async void RemovePassportAccountAsync(UserAccount account)
        {
            //Open the account with Windows Hello
            KeyCredentialRetrievalResult keyOpenResult = await KeyCredentialManager.OpenAsync(account.Username);

            if (keyOpenResult.Status == KeyCredentialStatus.Success)
            {
                // In the real world you would send key information to server to unregister
                AuthService.AuthService.Instance.PassportRemoveUser(account.UserId);
            }

            //Then delete the account from the machines list of Passport Accounts
            await KeyCredentialManager.DeleteAsync(account.Username);
        }
Exemple #14
0
        /// <summary>
        /// Function to be called when user requests deleting their account.
        /// Checks the KeyCredentialManager to see if there is a Passport for the current user
        /// Then deletes the local key associated with the Passport.
        /// </summary>
        public static async void RemovePassportAccountAsync(Account account)
        {
            // Open the account with Passport
            KeyCredentialRetrievalResult keyOpenResult = await KeyCredentialManager.OpenAsync(account.Username);

            if (keyOpenResult.Status == KeyCredentialStatus.Success)
            {
                // In the real world you would send key information to server to unregister
                //e.g. RemovePassportAccountOnServer(account);
            }

            // Then delete the account from the machines list of Passport Accounts
            await KeyCredentialManager.DeleteAsync(account.Username);
        }
        /// <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 #16
0
        /// <summary>
        /// Checks the KeyCredentialManager to see if there is a Passport for the current user and
        /// sends the informaton to the server to unregister it.
        ///
        /// Then deletes the local key associated with the Passport.
        /// </summary>
        private async void PassportDelete()
        {
            KeyCredentialRetrievalResult keyOpenResult = await KeyCredentialManager.OpenAsync(activeAccount.Email);

            if (keyOpenResult.Status == KeyCredentialStatus.Success)
            {
                var userKey   = keyOpenResult.Credential;
                var publicKey = userKey.RetrievePublicKey();

                // Send key information to server to unregister it
                DeletePassportServerSide();
            }

            await KeyCredentialManager.DeleteAsync(activeAccount.Email);
        }
Exemple #17
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);
            }
        }
Exemple #19
0
        /// <summary>
        /// Creates a Passport key on the machine using the account id passed.
        /// Then returns a boolean based on whether we were able to create a Passport key or not.
        ///
        /// Will also attempt to create an attestation that this key is backed by hardware on the device, but is not a requirement
        /// for a working key in this scenario. It is possible to not accept a key that is software-based only.
        /// </summary>
        /// <param name="accountId">The account id associated with the account that we are enrolling into Passport</param>
        /// <returns>Boolean representing if creating the Passport key succeeded</returns>
        public async Task <bool> CreatePassportKey(string accountId)
        {
            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync(accountId, KeyCredentialCreationOption.ReplaceExisting);

            if (keyCreationResult.Status == KeyCredentialStatus.Success)
            {
                KeyCredential userKey   = keyCreationResult.Credential;
                IBuffer       publicKey = userKey.RetrievePublicKey();
                KeyCredentialAttestationResult keyAttestationResult = await userKey.GetAttestationAsync();

                if (keyAttestationResult.Status == KeyCredentialAttestationStatus.Success)
                {
                    //keyAttestation Included.
                    //TODO:read  keyAttestationResult.AttestationBuffer and keyAttestationResult.CertificateChainBuffer
                }
                else if (keyAttestationResult.Status == KeyCredentialAttestationStatus.TemporaryFailure)
                {
                    //keyAttestation CanBeRetrievedLater
                }
                else if (keyAttestationResult.Status == KeyCredentialAttestationStatus.NotSupported)
                {
                    //keyAttestation is not supported
                }

                // Package public key, keyAttesation if available,
                // certificate chain for attestation endorsement key if available,
                // status code of key attestation result: keyAttestationIncluded or
                // keyAttestationCanBeRetrievedLater and keyAttestationRetryType
                // and send it to application server to register the user.
                bool serverAddedPassportToAccount = await AddPassportToAccountOnServer();

                if (serverAddedPassportToAccount == true)
                {
                    return(true);
                }
            }
            else if (keyCreationResult.Status == KeyCredentialStatus.UserCanceled)
            {
                // User cancelled the Passport enrollment process
            }
            else if (keyCreationResult.Status == KeyCredentialStatus.NotFound)
            {
                // User needs to create PIN
                return(false);
            }
            return(false);
        }
Exemple #20
0
        /// <summary>
        /// Saves an encrypted string containing the CompositeKey information to the Password vault.
        /// </summary>
        /// <param name="dbPath">Database Path. This is the identification of the database, if database is moved or name is changed,
        /// New credentials must be created.</param>
        /// <param name="keyList">KeyList object containing the composite key information.</param>
        /// <param name="rResult">KeyCredential object used to sign a key to encrypt the compositekey information.</param>
        /// <returns>String representing the result of the operation. Success or the error thrown.</returns>
        internal static async Task <string> SaveKeys(string dbPath, KeyList keyList, KeyCredentialRetrievalResult rResult)
        {
            try
            {
                PasswordVault myVault   = new PasswordVault();
                String        encrypted = await Encrypt(Library.ConvertToPString(keyList), rResult);

                PasswordCredential newCredential = new PasswordCredential(dbPath, WinHelloUnlockExt.ProductName, encrypted);
                newCredential.RetrievePassword();
                myVault.Add(newCredential);
                return("Success");
            }
            catch (Exception ev)
            {
                return(ev.Message);
            }
        }
Exemple #21
0
        /// <summary>
        /// Creates the data for WinHelloUnlock to work.
        /// 1. A Key Credential to sign a cryptographic key.
        /// 2. A Password vault to save the data into
        /// 3. A Password Credential in which to save the encrypted data (using the signed cryptographic key).
        /// </summary>
        /// <param name="dbPath">Database path. This is the identity of the database, if Database is moved or renamed,
        /// WinHelloUnlock will not work and new data needs to be created.
        /// </param>
        /// <returns>True if all the data was saved successfully.</returns>
        internal static async Task <bool> CreateHelloData(string dbPath)
        {
            bool isHelloAvailable = await UWPLibrary.IsHelloAvailable();

            if (isHelloAvailable)
            {
                KeyCredentialCreationOption  optionNew       = KeyCredentialCreationOption.ReplaceExisting;
                KeyCredentialRetrievalResult retrievalResult = await UWPLibrary.CreateCredential(dbPath, optionNew);

                if (retrievalResult.Status == KeyCredentialStatus.Success)
                {
                    KeyList keyList    = Library.GetKeys(WinHelloUnlockExt.database);
                    string  resultSave = await UWPLibrary.SaveKeys(dbPath, keyList, retrievalResult);

                    if (resultSave == "Success")
                    {
                        MessageService.ShowInfo("Database Keys saved successfuly");
                        UWPLibrary.ck = KeePass.Program.MainForm.ActiveDatabase.MasterKey;
                        return(true);
                    }
                    else
                    {
                        if (resultSave.Substring(0, 20) == "Value cannot be null")
                        {
                            MessageService.ShowWarning("Error saving the composite key: MasterKey was null." +
                                                       " Verify that \"Remember master password (in encrypted form) of a database while it is open\" option under Tools/Options/Security" +
                                                       " is enabled, then lock and unlock the database.");
                        }
                        else
                        {
                            MessageService.ShowWarning("Error saving the composite key: " + resultSave);
                        }
                    }
                }
                else
                {
                    WinHelloErrors(retrievalResult.Status, "Error creating the credential: ");
                }
            }
            else
            {
                MessageService.ShowWarning("Windows Hello is NOT Available");
            }
            return(false);
        }
Exemple #22
0
        public static async Task <bool> GetPassportAuthenticationMessageAsync(UserAccount account)
        {
            KeyCredentialRetrievalResult openKeyResult = await KeyCredentialManager.OpenAsync(account.Username);

            if (openKeyResult.Status == KeyCredentialStatus.Success)
            {
                return(true);
            }
            else if (openKeyResult.Status == KeyCredentialStatus.NotFound)
            {
                if (await CreatePassportKeyAsync(account.UserId, account.Username))
                {
                    return(await GetPassportAuthenticationMessageAsync(account));
                }
            }
            // Can't use Passport right now, try again later
            return(false);
        }
Exemple #23
0
        /// <summary>
        /// Checks the KeyCredentialManager to see if there is a Passport for the current user and
        /// sends the informaton to the server to unregister it.
        ///
        /// Then deletes the local key associated with the Passport.
        /// </summary>
        private async void PassportDelete()
        {
            KeyCredentialRetrievalResult keyOpenResult = await KeyCredentialManager.OpenAsync(activeAccount.Email);

            if (keyOpenResult.Status == KeyCredentialStatus.Success)
            {
                var userKey   = keyOpenResult.Credential;
                var publicKey = userKey.RetrievePublicKey();

                // Send key information to server to unregister it
                DeletePassportServerSide();
            }

            await KeyCredentialManager.DeleteAsync(activeAccount.Email);

            rootPage.NotifyUser("User " + activeAccount.Email + " deleted.", NotifyType.StatusMessage);
            button_Forget.IsEnabled = false;
            button_Forget.Content   = "User Forgotten.";
        }
Exemple #24
0
        private bool IsCredentialValid(KeyCredentialRetrievalResult keyCreation)
        {
            bool result = false;

            switch (keyCreation.Status)
            {
            case KeyCredentialStatus.Success:
                result = true;
                break;

            case KeyCredentialStatus.UserCanceled:
                break;

            case KeyCredentialStatus.NotFound:
                break;

            default:
                break;
            }
            return(result);
        }
Exemple #25
0
        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync("WinHello", KeyCredentialCreationOption.ReplaceExisting);

            var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();

            if (keyCreationResult.Status == KeyCredentialStatus.Success)
            {
                this.Frame.Navigate(typeof(MainPage));
            }
            else if (keyCreationResult.Status == KeyCredentialStatus.NotFound)
            {
                MessageDialog message = new MessageDialog(resourceLoader.GetString("WHError1"));
                await message.ShowAsync();
            }
            else if (keyCreationResult.Status == KeyCredentialStatus.UnknownError)
            {
                MessageDialog message = new MessageDialog(resourceLoader.GetString("WHError2"));
                await message.ShowAsync();
            }
        }
Exemple #26
0
        public static async Task <bool> RegisterWindowsHello(string userId)
        {
            // Check if the user already exists and if so log them in.
            KeyCredentialRetrievalResult retrieveResult = await KeyCredentialManager.OpenAsync(userId);

            if (retrieveResult.Status == KeyCredentialStatus.Success)
            {
                return(await SignInWithHelloAsync(userId, retrieveResult));
            }

            // Create the key credential with Passport APIs
            IBuffer publicKey = await CreatePassportKeyCredentialAsync(userId);

            if (publicKey != null)
            {
                // Register the public key and attestation of the key credential with the server
                // In a real-world scenario, this would likely also include:
                // - Certificate chain for attestation endorsement if available
                // - Status code of the Key Attestation result : Included / retrieved later / retry type
                if (await RegisterPassportCredentialWithServerAsync(publicKey, userId))
                {
                    // Remember that this is the user whose credentials have been registered
                    // with the server.
                    ApplicationData.Current.LocalSettings.Values["userId"] = userId;

                    // Registration successful. Continue to the signed-in state.
                    return(true);
                }
                else
                {
                    // Delete the failed credentials from the device.
                    await Util.TryDeleteCredentialAccountAsync(userId);

                    MessageDialog message = new MessageDialog("Failed to register with the server.");
                    await message.ShowAsync();
                }
            }

            return(false);
        }
Exemple #27
0
        /// <summary>
        /// Attempts to sign a message using the Passport key on the system for the accountId passed.
        /// </summary>
        /// <returns>Boolean representing if creating the Passport authentication message succeeded</returns>
        public static async Task <bool> GetPassportAuthenticationMessageAsync(Account account)
        {
            KeyCredentialRetrievalResult openKeyResult = await KeyCredentialManager.OpenAsync(account.Username);

            // Calling OpenAsync will allow the user access to what is available in the app and will not require user credentials again.
            // If you wanted to force the user to sign in again you can use the following:
            // var consentResult = await Windows.Security.Credentials.UI.UserConsentVerifier.RequestVerificationAsync(account.Username);
            // This will ask for the either the password of the currently signed in Microsoft Account or the PIN used for Microsoft Passport.

            if (openKeyResult.Status == KeyCredentialStatus.Success)
            {
                // If OpenAsync has succeeded, the next thing to think about is whether the client application requires access to backend services.
                // If it does here you would Request a challenge from the Server. The client would sign this challenge and the server
                // would check the signed challenge. If it is correct it would allow the user access to the backend.
                // You would likely make a new method called RequestSignAsync to handle all this
                // e.g. RequestSignAsync(openKeyResult);
                // Refer to the second Microsoft Passport sample for information on how to do this.

                // For this sample there is not concept of a server implemented so just return true.
                return(true);
            }
            else if (openKeyResult.Status == KeyCredentialStatus.NotFound)
            {
                // If the _account is not found at this stage. It could be one of two errors.
                // 1. Microsoft Passport has been disabled
                // 2. Microsoft Passport has been disabled and re-enabled cause the Microsoft Passport Key to change.
                // Calling CreatePassportKey and passing through the account will attempt to replace the existing Microsoft Passport Key for that account.
                // If the error really is that Microsoft Passport is disabled then the CreatePassportKey method will output that error.
                if (await CreatePassportKeyAsync(account.Username))
                {
                    // If the Passport Key was again successfully created, Microsoft Passport has just been reset.
                    // Now that the Passport Key has been reset for the _account retry sign in.
                    return(await GetPassportAuthenticationMessageAsync(account));
                }
            }

            // Can't use Passport right now, try again later
            return(false);
        }
Exemple #28
0
        /// <summary>
        /// Retrieves the CompositeKey information from the Password vault.
        /// </summary>
        /// <param name="dbPath">Database Path. This is the identification of the database, if database is moved or name is changed,
        /// New credentials must be created.</param>
        /// <param name="rResult">KeyCredential object used to sign a key to decrypt the compositekey information.</param>
        /// <returns>KeyList object with all the information to compose the CompositeKey.</returns>
        internal async static Task <KeyList> RetrieveKeys(string dbPath, KeyCredentialRetrievalResult rResult)
        {
            PasswordVault myVault       = new PasswordVault();
            var           newCredential = new PasswordCredential();

            try
            {
                newCredential = myVault.Retrieve(dbPath, WinHelloUnlockExt.ProductName);
                newCredential.RetrievePassword();
            }
            catch (Exception ev)
            {
                MessageService.ShowInfo("Not able to retrieve Composite Key from Microsoft Password Vault. " +
                                        "Maybe saving again will solve the problem. Message: " + ev.Message);
                return(new KeyList(null, null));
            }
            try
            {
                string          encrypted = newCredential.Password;
                ProtectedString decrypted = await Decrypt(encrypted, rResult);

                if (decrypted != null)
                {
                    KeyList Keys = Library.ConvertKeyList(decrypted);
                    decrypted = ProtectedString.EmptyEx;
                    return(Keys);
                }
                else
                {
                    return(new KeyList(null, null));
                }
            }
            catch (Exception ev)
            {
                MessageService.ShowInfo("Credential not retrieved: " + ev.Message);
                Debug.Write(ev.Message);
                return(new KeyList(null, null));
            }
        }
Exemple #29
0
        public static async Task <bool> CreatePassportKeyAsync(string accountId)
        {
            KeyCredentialRetrievalResult keyCreationResult = await KeyCredentialManager.RequestCreateAsync(accountId, KeyCredentialCreationOption.ReplaceExisting);

            switch (keyCreationResult.Status)
            {
            case KeyCredentialStatus.Success:
                Debug.WriteLine("Successfully made key");
                return(true);

            case KeyCredentialStatus.UserCanceled:
                Debug.WriteLine("User cancelled sign-in process.");
                break;

            case KeyCredentialStatus.NotFound:
                Debug.WriteLine("Microsoft Passport is not setup!\nPlease go to Windows Settings and set up a PIN to use it.");
                break;

            default:
                break;
            }
            return(false);
        }
        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);
        }