Windows Hello

この記事では、Windows の一部として提供される Windows Hello テクノロジについて説明し、開発者がこのテクノロジを実装して Windows アプリとバックエンド サービスを保護する方法について説明します。 ここでは、従来の資格情報を使用して発生する脅威を軽減するのに役立つこれらのテクノロジの特定の機能を強調し、Windows クライアントロールアウトの一環としてこれらのテクノロジの設計と展開に関するガイダンスを提供します。

Note

この記事では、アプリ開発に焦点を当てます。 Windows Hello のアーキテクチャと実装の詳細については、「 Plan a Windows Hello for Business の展開を参照してください。

Windows Hello とバッキング認証サービスを使用して WinUI アプリを作成する手順については、windows Hello ログイン アプリWindows Hello ログイン サービスに関する記事を参照してください。

はじめに

情報セキュリティに関する基本的な前提は、システムがそれを使用しているユーザーを識別できることです。 ユーザーを識別すると、システムはユーザーが適切に識別されるかどうか (認証と呼ばれるプロセス) を決定し、適切に認証されたユーザーが実行できる必要がある操作 (承認) を決定できます。 世界中に展開されているコンピューター システムの大部分は、認証と承認の決定を行う際のユーザー資格情報に依存しています。つまり、これらのシステムは、ユーザーが作成した再利用可能なパスワードをセキュリティの基礎として使用します。 認証が「知っているもの、持っているもの、または何か」を含むことができるという大言は、問題をきちんと強調しています。再利用可能なパスワードは認証要素であるため、パスワードを知っている人は誰でもそれを所有するユーザーになりすますことができます。

従来の資格情報の問題

1960年代半ばから、フェルナンド・コルバトーとマサチューセッツ工科大学の彼のチームがパスワードの導入を支持したとき、ユーザーと管理者は、ユーザー認証と承認のためのパスワードの使用に対処する必要がありました。 時間の経過と共に、パスワードの保存と使用に関する最新の技術は多少進んでいます (たとえば、セキュリティで保護されたハッシュと塩分を使用するなど) が、2 つの問題に直面しています。 パスワードは簡単に複製でき、簡単に盗むことができます。 さらに、実装エラーによってセキュリティが損なわれる可能性があり、ユーザーは利便性とセキュリティのバランスを取るのに苦労します。

資格情報の盗用

パスワードの最大のリスクは、単純に、攻撃者がそれを簡単に盗めることです。 パスワードが入力、処理、または保存される場所は、すべて脆弱性があります。 たとえば、攻撃者は、アプリケーション サーバーへのネットワーク トラフィックを盗聴したり、アプリケーションまたはデバイスにマルウェアを埋め込んだり、デバイスでユーザーのキーストロークをログに記録したり、ユーザーが入力した文字を確認したりすることによって、認証サーバーからパスワードやハッシュのコレクションを盗むことができます。 これらは、最も一般的な攻撃方法にすぎません。

もう 1 つの関連するリスクは、資格情報の再生です。攻撃者は安全でないネットワークを傍受して有効な資格情報をキャプチャし、後でそれを再生して有効なユーザーを偽装します。 ほとんどの認証プロトコル (Kerberos や OAuth を含む) は、資格情報交換プロセスにタイム スタンプを含めることでリプレイ攻撃から保護されますが、この戦術では、ユーザーが最初にチケットを取得するために提供するパスワードではなく、認証システムが発行するトークンのみを保護します。

資格情報の再利用

ユーザー名として電子メール アドレスを使用する一般的な方法では、悪い問題が悪化します。 侵害されたシステムからユーザー名とパスワードのペアを正常に回復した攻撃者は、その同じペアを他のシステムで試すことができます。 この戦術は、攻撃者が侵害されたシステムから他のシステムに侵入できるようにするために、驚くほど頻繁に機能します。 ユーザー名としてメール アドレスを使用すると、このガイドの後半で説明する追加の問題が発生します。

資格情報の問題の解決

パスワードによって発生する問題を解決するのは難しいです。 パスワード ポリシーだけを締め付けるだけでは、パスワード ポリシーは適用されません。ユーザーは、パスワードのリサイクル、共有、または書き留めのみを行うことができます。 ユーザー教育は認証セキュリティにとって重要ですが、教育だけでは問題は解消されません。

