LINEヤフー Tech Blog

LINEヤフー株式会社のサービスを支える、技術・開発文化を発信しています。

This post is also available in the following languages. English, Korean

FIDO2クライアントSDK オープンソースのご紹介

はじめに

はじめまして。セキュリティ開発チームでFIDO2クライアントの開発を担当しているキム・ドヨン、キム・ヨンヒョンと申します。

公開鍵暗号方式に基づく FIDO 認証は、パスワードやSMS OTPよりも安全で、ユーザーエクスペリエンスの面において使いやすく、サービスの面でも導入・管理しやすい認証規格です。 FIDO認証の資格証明データは、ユーザーのデバイスを離れずにサーバーにも保存されないため、フィッシング(phishing)やあらゆる形態のパスワード盗用およびリプレイ攻撃(Replay Attack)のリスクを軽減できます。

弊社はLINEヤフー株式会社に合併する前、ヤフーが2014年にFIDOアライアンスに加入し2019年に取締役に選任、LINEが2017年にFIDOアライアンスの取締役陣に加入したのを皮切りに、FIDOサーバーの相互運用性試験イベントに参加するなど、FIDOに関連したさまざまなイベントに参加しました。 そして2021年には、サービスプロバイダとして世界で初めてFIDO Universal Server認証を取得したFIDO2サーバーをオープンソースとして公開しました。 これに関連した内容をTech Blogにて「パスワードのいらない世界に向けて」と「LINE FIDO2-Serverをオープンソースとして公開しました」というタイトルで公開しました。本稿では、新たにオープンソースとして公開するWebAuthn標準に準拠したFIDO2クライアントSDKをご紹介します。このSDKを使用することで、アプリでFIDO2ベースの生体認証を容易に実装できるようになります。

FIDOの紹介

パスワードや暗証番号による知識認証を使用する従来の認証方式を代替するための新たな標準認証方式であるFIDO(Fast Identity Online)は「所有」と「生体」の組み合わせを基にした認証方式を提案します。

従来型の認証方式である知識認証は、ユーザーとサーバーが事前に設定した知識を基盤にした認証方式です。ユーザーの観点ではパスワードのような知識を覚えていなければならないという不便さがあり、攻撃者がユーザーのパスワードを推測したり、サーバーに保存されたパスワードが流出する可能性があるため、そのリスクに対処するには追加のセキュリティレイヤーが要求されます。

所持情報による認証は、ユーザーが所持している機器を基盤として認証を行う方式です。FIDOの認証方式はユーザーのデバイスを認証機(authenticator)として活用します。ユーザーの認証情報(例: 生体情報)はデバイスにのみ保存され、サーバーには伝わらないため、サービスの面ではセキュリティをさらに強化できます。ユーザーはパスワードを記憶する必要がなく、ユーザーだけが持っている情報を通じて安全かつ簡易に認証できます。

FIDO1とFIDO2の違い

FIDO1とFIDO2の違いは次のとおりです。

  • FIDO1: FIDO1は、UAF(Universal Authentication Framework)とU2F(Universal 2nd Factor)という二つのプロトコルを含みます。 UAFはパスワードなし認証を提供するプロトコルであり、U2Fは既存のパスワードベース認証に二要素認証(2FA)を提供するプロトコルです。
  • FIDO2: FIDO2はFIDO1が拡張されたバージョンで、WebAuthn(Web Authentication)とCTAP(Client to Authenticator Protocol)が含まれます。 FIDO2はウェブアプリケーションとの統合を強化し、より多様な認証方法を支援します。

FIDO2に新しく含まれたWebAuthnとCTAPについて、一つずつご説明いたします。

WebAuthn

WebAuthnは、W3C(World Wide Web Consortium)によって標準化されたウェブ認証プロトコルです。これにより、ウェブブラウザとウェブアプリがFIDO認証をサポートするデバイスと直接通信できるようになります。WebAuthnは、ユーザーがパスワードを使用せずに安全にログインできるように設計されています。
WebAuthnで提供する機能は次のとおりです。

  • 登録(registration): ユーザーは、自分のデバイスをWebアプリに登録します。この過程で秘密鍵と公開鍵が生成され、公開鍵はサーバーに保存され、秘密鍵はデバイスにのみ保存されます。
  • 認証(authentication): ユーザーがWebアプリにログインするとき、デバイスは秘密鍵を使用して署名を生成し、これをサーバーに転送します。 サーバーは公開鍵を使用して署名を検証し、ユーザーを認証します。

WebAuthnはWebアプリだけでなくネイティブアプリでも同様に使用できます。iOSやAndroidのようなプラットフォームが提供する生体認証APIを基にして、WebAuthn規格に従う認証を実現できます。

CTAP

