Wdrażanie poświadczania cyfrowych dokumentów tożsamości za pomocą sprzętu

W typowym procesie wydawania cyfrowych poświadczeń zgodnie ze specyfikacją OpenID for Verifiable Credential Issuance (OpenID4VCI) wystawca musi mieć pewność, że klucz w poświadczeniu, które ma zostać podpisane, jest przechowywany w bezpiecznym miejscu. android_keystore_attestation Typ weryfikacji – format do użycia z OpenID4VCI – zapewnia podpisany sprzętowo raport z magazynu kluczy Androida, co gwarantuje, że klucz jest zablokowany w zaufanym środowisku wykonawczym (TEE) lub StrongBox i nie można go wyeksportować ani sklonować.

Omówienie atestu sprzętowego

Gdy klucz zostanie wygenerowany w magazynie kluczy Androida, system może wygenerować certyfikat atestu. Ten certyfikat jest podpisany kluczem chronionym przez sprzęt urządzenia, który jest powiązany z głównym źródłem zaufania należącym do Google.

Dowód android_keystore_attestation to tablica łańcuchów certyfikatów X.509. Każdy łańcuch reprezentuje pojedynczy klucz uwierzytelniania i jest zbudowany z certyfikatu liścia, a następnie z certyfikatów pośrednich.

  • Certyfikat końcowy: zawiera klucz i rozszerzenie atestu specyficzne dla Androida.
  • Certyfikaty pośrednie: połącz certyfikat końcowy z certyfikatem głównym Androida.

Działania weryfikacyjne

Wystawcy powinni przeprowadzić kilka weryfikacji zaświadczenia.

  • Znajdź w łańcuchu certyfikat zawierający rozszerzenie atestu Androida (zwykle jest to certyfikat liścia). Ten certyfikat zawiera dane atestu klucza wygenerowanego przez Magazyn kluczy Androida.
  • Sprawdź, czy pole attestationChallenge w rozszerzeniu jest zgodne z polem c_nonce dostarczonym przez protokół, aby zapobiec atakom typu replay.
  • Sprawdź wartość wszystkich asercji w interesujących Cię rozszerzeniach.
  • Sprawdź, czy certyfikaty w magazynie kluczy Androida nie zostały unieważnione.

Wartości w dowodzie atestu pochodzą z kilku źródeł:

  • Wystawca: różne wartości są podawane przez wystawcę i najczęściej umieszczane w formacie metadanych wystawcy, aby umożliwić filtrowanie podczas prezentacji.
  • Właściciel: wartości takie jak nazwa pakietu i podpis pochodzą od właściciela. Nie są one udostępniane w ramach standardowych procedur wydawania i muszą być pozyskiwane niezależnie od posiadacza.
  • Protokół: wartości takie jak nonce z symbolem attestationChallenge pochodzą z protokołu.

Bardziej szczegółowe instrukcje weryfikacji danych atestu znajdziesz w tych materiałach:

Format dowodu atestu

W prośbie o dane logowania dowód android_keystore_attestation jest uwzględniony w tym przykładzie:

{
  "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
}

Jest on następnie przechowywany w obiekcie proofs żądania danych logowania.

{
  "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
    ]
  }
}

Format metadanych wystawcy

Wystawca wskazuje obsługiwane typy dowodów, umieszczając obiekt android_keystore_attestation w obiekcie proof_types_supported w przypadku danej konfiguracji dokumentu.

Oto przykład obiektu android_keystore_attestation dla wydawców:

{
  "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"]
}

Oto przykład zewnętrznego obiektu 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"]
          }
        }
      }
    }
  }
}

Mapowanie roszczeń atestacyjnych VCI na Keystore Androida

Ta tabela zawiera mapowanie informacyjne, które pomoże podmiotom znającym standardowy typ dowodu zaświadczenia OpenID4VCI zrozumieć, gdzie w zaświadczeniu z Android Keystore znajdują się podobne pojęcia.

Roszczenie dotyczące atestu VCI

android_keystore_attestation lokalizacja

Lokalizacja wartości oczekiwanej

iss

Klucz publiczny certyfikatu głównego magazynu kluczy

Nie dotyczy

iat

Wartość creationDateTime w rozszerzeniu atestu

Nie dotyczy

exp

pole validUntil w certyfikacie wierzchołka ścieżki,

Nie dotyczy

attested_keys

Klucz publiczny zawarty w certyfikacie liścia każdego łańcucha

Nie dotyczy

key_storage

Wartość keyMintSecurityLevel w rozszerzeniu atestu

Wybrany wydawca: pole key_mint_security_level w metadanych wydawcy

user_authentication

Wartości userAuthType i noAuthRequired w rozszerzeniu atestu

Wybrany wydawca: pole user_auth_types w metadanych wydawcy

nonce

Wartość attestationChallenge w rozszerzeniu atestu

Z protokołu: c_nonce wartość z punktu końcowego nonce opisanego w VCI

certyfikat

Nie dotyczy

Nie dotyczy

status

Nie dotyczy

Nie dotyczy