Windows Hello では、既存の資格情報を検証し、生体認証または PIN ベースのユーザー ジェスチャによって保護されるデバイス固有の資格情報を作成することで、パスワードを強力な 2 要素認証 (2FA) に置き換えます。

Windows Hello とは

Windows Hello は、Windows に組み込まれている新しい生体認証サインイン システムに Microsoft が付けた名前です。 では営業システム、Windowsこんにちはき顔や指紋認証のロック解除ユーザーのデバイス 認証は、ユーザーがデバイス固有の資格情報にアクセスするために一意の生体認証識別子を指定した場合に発生します。つまり、デバイスを盗んだ攻撃者は、その攻撃者が PIN を持っていない限りログオンできません。 Windows secure credential storeは、デバイス上の生体認証データを保護します。 Windows Hello を使用してデバイスのロックを解除すると、承認されたユーザーは、すべての Windows エクスペリエンス、アプリ、データ、Web サイト、およびサービスにアクセスできます。

Windows Hello 認証システムは、Hello と呼ばれます。 Hello は、個々のデバイスと特定のユーザーの組み合わせに固有です。 デバイス間ではローミングされず、サーバーや呼び出し元アプリと共有されず、デバイスから簡単に抽出することはできません。 複数のユーザーがデバイスを共有する場合、各ユーザーは自分のアカウントを設定する必要があります。 すべてのアカウントは、そのデバイスの一意の Hello を取得します。 Hello は、保存されている資格情報のロック解除 (または解放) に使用できるトークンと考えることができます。 Hello 自体はアプリまたはサービスに対してユーザーを認証しませんが、可能な資格情報を解放します。 つまり、Hello はユーザー資格情報ではありませんが、認証プロセスの 2 番目の要素です。

Windows Hello 認証

Windowsこんにちは提供を確実にデバイスを認識し、個人ユーザーは、アドレスの最初の部分の間、ユーザーは、要求されたサービスまたはデータ項目です。 デバイスは、ユーザーを認識した後も、要求されたリソースへのアクセスを許可するかどうかを決定する前に、ユーザーを認証する必要があります。 Windows Hello は、Windows に完全に統合された強力な 2FA を提供し、再利用可能なパスワードを特定のデバイスと生体認証ジェスチャまたは PIN の組み合わせに置き換えます。

ただし、Windows Hello は従来の 2FA システムに代わるものではありません。 概念的にはスマート カードに似ています。認証は文字列比較ではなく暗号化プリミティブを使用して実行され、ユーザーのキー マテリアルは改ざん防止ハードウェア内でセキュリティで保護されます。 Windows Hello では、スマート カードの展開に必要な追加のインフラストラクチャ コンポーネントも必要ありません。 特に、証明書を管理するために公開キー 基盤 (PKI) を現在持っていない場合は必要ありません。 Windowsこんにちはを併せ持つ強みは主にスマートカード展開の柔軟性のための仮想スマートカードおよび堅牢なセキュリティのための物理的スマートカードせずにその問題点がありました。

Windows Hello のしくみ

ユーザーが自分のコンピューターで Windows Hello を設定すると、デバイスに新しい公開キーと秘密キーのペアが生成されます。 信頼されたプラットフォーム モジュール (TPM) は、この秘密キーを生成して保護します。 デバイスに TPM チップがない場合、秘密キーは暗号化され、ソフトウェアによって保護されます。 さらに、TPM 対応デバイスは、キーが TPM にバインドされていることを証明するために使用できるデータ ブロックを生成します。 この構成証明情報は、ソリューションで使用して、ユーザーに別の承認レベルが付与されているかどうかを判断できます。

デバイスで Windows Hello を有効にするには、ユーザーが自分の Microsoft Entra ID アカウントまたは Windows 設定で接続されている Microsoft アカウントを持っている必要があります。

キーの保護方法

