「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。 -[[戻る>Microsoft Passport]] * 目次 [#x5106216] #contents *概要 [#f8516d04] -[[Microsoft Passport]]が提供するプログラミングシステムのAPI -Windowsデバイス上で、[[FIDO]]を実装する場合に、このAPIを利用する。 *クライアント実装 [#r4886e70] **共通 [#s0d4b169] -アプリケーションに登録開始リクエストを送る。 -challenge、policy、appIDなどが返される。 ***policyに適合する認証器を調べる [#d4ce3298] ***認証器の調査: KeyCredentialManager.IsSupportedAsync()メソッド [#jdffe4a8] -ユーザーが Windows Hello をセットアップしたかどうかを調べる if (await KeyCredentialManager.IsSupportedAsync() == false) { ・・・ ***キーのストア&コンテナを開く: KeyCredentialManager.OpenAsync()メソッド [#o536dd3d] 当該ユーザ&アプリケーションのキーのストア&コンテナを開く。 // retrieve private key for sign KeyCredentialRetrievalResult res = await KeyCredentialManager.OpenAsync("keyName"); **登録 [#mf95bb5b] -[[上記のKeyCredentialManager.OpenAsync>#o536dd3d]]の結果が、 if (res.Status == KeyCredentialStatus.NotFound) { ・・・ >の場合、 -≒新規のdeviceを登録する場合、若しくは、追加のデバイスを登録する場合。 ***キーペアを作成する: KeyCredentialManager.RequestCreateAsync()メソッド [#x9609a48] -RequestCreateAsyncを使用してキーペアを作成する。 --Windows Helloに対応した認証器に生体認証の情報を入力する。 --入力後、内部では、private key と public key が作成される。 --private key は TPM に登録され、以降、認証器によって保護される。 --private key は [[TPM>TPM(Trusted Platform Module)]] に登録され、以降、認証器によって保護される。 -実装 // Create the credential // (Windows Hello is diplayed here !) KeyCredentialRetrievalResult createRes = await KeyCredentialManager.RequestCreateAsync("keyName", KeyCredentialCreationOption.ReplaceExisting); // if the status is success, retrieve the public key. if (createRes.Status == KeyCredentialStatus.Success) { ・・・public keyとattestationを取得する。 } else if( keyCreationResult.Status == KeyCredentialStatus.UserCanceled || keyCreationResult.Status == KeyCredentialStatus.UserPrefersPassword) { // Show error message to the user to get confirmation that user does not want to enroll. } ***public keyを取得する: KeyCredential.RetrievePublicKey()メソッド [#pd6ccca1] -public keyを取得する。 -実装 KeyCredential userKey = keyCreationResult.Credential; IBuffer publicKey = userKey.RetrievePublicKey(); ***attestationを取得する: KeyCredential.GetAttestationAsync()メソッド [#j562a388] -attestation(デバイス正常性構成証明)を取得する。 -実装 KeyCredentialAttestationResult keyAttestationResult = await userKey.GetAttestationAsync(); IBuffer keyAttestation = null; IBuffer certificateChain = null; bool keyAttestationIncluded = false; bool keyAttestationCanBeRetrievedLater = false; KeyCredentialAttestationStatus keyAttestationRetryType = 0; if (keyAttestationResult.Status == KeyCredentialAttestationStatus.Success) { keyAttestationIncluded = true; keyAttestation = keyAttestationResult.AttestationBuffer; certificateChain = keyAttestationResult.CertificateChainBuffer; rootPage.NotifyUser("Successfully made key and attestation", NotifyType.StatusMessage); } else if (keyAttestationResult.Status == KeyCredentialAttestationStatus.TemporaryFailure) { keyAttestationRetryType = KeyCredentialAttestationStatus.TemporaryFailure; keyAttestationCanBeRetrievedLater = true; rootPage.NotifyUser("Successfully made key but not attestation", NotifyType.StatusMessage); } else if (keyAttestationResult.Status == KeyCredentialAttestationStatus.NotSupported) { keyAttestationRetryType = KeyCredentialAttestationStatus.NotSupported; keyAttestationCanBeRetrievedLater = false; rootPage.NotifyUser("Key created, but key attestation not supported", NotifyType.StatusMessage); } ***上記の情報をサーバに飛ばして登録する。 [#mb7ccf4d] -PublicKey IBuffer publicKey -KeyAttesation IBuffer keyAttestation --certificate chain for attestation endorsement key IBuffer certificateChain --status code of key attestation result bool keyAttestationIncluded bool keyAttestationCanBeRetrievedLater KeyCredentialAttestationStatus keyAttestationRetryType -実装 // 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; } -サーバ側~ [[こちら>#h5e2d6ee]]。 **認証 [#m53e84af] [[上記のKeyCredentialManager.OpenAsync>#o536dd3d]]の結果が、 if (res.Status == KeyCredentialStatus.Success) { ・・・ の場合、 ***KeyCredentialManager.RequestSignAsync()メソッド [#x249d76f] [[登録>#h5b260df]]後、PIN や 生体認証を使って、challengeにデジタル署名 (RequestSignAsync) する。 var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId); if (openKeyResult.Status == KeyCredentialStatus.Success) { var userKey = openKeyResult.Credential; var publicKey = userKey.RetrievePublicKey(); var signResult = await userKey.RequestSignAsync(message); if (signResult.Status == KeyCredentialStatus.Success) { return signResult.Result; } else if (signResult.Status == KeyCredentialStatus.UserPrefersPassword) { } } ***上記の情報をサーバに飛ばして認証する。 [#d9e101a4] [[こちら>#m586e835]] **その他 [#l36fc4ff] ***UserConsentVerifier.RequestVerificationAsync()メソッド [#x8f6e46c] ある特定の箇所で 生体認証を呼び出してOKかNOか確認したい場合 if (await UserConsentVerifier.CheckAvailabilityAsync() == UserConsentVerifierAvailability.Available) { UserConsentVerificationResult res = await UserConsentVerifier.RequestVerificationAsync( "This is sensitive operation ! Please authenticate again."); if(res == UserConsentVerificationResult.Verified) { // some important action … } } ***KeyCredentialManager.DeleteAsync()メソッド [#a88cf643] private keyを削除する。 await KeyCredentialManager.DeleteAsync("keyName"); *サーバ実装 [#d263bb7b] **サンプルのデータベース スキーマ [#da11a4e9] ***User [#s3fe73af] -id -e-mail address -first name -last name ***UserKeys [#j15d23ad] -id -user id -public key -attestation -device id -last logontime **処理 [#n8303bac] ***登録 [#h5e2d6ee] UserKeysレコードを追加。 ***認証 [#m586e835] using (RSACng pubKey = new RSACng(publicKey)) { retval = pubKey.VerifyData( originalChallenge, responseSignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); } *参考 [#r42666b1] -Windows Hello を使った App 開発 – Tsmatz~ https://blogs.msdn.microsoft.com/tsmatsuz/2015/07/30/windows-hello-app/ **docs.microsoft.com [#s410a0be] -UWP app developer --Windows Hello~ https://docs.microsoft.com/ja-jp/windows/uwp/security/microsoft-passport ---Windows Hello ログイン アプリの作成~ https://docs.microsoft.com/ja-jp/windows/uwp/security/microsoft-passport-login ---Windows Hello ログイン サービスの作成~ https://docs.microsoft.com/ja-jp/windows/uwp/security/microsoft-passport-login-auth-service --(Windows.Security.Credentials) ---KeyCredential Class (Windows.Security.Credentials)~ https://docs.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredential ---KeyCredentialManager Class (Windows.Security.Credentials)~ https://docs.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredentialmanager ---KeyCredentialAttestationResult Class (Windows.Security.Credentials)~ https://docs.microsoft.com/en-us/uwp/api/windows.security.credentials.keycredentialattestationresult **Microsoft/Windows-universal-samples [#u118327d] -MicrosoftPassport~ https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/MicrosoftPassport --クライアント(UWP)~ https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/MicrosoftPassport/cs --サーバ(ASP.NET MVC)~ https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/MicrosoftPassport/Server ---- Tags: [[:Windows]], [[:認証基盤]]