/// <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(); } }
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); }
/// <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)); }
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); }
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); } }
/// <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); }
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()); }
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); } }
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); }
/// <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(); } }
/// <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); }
/// <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); } }
/// <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); }
/// <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); } }
/// <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); }
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); }
/// <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."; }
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); }
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(); } }
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); }
/// <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); }
/// <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)); } }
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); }