キー マテリアルが生成されるたびに、攻撃から保護する必要があります。 これを行う最も堅牢な方法は、特殊なハードウェアを使用することです。 ハードウェア セキュリティ モジュール (HSM) を使用して、セキュリティクリティカルなアプリケーションのキーを生成、格納、および処理する長い歴史があります。 スマート カードは、トラステッド コンピューティング グループの TPM 標準に準拠しているデバイスと同様に、特殊な種類の HSM です。 可能な限り、Windows Hello の実装では、TPM ハードウェアのオンボードを利用して、キーの生成、格納、および処理を行います。 ただし、Windows Hello と Windows Hello for Work にはオンボード TPM は必要ありません。

可能な場合は常に、TPM ハードウェアを使用することをお勧めします。 TPM は、PIN ブルート フォース攻撃など、さまざまな既知および潜在的な攻撃から保護します。 TPM は、アカウントロックアウト後も保護の追加レイヤーを提供します。 TPM がキー マテリアルをロックしている場合、ユーザーは PIN をリセットする必要があります。 PIN をリセットすると、古いキー マテリアルで暗号化されたすべてのキーと証明書が削除されます。

認証

ユーザーが保護されたキー マテリアルにアクセスする場合、認証プロセスは、ユーザーが PIN または生体認証ジェスチャを入力してデバイスのロックを解除することで開始されます。これは、"キーの解放" と呼ばれることもあります。

アプリケーションは、別のアプリケーションのキーを使用することも、他のユーザーのキーを使用することもできません。 これらのキーは、ID プロバイダーまたは IDP に送信される要求に署名するために使用され、指定されたリソースへのアクセスを求めます。 アプリケーションでは、特定の API を使用して、特定のアクションの重要なマテリアルを必要とする操作を要求できます。 これらの API を介したアクセスには、ユーザー ジェスチャによる明示的な検証が必要であり、キー マテリアルは要求側のアプリケーションに公開されません。 代わりに、アプリケーションはデータの署名などの特定のアクションを要求し、Windows Hello レイヤーが実際の作業を処理し、結果を返します。

Windows Hello を実装する準備

Windows Hello のしくみを基本的に理解したので、独自のアプリケーションで実装する方法を見てみましょう。

Windows Hello を使用して実装できるシナリオはさまざまです。 たとえば、デバイスでアプリにログオンするだけです。 もう 1 つの一般的なシナリオは、サービスに対する認証です。 ログオン名とパスワードを使用する代わりに、Windows Hello を使用します。 以降のセクションでは、Windows Hello を使用してサービスに対して認証する方法、既存のユーザー名/パスワード システムから Windows Hello システムに変換する方法など、いくつかの異なるシナリオの実装について説明します。

Windows Hello の実装

このセクションでは、既存の認証システムがないグリーンフィールド シナリオから始め、Windows Hello を実装する方法について説明します。

次のセクションでは、既存のユーザー名/パスワード システムから移行する方法について説明します。 ただし、そのセクションの関心が高い場合でも、このセクションを参照して、プロセスと必要なコードの基本的な理解を得ることができます。

新しいユーザーの登録

まず、Windows Hello を使用する新しいサービスと、新しいデバイスにサインアップする準備ができている架空の新しいユーザーから始めます。

最初の手順では、ユーザーが Windows Hello を使用できることを確認します。 アプリは、ユーザー設定とマシンの機能を検証して、ユーザー ID キーを作成できることを確認します。 ユーザーがまだ Windows Hello を有効にしていないとアプリが判断した場合は、アプリを使用する前にこれを設定するようユーザーに求められます。

Windows Hello を有効にするには、ユーザーが Out of Box Experience (OOBE) 中に PIN を設定しない限り、Windows 設定で PIN を設定するだけで済みます。

次のコード行は、ユーザーが Windows Hello 用に設定されているかどうかを簡単に確認する方法を示しています。

var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();
if (!keyCredentialAvailable)
{
    // User didn't set up PIN yet
    return;
}

次の手順では、サービスにサインアップするための情報をユーザーに求めます。 名、姓、電子メール アドレス、および一意のユーザー名をユーザーに求めることもできます。 電子メール アドレスを一意の識別子として使用できます。それはあなた次第です。