CTAPはFIDOアライアンスが開発したプロトコルで、クライアントと認証機の間の通信に使用されるプロトコルです。CTAPには2つのバージョンがあります。

  • CTAP1: U2Fプロトコルに基づいており、二要素認証(2FA)を提供します。既存のFIDO U2Fデバイスと互換性があります。
  • CTAP2: FIDO2規格の一部としてパスワードなし認証をサポートし、WebAuthnとともに動作してさまざまな認証方法を提供します。

FIDO2クライアントSDKの紹介

セキュリティ開発チームでは、パスワードなし認証をより簡単にサービスに統合できるよう、FIDO2クライアントSDKを実装しました。私たちが開発したSDKは、最新のセキュリティ基準を遵守し、FIDO2認証を受けたサーバーと互換性があるようにWebAuthn Level 2仕様に従っています。

私たちが現在W3Cで作業中のLevel3ではなく、Level2を採用した理由は2つあります。 まず、Level 3スペックはまだ公式に確定していないドラフト(draft)状態であり、 Level2はすでにW3Cの公式勧告(recommendation)として採用されており、より安定した仕様です。 また、Level3で紹介されたパスキーを使えば、同じアカウント内で鍵が同期されて複数デバイス間で鍵を共有できるようになっており、各プラットフォームで提供しているPasskey関連APIでは、鍵の同期をオフにする方法がありませんので、ビジネスのセキュリティ方針に従って認証鍵の同期を許容してはならない要件に対処することが困難です。

このような理由から、私たちはLevel 2スペックに従っており、今後Level 3スペックが公式に確定し、Passkeyの同期問題に対する解決策が用意されれば、これを検討してスペックをアップデートする予定です。

それでは私たちが開発したFIDO2クライアントSDKを詳しくご説明いたします。 FIDO2クライアントSDKは、ネイティブアプリで使いやすい構造に設計されています。 AndroidとiOSプラットフォームで簡単に統合できますように、KotlinとSwiftで実装し、次のようなメリットを得られます。

  • プラットフォーム最適化: クライアントをネイティブコードで開発したため、ネイティブアプリで追加インターフェースの実現なしにFIDO2 APIを呼び出すことができます。また、デバイスの生体認証機能(Face ID、Touch IDなど)を直接活用し、各プラットフォームに最適化された認証経験を提供します。 
  • 開発の容易性:SDKを利用すると、クライアントと認証機の間の転送プロトコルやCTAPインターフェースを別途に実装する必要がないため、比較的簡単かつ迅速に開発することが可能です。 これにより、開発者はより少ない労力でパスワードなし認証をサービスに統合できます。
  • 柔軟性: 各サービス固有の認証ロジックが必要な場合は、カスタム クライアントと認証機を簡単に追加できます。 これにより、さまざまなビジネス要件を満たすことができ、ユーザーエクスペリエンスを改善できます。
  • セキュリティ:デバイス内にハードウェア支援を用いた隔離実行環境として、セキュリティ的に信頼可能な高信頼実行環境(例:iOS Secure Enclave、ARM TrustZone、Android StrongBox)を直接活用し、生体認証データを安全に処理します。

下は、FIDO2 クライアントSDK の全体構造を簡略化した図です。

  • PublicKeyCredential:ユーザー登録および認証全般のためのインターフェースとして、新たな公開鍵クレデンシャル(public key credential、非対称鍵ペアおよび鍵関連情報)を生成し、これに基づいて認証を実行します。開発者はこのインターフェースを使ってWebAuthn 規格によるユーザー登録および認証機能をサービスに統合します。
  • Authenticator: ユーザーの身元を確認した後、識別されたユーザーに対して新たな公開鍵クレデンシャルを生成し、生成された公開鍵クレデンシャルを使用するインターフェースです。
  • 高信頼実行環境(Trusted Execution Environment, TEE): デバイス内にハードウェア支援を用いた隔離実行環境として、セキュリティ的に信頼可能な高信頼実行環境を指します。TEE 内のデータは、その環境外のコード(例えば、App,OS レベルでのアクセス)で読み取ったり改ざんしたりできず、公開鍵クレデンシャルの秘密鍵と生体情報がTEE内に保存されます。
  • FIDO2サーバー(FIDO2 Server): ユーザー登録および認証プロセス上で必要な検証ロジックを実行するサーバーです。 認証のため、公開鍵クレデンシャルの公開鍵がFIDO2サーバーに保存されます。
  • ユーザー(User): サービスを利用するユーザーとして、デバイスを所持するユーザーです。生体認証またはパスコード(デバイス上でユーザーを認証するためのローカルパスワードで、サーバーに保存される情報ではありません)を入力する主体で、認証機と相互作用します。

