「マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。
目次 †
概要 †
クライアント実装 †
共通 †
- アプリケーションに登録開始リクエストを送る。
- challenge、policy、appIDなどが返される。
policyに適合する認証器を調べる †
認証器の調査: KeyCredentialManager?.IsSupportedAsync?()メソッド †
- ユーザーが Windows Hello をセットアップしたかどうかを調べる
if (await KeyCredentialManager.IsSupportedAsync() == false)
{
・・・
キーのストア&コンテナを開く: KeyCredentialManager?.OpenAsync?()メソッド †
当該ユーザ&アプリケーションのキーのストア&コンテナを開く。
// retrieve private key for sign
KeyCredentialRetrievalResult res =
await KeyCredentialManager.OpenAsync("keyName");
登録 †
if (res.Status == KeyCredentialStatus.NotFound)
{
・・・
の場合、
- ≒新規のdeviceを登録する場合、若しくは、追加のデバイスを登録する場合。
キーペアを作成する: KeyCredentialManager?.RequestCreateAsync?()メソッド †
- RequestCreateAsync?を使用してキーペアを作成する。
- Windows Helloに対応した認証器に生体認証の情報を入力する。
- 入力後、内部では、private key と public key が作成される。
- private key は TPM に登録され、以降、認証器によって保護される。
- 実装
// 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?()メソッド †
attestationを取得する: KeyCredential?.GetAttestationAsync?()メソッド †
- 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);
}
上記の情報をサーバに飛ばして登録する。 †
- PublicKey?
IBuffer publicKey
- KeyAttesation?
IBuffer keyAttestation
- certificate chain for attestation endorsement key
IBuffer certificateChain
- 実装
// 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;
}
認証 †
上記のKeyCredentialManager.OpenAsyncの結果が、
if (res.Status == KeyCredentialStatus.Success)
{
・・・
の場合、
KeyCredentialManager?.RequestSignAsync?()メソッド †
登録後、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)
{
}
}
上記の情報をサーバに飛ばして認証する。 †
こちら
その他 †
UserConsentVerifier?.RequestVerificationAsync?()メソッド †
ある特定の箇所で 生体認証を呼び出して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?()メソッド †
private keyを削除する。
await KeyCredentialManager.DeleteAsync("keyName");
サーバ実装 †
サンプルのデータベース スキーマ †
User †
- id
- e-mail address
- first name
- last name
UserKeys? †
- id
- user id
- public key
- attestation
- device id
- last logontime
処理 †
登録 †
UserKeys?レコードを追加。
認証 †
using (RSACng pubKey = new RSACng(publicKey))
{
retval = pubKey.VerifyData(
originalChallenge, responseSignature,
HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}
参考 †
docs.microsoft.com †
- (Windows.Security.Credentials)
Microsoft/Windows-universal-samples †
Tags: :Windows, :認証基盤