このシナリオでは、ユーザーの一意識別子として電子メール アドレスを使用します。 ユーザーがサインアップしたら、検証電子メールを送信してアドレスが有効であることを確認することを検討する必要があります。 これにより、必要に応じてアカウントをリセットするメカニズムが提供されます。

ユーザーが PIN を設定した場合、アプリはユーザーの KeyCredential を作成します。 また、アプリはオプションのキー構成証明情報を取得して、キーが TPM で生成されるという暗号証明を取得します。 生成された公開キー (必要に応じて構成証明) がバックエンド サーバーに送信され、使用されているデバイスが登録されます。 すべてのデバイスで生成されるすべてのキー ペアは一意になります。

KeyCredentialを作成するコードは次のようになります。

var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(
    AccountId, KeyCredentialCreationOption.ReplaceExisting);

RequestCreateAsync は、公開キーと秘密キーを作成する呼び出しです。 デバイスに適切な TPM チップがある場合、API は TPM チップに秘密キーと公開キーを作成し、結果を格納するように要求します。使用可能な TPM チップがない場合、OS はコードでキー ペアを作成します。 作成された秘密キーにアプリが直接アクセスする方法はありません。 キー ペアの作成の一部は、結果の構成証明情報でもあります。 (構成証明の詳細については、次のセクションを参照してください)。

デバイスでキー ペアと構成証明情報が作成されたら、公開キー、オプションの構成証明情報、および一意識別子 (電子メール アドレスなど) をバックエンド登録サービスに送信し、バックエンドに格納する必要があります。

ユーザーが複数のデバイスでアプリにアクセスできるようにするには、バックエンド サービスが同じユーザーの複数のキーを格納できる必要があります。 すべてのキーはデバイスごとに一意であるため、これらのキーはすべて同じユーザーに接続されて格納されます。 デバイス識別子は、ユーザーの認証時にサーバー 部分を最適化するために使用されます。 これについては、次のセクションで詳しく説明します。

バックエンドにこの情報を格納するサンプル データベース スキーマは、次のようになります。

Windows Hello サンプル データベース スキーマ

登録ロジックは次のようになります。

Windows Hello 登録ロジック

もちろん、収集する登録情報には、この単純なシナリオに含まれるよりも多くの識別情報が含まれる場合があります。 たとえば、アプリが銀行などのセキュリティで保護されたサービスにアクセスする場合は、サインアップ プロセスの一環として、ID の証明やその他のものを要求する必要があります。 すべての条件が満たされると、このユーザーの公開キーがバックエンドに格納され、ユーザーが次回サービスを使用する際の検証に使用されます。

using System;
using System.Runtime;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Security.Credentials;

static async void RegisterUser(string AccountId)
{
    var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();
    if (!keyCredentialAvailable)
    {
        // The user didn't set up a PIN yet
        return;
    }

    var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(AccountId, KeyCredentialCreationOption.ReplaceExisting);
    if (keyCreationResult.Status == KeyCredentialStatus.Success)
    {
        var userKey = keyCreationResult.Credential;
        var publicKey = userKey.RetrievePublicKey();
        var keyAttestationResult = await userKey.GetAttestationAsync();
        IBuffer keyAttestation = null;
        IBuffer certificateChain = null;
        bool keyAttestationIncluded = false;
        bool keyAttestationCanBeRetrievedLater = false;

        keyAttestationResult = await userKey.GetAttestationAsync();
        KeyCredentialAttestationStatus keyAttestationRetryType = 0;

        switch (keyAttestationResult.Status)
        {
            case KeyCredentialAttestationStatus.Success:
                keyAttestationIncluded = true;
                keyAttestation = keyAttestationResult.AttestationBuffer;
                certificateChain = keyAttestationResult.CertificateChainBuffer;
                break;
            case KeyCredentialAttestationStatus.TemporaryFailure:
                keyAttestationRetryType = KeyCredentialAttestationStatus.TemporaryFailure;
                keyAttestationCanBeRetrievedLater = true;
                break;
            case KeyCredentialAttestationStatus.NotSupported:
                keyAttestationRetryType = KeyCredentialAttestationStatus.NotSupported;
                keyAttestationCanBeRetrievedLater = true;
                break;
        }
    }
    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.
    }
}

構成証明

キー ペアを作成するときに、TPM チップによって生成される構成証明情報を要求するオプションもあります。 このオプションの情報は、サインアップ プロセスの一環としてサーバーに送信できます。 TPM キーの構成証明は、キーが TPM にバインドされていることを暗号で証明するプロトコルです。 この種類の構成証明は、特定のコンピューターの TPM で特定の暗号化操作が発生したことを保証するために使用できます。

生成された RSA キー、構成証明ステートメント、および AIK 証明書を受け取ると、サーバーは次の条件を検証します。

  • AIK 証明書の署名が有効です。
  • AIK 証明書は、信頼されたルートにチェーンされます。
  • AIK 証明書とそのチェーンは、EKU OID "2.23.133.8.3" に対して有効になっています (フレンドリ名は "Attestation Identity Key Certificate" です)。
  • AIK 証明書は有効な時刻です。
  • チェーン内のすべての発行元 CA 証明書は時間有効であり、取り消されません。
  • 構成証明ステートメントは正しく形成されています。
  • KeyAttestation BLOB の署名では、AIK 公開キーが使用されます。
  • KeyAttestation BLOB に含まれる公開キーは、クライアントが構成証明ステートメントと共に送信した公開 RSA キーと一致します。

これらの条件に応じて、アプリによってユーザーに異なる承認レベルが割り当てられる場合があります。 たとえば、これらのチェックのいずれかが失敗した場合、ユーザーが登録されなかったり、ユーザーが実行できる操作が制限されたりする可能性があります。

Windows Hello でのログオン

ユーザーがシステムに登録されると、ユーザーはアプリを使用できます。 シナリオに応じて、アプリの使用を開始する前にユーザーに認証を依頼したり、バックエンド サービスの使用を開始した後で認証を求めたりすることができます。

ユーザーに再度サインインを強制する

一部のシナリオでは、アプリにアクセスする前、またはアプリ内で特定のアクションを実行する前に、ユーザーが現在サインインしているユーザーであることをユーザーに証明することが必要な場合があります。 たとえば、銀行アプリが送金コマンドをサーバーに送信する前に、ログインしているデバイスを見つけたユーザーではなく、トランザクションを実行しようとしているユーザーであることを確認する必要があります。 UserConsentVerifier クラスを使用して、ユーザーにアプリでもう一度サインインするように強制できます。 次のコード行は、ユーザーに資格情報の入力を強制します。

次のコード行は、ユーザーに資格情報の入力を強制します。

UserConsentVerificationResult consentResult = await UserConsentVerifier.RequestVerificationAsync("userMessage");
if (consentResult.Equals(UserConsentVerificationResult.Verified))
{
    // continue
}

また、サーバーからのチャレンジ応答メカニズムを使用することもできます。このメカニズムでは、ユーザーが PIN コードまたは生体認証資格情報を入力する必要があります。 これは、開発者が実装する必要があるシナリオによって異なります。 このメカニズムについては、次のセクションで説明します。

バックエンドでの認証

アプリが保護されたバックエンド サービスにアクセスしようとすると、サービスはチャレンジをアプリに送信します。 アプリは、ユーザーの秘密キーを使用してチャレンジに署名し、サーバーに送信します。 サーバーはそのユーザーの公開キーを格納しているため、標準の暗号化 API を使用して、メッセージが正しい秘密キーで実際に署名されていることを確認します。 クライアントでは、署名は Windows Hello API によって行われます。開発者がユーザーの秘密キーにアクセスすることは決してありません。

キーの確認に加えて、サービスはキーの構成証明を確認し、キーがデバイスに格納される方法に関して呼び出される制限があるかどうかを識別することもできます。 たとえば、デバイスが TPM を使用してキーを保護する場合、TPM を使用せずにキーを格納するデバイスよりも安全です。 たとえば、バックエンド ロジックは、リスクを軽減するために TPM を使用しない場合にのみ、ユーザーが一定の金額を転送することを許可することを決定できます。

構成証明は、バージョン 2.0 以降の TPM チップを搭載したデバイスでのみ使用できます。 そのため、この情報はすべてのデバイスで使用できない可能性があることを考慮する必要があります。

