「[[マイクロソフト系技術情報 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]], [[:認証基盤]]

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS