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