クライアント ワークフローは、次のグラフのようになります。

Windows Hello クライアント ワークフロー

アプリがバックエンドでサービスを呼び出すと、サーバーはチャレンジを送信します。 チャレンジは次のコードで署名されます。

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)
    {

    }
}

最初の行 KeyCredentialManager.OpenAsync は、キー ハンドルを開くように Windows に求めます。 成功した場合は、 KeyCredential.RequestSignAsync メソッドを使用してチャレンジ メッセージに署名できます。これにより、Windows は Windows Hello を介してユーザーの PIN または生体認証を要求します。 開発者は、ユーザーの秘密キーにアクセスできなくなります。 これはすべて、API を介してセキュリティで保護されます。

API は、秘密キーを使用してチャレンジに署名するよう Windows に要求します。 その後、システムは PIN コードまたは構成済みの生体認証ログオンをユーザーに要求します。 正しい情報が入力されると、システムは TPM チップに暗号機能を実行し、チャレンジに署名するように要求できます。 (または、TPM が使用できない場合は、フォールバック ソフトウェア ソリューションを使用します)。 クライアントは、署名されたチャレンジをサーバーに送り返す必要があります。

次のシーケンス図に、基本的なチャレンジ応答フローを示します。

Windows Hello チャレンジ応答

次に、サーバーで署名を検証する必要があります。 公開キーを要求し、以降の検証用にサーバーに送ると、そのキーは ASN.1 でエンコードされた publicKeyInfo BLOB に格納されます。 GitHub で Windows Hello コード サンプルを調べると、ASN.1 でエンコードされた BLOB を CNG BLOB に変換するための Crypt32 関数をラップするヘルパー クラスがあることがわかります。これは、より一般的に使用されます。 BLOB には、公開キー アルゴリズム (RSA) と RSA 公開キーが含まれています。

このサンプルでは、ASN.1 でエンコードされた BLOB を CNG BLOB に変換する理由は、 CNG および BCrypt API で使用できるようにするためです。 CNG BLOB を検索すると、関連する BCRYPT_KEY_BLOB 構造体が示されます。 この API サーフェスは、Windows アプリケーションでの認証と暗号化に使用できます。 ASN.1 は、シリアル化可能なデータ構造のをやり取りに使用される文書化された標準であり、公開キー暗号化や証明書でよく使用されています。 公開キーの情報がこの形式で返されるのは、そのためです。 公開キーは RSA キーであり、RSA は、Windows Hello がデータへの署名に使用するアルゴリズムです。

CNG BLOB を取得したら、署名されたチャレンジをユーザーの公開キーに対して検証する必要があります。 すべてのユーザーが独自のシステムまたはバックエンド テクノロジを使用するため、このロジックを実装する一般的な方法はありません。 ハッシュ アルゴリズムとして SHA256 と SignaturePadding 用の Pkcs1 を使用しているため、クライアントからの署名付き応答を検証するときにそれが使用されていることを確認してください。 ここでも、.NET 4.6 のサーバーで実行する方法についてはサンプルを参照してくださいが、一般的には次のようになります。

using (RSACng pubKey = new RSACng(publicKey))
{
    retval = pubKey.VerifyData(originalChallenge, responseSignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}

格納されている公開キー (RSA キー) を読み取ります。 公開キーを使用して署名済みのチャレンジ メッセージを検証し、これがチェックアウトされた場合はユーザーを承認します。 ユーザーが認証されている場合、アプリは通常どおりバックエンド サービスを呼び出すことができます。

完全なコードは次のようになります。

using System;
using System.Runtime;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Security.Credentials;

static async Task<IBuffer> GetAuthenticationMessageAsync(IBuffer message, String AccountId)
{
    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.UserCanceled)
        {
            // Launch app-specific flow to handle the scenario 
            return null;
        }
    }
    else if (openKeyResult.Status == KeyCredentialStatus.NotFound)
    {
        // PIN reset has occurred somewhere else and key is lost.
        // Repeat key registration
        return null;
    }
    else
    {
        // Show custom UI because unknown error has happened.
        return null;
    }
}