動作方式を各段階別に説明しますと、次のとおりです。

  1. PublicKeyCredentialは、リプレイ攻撃を防ぐためにFIDO2サーバーにチャレンジを要求し、受け取ります。
  2. PublicKeyCredentialは、内部的にAuthenticatorを呼び出します。
  3. Authenticatorは、生体認識またはパスコードなどのデバイスの認証情報(Device Credential)に基づいてユーザーの身元を確認します。
  4. ユーザーの身元確認が完了したら、TEEで公開鍵クレデンシャルを生成または使用します。このとき、秘密鍵を使用してチャレンジを含むユーザー登録および認証プロセスに必要なデータを署名します。
  5. PublicKeyCredentialは、Authenticatorを通じて署名されたデータを受け取り、FIDO2サーバーに検証を要請します。
  6. FIDO2サーバーは、登録プロセスを通じて、事前に登録された公開鍵に基づいて署名されたデータを検証します。

次に、FIDO2クライアントSDKの主要インターフェースであるPublicKeyCredentialAuthenticatorのパートをより詳しくご説明いたします。

PublicKeyCredential

PublicKeyCredentialはWebAuthn Level 2仕様のPublicKeyCredentialインターフェースを実装したもので、パスワードではなく非対称キーペア(asymmetric key pair)をクレデンシャルとして使用します。このインターフェースにより、クレデンシャルを生成してユーザーを登録でき、生成されたクレデンシャルを使用してユーザー認証を行うことができます。

PublicKeyCredentialインターフェースは、ユーザー登録および認証のためにWebAuthn Level 2仕様に定義された二つのAPIであるcreategetメソッドを提供します。createメソッドはユーザー登録を行い、認証機を通じて新しいクレデンシャルを生成します。 getメソッドはcreateメソッドから生成されたクレデンシャルに基づいて認証を実行します。この二つのメソッドはWebAuthn Level 2仕様に明示された基本ロジックを提供するだけでなく、自主的にFIDO2サーバーと通信してクレデンシャルを検証する役割も果たします。

FIDO2クライアントSDKでは、サービス開発者がFIDO2サーバーのAPIを呼び出す際にネットワーキング方法を選択し、カスタムロジックを実装できるようにRelyingPartyインターフェースを提供します。サービス開発者は、FIDO2サーバー側のAPIとの応答をやりとりできるように、RelyingPartyインターフェースを実装する必要があります。 そのためにRelyingPartyインターフェースのテンプレートを別途提供しています。

FIDO2クライアントSDKでは、さまざまなユーザー認証方式に対応するため、認証機ごとに別途のクライアントを実装しました。 現在、PublicKeyCredentialインターフェースの実装体としては、BiometricDeviceCredential 2種類の認証機に対応しています。BiometricBiometricAuthenticatorとして、ユーザーの身元確認時に生体情報だけを基にした認証機です。DeviceCredentialDeviceCredentialAuthenticatorとして、ユーザーの身元確認時に生体情報またはパスコードなどのデバイスの認証情報を基にした認証機です。 各認証機については、以下で詳しく説明いたします。

Authenticator

AuthenticatorWebAuthn Level 2仕様の認証機モデル(authenticator model)を基に実装されたコンポーネントで、OSレベルで提供される認証機能に基づいてユーザー登録または認証を試みる対象が正しいユーザーであるかどうかを識別する重要なコンポーネントです。

Authenticatorはユーザー登録および認証プロセス上で次のような重要な役割を果たします。

  • クレデンシャルの生成と保存: ユーザーが新しいサービスに登録するときに固有のクレデンシャルを生成します。 このクレデンシャルは、デバイス内のセキュリティ的に信頼可能な高信頼実行環境で生成された公開鍵と秘密鍵のペアで構成されています。公開鍵はユーザー登録および証明プロセスが完了した後にサーバーに保存され、秘密鍵はデバイス内の高信頼実行環境にのみ保存されます。

  • クレデンシャル関連情報の保存:クレデンシャルを管理するために、関連情報である公開鍵クレデンシャルソース(publickey credential source)署名カウンター(signature counter)を保存します。 FIDO2クライアントSDKでは、アプリ開発者が状況に応じた適切なストレージを選択できるように、クレデンシャルソースストレージインターフェースを提供しています。 アプリ開発者は、公開鍵クレデンシャルソースと署名カウンターが正しく保存·管理されるように、クレデンシャルソースストレージインターフェイスに従うストレージを実装する必要があります。

  • ユーザーの身元確認: ユーザーに生体認証またはパスコードの入力を要求して、ユーザーの身元を確認します。

  • 認証情報の生成:ユーザー登録プロセス上では、秘密鍵で署名された証明オブジェクト(attestation object)を生成し、ユーザー認証プロセス上では、署名されたアサーションオブジェクト(assertion object)を生成します。 どちらのオブジェクトもFIDO2サーバーに送信され、公開鍵で検証されます。

