デジタル認証情報にハードウェア格納型の証明書を実装する

OpenID for Verifiable Credential Issuance(OpenID4VCI)仕様を使用した一般的なデジタル認証情報の発行フローでは、署名される認証情報内の鍵が安全な場所に保存されていることを発行者が知る必要があります。android_keystore_attestation 証明タイプ( OpenID4VCI で使用する形式)は、 Android Keystore からハードウェア署名付きレポートを提供し、鍵が Trusted Execution Environment(TEE)または StrongBox にロックされ、エクスポートまたはクローン作成できないようにします。

ハードウェア証明書の概要

Android Keystore で鍵が生成されると、システムは証明書を生成できます。この証明書は、デバイスのハードウェアで保護された鍵によって署名され、Google が保持するルート オブ トラストにチェーンバックされます。

android_keystore_attestation 証明は、X.509 証明書チェーンの配列です。各チェーンは単一の認証鍵を表し、リーフ証明書と中間証明書で構成されています。

  • リーフ証明書: 鍵と Android 固有の証明書 拡張機能が含まれています。
  • 中間証明書: リーフを Android ルートに接続します。

確認手順

発行者は、証明書に対していくつかの検証を行う必要があります。

  • Android 証明書拡張機能を含むチェーン内の証明書を見つけます(通常はリーフ証明書)。この証明書には、Android Keystore によって生成された鍵の証明書データが含まれています。
  • リプレイ攻撃を防ぐため、拡張機能の attestationChallenge フィールドがプロトコルによって提供された c_nonce と一致していることを確認します。
  • 関心のある拡張機能のすべてのアサーションの値を確認します。
  • Android Keystore 証明書に対して失効チェックを行います。

証明書証明の値は、次のようないくつかのソースから取得されます。

  • 発行者: 発行者によってさまざまな値が提供されます。最も一般的な値は、プレゼンテーション時にフィルタリングできるように、 発行者メタデータ形式で指定されます。
  • 保持者: パッケージ名や署名などの値は保持者から取得されます。これらは標準の発行手順では共有されないため、保持者から個別に取得する必要があります。
  • プロトコル: attestationChallenge を含む nonce などの値はプロトコルから取得されます。

証明書データの検証の詳細については、次のリソースをご覧ください。

証明書証明の形式

認証情報リクエストでは、次の例に示すように、android_keystore_attestation 証明が含まれています。

{
  "type": "array",
  "description": "An array of certificate chains. Each chain attests a single key.",
  "items": {
    "type": "array",
    "description": "An X.509 certificate chain. Each certificate is a Base64-encoded string. The first element in the chain is the leaf certificate with the extension, the last is the Android Keystore root certificate.",
    "items": {
      "type": "string",
      "description": "A single X.509 certificate (Base64-NoWrap padded DER encoded)."
    },
    "minItems": 1
  },
  "minItems": 1
}

その後、認証情報リクエストの proofs オブジェクトに保存されます。

{
  "credential_configuration_id": "org.iso.18013.5.1.mDL",
  "proofs": {
    "android_keystore_attestation": [
      [
        "MII...", // Leaf certificate (contains Keystore extension)
        "MII...", // Intermediate certificate
        "MII..."  // Android Root certificate
      ],
      [ "MII...", "MII...", "MII..." ] // second proof
    ]
  }
}

発行者メタデータ形式

発行者は、特定の認証情報構成の proof_types_supported オブジェクト内に android_keystore_attestation オブジェクトを含めることで、サポートする証明タイプを示します。

発行者の android_keystore_attestation オブジェクトの例を次に示します。

{
  "type": "object",
  "properties": {
    "proof_signing_alg_values_supported": {
      "type": "array",
      "description": "REQUIRED. As defined in OpenID4VCI 1.0 Section 12.2.4.",
      "items": {
        "type": "string",
        "description": "Cryptographic algorithm identifiers used in the proof_signing_alg_values_supported Credential Issuer metadata parameter for this proof type are case sensitive strings and SHOULD be one of those defined in [IANA.JOSE]."
      },
      "minItems": 1
    },
    "key_attestations_required": {
      "type": "object",
      "description": "OPTIONAL. Specifies the minimum attestation requirements.",
      "properties": {
        "key_mint_security_level": {
          "type": "string",
          "description": "OPTIONAL. Minimum accepted keyMintSecurityLevel. Values defined in https://source.android.com/docs/security/features/keystore/attestation#securitylevel-values.",
          "enum": ["Software", "TrustedEnvironment", "StrongBox"],
          "default": "TrustedEnvironment"
        },
        "user_auth_types": {
          "type": "array",
          "description": "OPTIONAL. A list of authentication types which can authorize the use of the key. If empty, no authentication is required. If multiple, any are allowed.",
          "items": {
            "type": "string",
            "description": "Allowed values are 'LSKF' and 'BIOMETRIC'. These values are meant to mimic the values used during the key generation process here.",
            "enum": ["LSKF", "BIOMETRIC"]
          },
          "default": []
        }
      }
    }
  },
  "required": ["proof_signing_alg_values_supported"]
}

外側の proof_types_supported オブジェクトの例を次に示します。

{
  "credential_configurations_supported": {
    "org.iso.18013.5.1.mDL": {
      "format": "mso_mdoc",
      "doctype": "org.iso.18013.5.1.mDL",
      "cryptographic_binding_methods_supported": [
        "cose_key"
      ],
      "credential_signing_alg_values_supported": [
        -7, -9
      ],
      "proof_types_supported": {
        "android_keystore_attestation": {
          "proof_signing_alg_values_supported": [
            "ES256" // ecdsaWithSHA256
          ],
          "key_attestations_required" : {
            // OPTIONAL String - Representing the minimum accepted value for keyMintSecurityLevel values
            // defined here ("Software"|"TrustedEnvironment"|"StrongBox"). Default value: "TrustedEnvironment"
            "key_mint_security_level": "TrustedEnvironment",
            // OPTIONAL List of Strings - Representing all allowed values for userAuthType values defined here.
            // [] value will represent noAuthRequired. Default value: [].
            "user_auth_types": ["LSKF", "BIOMETRIC"]
          }
        }
      }
    }
  }
}

VCI 証明書クレームを Android Keystore にマッピングする

この表は、標準の OpenID4VCI 証明書証明タイプに精通しているエンティティが、同様のコンセプトが Android Keystore 証明書内のどこにあるかを理解するのに役立つ情報マッピングを示しています。

VCI 証明書クレーム

android_keystore_attestation の場所

期待値の場所

iss

Keystore ルート証明書の公開鍵

なし

iat

証明書拡張機能の creationDateTime

なし

exp

リーフ証明書の validUntil フィールド

なし

attested_keys

各チェーンのリーフ証明書に含まれる公開鍵

なし

key_storage

証明書拡張機能の keyMintSecurityLevel

発行者が選択: 発行者メタデータの key_mint_security_level フィールド

user_authentication

証明書拡張機能の userAuthType 値と noAuthRequired

発行者が選択: 発行者メタデータの user_auth_types フィールド

nonce

証明書拡張機能の attestationChallenge

プロトコルから: VCI で説明されている nonce エンドポイントc_nonce

certification

なし

なし

status

なし

なし