正しいチャレンジ応答メカニズムの実装は、このドキュメントの範囲外ですが、このトピックでは、リプレイ攻撃や中間者攻撃などを防ぐための安全なメカニズムを正常に作成するために注意が必要です。

別のデバイスの登録

ユーザーは、同じアプリを持つ複数のデバイスを現在インストールするのが一般的です。 複数のデバイスで Windows Hello を使用する場合、これはどのように機能しますか?

Windows Hello を使用すると、すべてのデバイスで一意の秘密キーと公開キー セットが作成されます。 つまり、ユーザーが複数のデバイスを使用できるようにする場合、バックエンドはこのユーザーから複数の公開キーを格納できる必要があります。 テーブル構造の例については、「 新規ユーザーの登録 」セクションのデータベース 図を参照してください。

別のデバイスの登録は、ユーザーを初めて登録する場合とほぼ同じです。 引き続き、この新しいデバイスに登録しているユーザーが実際にユーザーであることを確認する必要があります。 これは、現在使用されている 2 要素認証メカニズムを使用して行うことができます。 これを安全な方法で実現するには、いくつかの方法があります。 これはすべて、シナリオによって異なります。

たとえば、ログイン名とパスワードを引き続き使用する場合は、それを使用してユーザーを認証し、SMS や電子メールなどの検証方法のいずれかを使用するように求めることができます。 ログイン名とパスワードがない場合は、既に登録されているデバイスのいずれかを使用して、そのデバイス上のアプリに通知を送信することもできます。 この例は、MSA 認証アプリです。 つまり、一般的な 2FA メカニズムを使用して、ユーザーに追加のデバイスを登録する必要があります。

新しいデバイスを登録するコードは、(アプリ内から) 初めてユーザーを登録する場合とまったく同じです。

var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(
    AccountId, KeyCredentialCreationOption.ReplaceExisting);

登録されているデバイスをユーザーが認識しやすくするために、登録の一部としてデバイス名または別の識別子を送信することを選択できます。 これは、たとえば、デバイスが失われたときにユーザーがデバイスの登録を解除できるサービスをバックエンドに実装する場合にも役立ちます。

アプリで複数のアカウントを使用する

1 つのアカウントで複数のデバイスをサポートするだけでなく、1 つのアプリで複数のアカウントをサポートすることも一般的です。 たとえば、アプリ内から複数の Twitter アカウントに接続している可能性があります。 Windows Hello では、複数のキー ペアを作成し、アプリ内で複数のアカウントをサポートできます。

これを行う 1 つの方法は、分離ストレージに関する前のセクションで説明したユーザー名または一意の識別子を保持することです。 そのため、新しいアカウントを作成するたびに、アカウント ID を分離ストレージに格納します。

アプリ UI では、ユーザーが以前に作成したアカウントのいずれかを選択するか、新しいアカウントでサインアップすることを許可します。 新しいアカウントを作成するフローは、前に説明したフローと同じです。 アカウントの選択は、保存されているアカウントを画面に一覧表示することです。 ユーザーがアカウントを選択したら、アカウント ID を使用してアプリでユーザーにログオンします。

var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

フローの残りの部分は、前に説明した内容と同じです。 明確に言うと、これらのアカウントはすべて、同じ PIN または生体認証ジェスチャによって保護されます。このシナリオでは、同じ Windows アカウントを持つ単一のデバイスで使用されているためです。

既存のシステムを Windows Hello に移行する

この短いセクションでは、ユーザー名とハッシュされたパスワードを格納するデータベースを使用する既存のパッケージ アプリとバックエンド システムに対処します。 これらのアプリは、アプリの起動時にユーザーから資格情報を収集し、バックエンド システムが認証チャレンジを返すときに使用します。

ここでは、Windows Hello を動作させるために変更または置換する必要がある部分について説明します。

前のセクションでほとんどの手法を既に説明しました。 既存のシステムに Windows Hello を追加するには、コードの登録と認証の部分に、いくつかの異なるフローを追加する必要があります。