このような役割を果たすために、AuthenticatorはWebAuthn Level2仕様のAuthenticator Operationsに該当する二つのメソッドであるmakeCredentialgetAssertionに対応しています。 makeCredentialPublicKeyCredentialcreateメソッド内部で呼び出されるメソッドであり、getAssertionPublicKeyCredentialgetメソッド内部で呼び出されるメソッドです。 各メソッドの具体的な動作方式は、各メソッドのリンクから確認できます。

FIDO2クライアントSDKは、生体認証に基づくBiometricAuthenticatorとデバイスの認証情報(デバイスクレデンシャル認証)に基づくDeviceCredentialAuthenticatorに対応しています。 各認証方式の特徴についてご説明いたします。

生体認証

デバイスの生体認証(Face ID、Touch IDなど)を基にした認証方式です。 この認証方式では、ユーザー登録後に新しい生体情報が追加される場合、既存の生体情報が無効になります。例えば、デバイスに指紋Aが追加された状態で、クレデンシャルを登録した後、デバイスに新しい指紋Bを追加すると、既存の生体情報が無効化され、既存に登録したクレデンシャルを使用して認証することができず、クレデンシャルの再登録が必要になります。 これはセキュリティレベルの高い方式です。

デバイスクレデンシャル認証

生体認証またはパスコードなどのデバイスの認証情報に基づく認証方式です。 この方式は、生体認証に比べて柔軟な認証方式を提供します。生体認証に対応していない場合、パスコードを入力することができ、生体認証に対応するデバイスでも生体認証に数回失敗すると、パスコードを入力できるように補助認証手段を提供します。生体認証とデバイス認証情報を組み合わせて使用することもできます。つまり、指紋を利用してクレデンシャルを登録した場合でも、認証時に指紋およびパスコードのようなデバイス認証情報をすべて使用できます。 また、生体情報の追加に影響を受けず、追加された生体情報と既存の認証情報と互換性があります。例えば、デバイスに指紋Aが追加された状態でクレデンシャルを登録した後、デバイスに新しい指紋Bを追加する場合にも、指紋Aと指紋Bの両方が既存のクレデンシャルを使用して認証することが可能です。

FIDO2クライアントオープンソースのご紹介

私たちのチームは以前、LINE FIDO2サーバーをオープンソースとして公開したのに続き、新たに開発したFIDO2クライアントSDKおよびテストのためのデモアプリコードもオープンソースとして公開することに決定しました。このような活動が究極的にアプリのセキュリティとFIDOエコシステムの発展に寄与すると期待し、オープンソースで公開したSDKとデモアプリを簡単に紹介したいと思います。

FIDO2クライアントSDK

私たちのチームのFIDO2クライアントSDKオープンソースのGitHubリポジトリは以下の通りです。

ライセンスはApache License 2.0を元にしており、それぞれ以下のような環境で動作します。

  • Android
    • Gradle 7.6.3
    • Android API level 28以上
  • iOS
    • Swift 5.9以上

前述したように、FIDO2クライアントSDKを使用するためには、アプリ開発者がSDKで提供するCredential Source StorageRelying Partyインターフェースをそれぞれ実装する必要があります。 詳しい情報は各リポジトリのREADME.mdをご参照ください。

デモアプリ

私たちのチームは、アプリ開発者がFIDO2クライアントSDKの使用方法を理解し、より簡単にサービスに統合できるよう、ユーザー登録と認証プロセスを含むデモアプリをプラットフォーム別SDKとともにオープンソースとして公開しました。 各プラットフォーム別デモアプリのGitHubリポジトリは以下の通りです。

ライセンスはApache License 2.0を元にしており、それぞれ以下のような環境で動作します。

  • Android
    • Gradle 7.6.3
    • Android API level 28以上
  • iOS
    • Swift 5.9以上
    • Xcode 15.4以上

デモアプリでは、FIDO2クライアントSDKを使用する際に、アプリ開発者が直接実装しなければならないCredentialSourceStorageRelyingPartyインターフェースの実装例を確認できます。

デモアプリを実行するためには、アプリと相互作用するFIDO2サーバーを起動させる必要があります。私たちのチームが提供するFIDO2オープンソースサーバーを使用する場合は、こちらのREADME.mdをご参照ください。

まとめ

私たちが公開したFIDO2クライアントSDKとデモアプリは、FIDOエコシステムの発展を目指した取り組みの一環です。オープンソースコードに関してイシューがあったり、改善事項を提案したい場合はいつでもGitHubイシュートラッカーにご投稿くださいますようお願い申し上げます。

私たちのチームは、オープンソースコミュニティと協力しながら、プロジェクトの継続的な改善を計画しています。新しい機能の追加や性能の向上、バグ修正を通じて、より良いソリューションを提供できるよう努めています。 最後までご覧いただき、ありがとうございました。