1 つの方法は、アップグレードするタイミングをユーザーが選択できるようにすることです。 ユーザーがアプリにログオンし、アプリと OS が Windows Hello をサポートできることが検出されたら、この最新のセキュリティで保護されたシステムを使用するために資格情報をアップグレードするかどうかをユーザーに確認できます。 次のコードを使用して、ユーザーが Windows Hello を使用できるかどうかを確認できます。

var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();

UI は次のようになります。

Windows Hello ユーザー インターフェイスのスクリーンショット

ユーザーが Windows Hello の使用を開始する場合は、前に説明した KeyCredential を作成します。 バックエンド登録サーバーは、公開キーとオプションの構成証明ステートメントをデータベースに追加します。 ユーザーは既にユーザー名とパスワードで認証されているため、サーバーは新しい資格情報をデータベース内の現在のユーザー情報にリンクできます。 データベース モデルは、前に説明した例と同じにすることができます。

アプリがユーザー KeyCredentialを作成できた場合は、分離ストレージにユーザー ID が格納されるため、ユーザーはアプリを再度起動した後に一覧からこのアカウントを選択できます。 この時点から、フローは前のセクションで説明した例に正確に従います。

完全な Windows Hello シナリオに移行する最後の手順は、アプリのログオン名とパスワード オプションを無効にし、格納されているハッシュされたパスワードをデータベースから削除することです。

まとめ

Windows では、より高いレベルのセキュリティが導入されており、実装も簡単です。 Windowsこんにちは新たな生体認証ログイン認識システムのユーザーの積極的な取組みに反を回避するに正します。 その後、信頼されたプラットフォーム モジュールの外部で公開または使用できない複数のキーと証明書のレイヤーを提供できます。 さらに、構成証明 ID キーと証明書をオプションで使用して、セキュリティをさらに強化できます。

開発者は、これらのテクノロジの設計と展開に関するこのガイダンスを使用して、パッケージ化された Windows アプリのロールアウトにセキュリティで保護された認証を簡単に追加して、アプリとバックエンド サービスを保護できます。 必要なコードは最小限で、理解しやすいです。 Windows は重い持ち上げを処理します。

柔軟な実装オプションを使用すると、Windows Hello を既存の認証システムに置き換えたり、既存の認証システムと連携させたりすることができます。 デプロイ エクスペリエンスは痛みがなく、経済的です。 Windows セキュリティを展開するために追加のインフラストラクチャは必要ありません。 Microsoft Hello がオペレーティング システムに組み込まれていると、Windows は最新の開発者が直面している認証の問題に対して最も安全なソリューションを提供します。

ミッションは完了です。 あなたはインターネットをより安全な場所にしました!

その他のリソース

記事とサンプル コード

用語

相談 定義
AIK 構成証明 ID キーは、移行不可能なキーのプロパティに署名し、検証のためにプロパティと署名を証明書利用者に提供することによって、このような暗号化証明 (TPM キー構成証明) を提供するために使用されます。 結果のシグネチャは"構成証明ステートメント" と呼ばれます。 署名は AIK 秘密キー (作成した TPM でのみ使用できる) を使用して作成されるため、証明書利用者は、構成証明されたキーが本当に移行不可能であり、その TPM の外部で使用できないことを信頼できます。
AIK 証明書 AIK 証明書は、TPM 内に AIK が存在することを証明するために使用されます。 また、AIK によって認定された他のキーがその特定の TPM から生成されたことを証明するためにも使用されます。
IDP IDP は ID プロバイダーです。 たとえば、Microsoft アカウント用の Microsoft による IDP ビルドがあります。 アプリケーションは、MSA で認証する必要があるたびに、MSA IDP を呼び出すことができます。
PKI 公開キー インフラストラクチャは、通常、組織自体によってホストされ、キーの作成やキーの取り消しなどを担当する環境を指すために使用されます。
TPM トラステッド プラットフォーム モジュールを使用すると、秘密キーを TPM の外部で表示したり使用したりできない (つまり、キーが移行不可能) ように、暗号化公開キーと秘密キーのペアを作成できます。
TPM キーの構成証明 キーが TPM にバインドされていることを暗号で証明するプロトコル。 この種類の構成証明は、特定のコンピューターの TPM で特定の暗号化操作が発生したことを保証するために使用できます。