Implementare l'attestazione basata sull'hardware per le credenziali digitali

In un tipico flusso di emissione di credenziali digitali che utilizza la specifica OpenID for Verifiable Credential Issuance (OpenID4VCI), un emittente deve sapere che la chiave all'interno della credenziale da firmare è archiviata in una posizione sicura. Il tipo di prova android_keystore_attestation, un formato da utilizzare con OpenID4VCI, fornisce un report firmato dall'hardware dall'archivio chiavi Android, garantendo che la chiave sia bloccata in un ambiente di esecuzione attendibile (TEE) o StrongBox e non possa essere esportata o clonata.

Panoramica dell'attestazione hardware

Quando viene generata una chiave nell'Android Keystore, il sistema può generare un certificato di attestazione. Questo certificato è firmato da una chiave protetta dall'hardware del dispositivo, che rimanda a una radice di attendibilità di proprietà di Google.

La prova android_keystore_attestation è un array di catene di certificati X.509. Ogni catena rappresenta una singola chiave di autenticazione ed è strutturata da un certificato dell'entità finale seguito da certificati intermedi.

  • Certificato foglia: contiene la chiave e un'estensione di attestazione specifica per Android.
  • Certificati intermedi: collegano la foglia alla radice Android.

Procedura di verifica

Gli emittenti devono eseguire diverse convalide dell'attestazione.

  • Trova il certificato nella catena che contiene l'estensione di attestazione Android (in genere il certificato foglia). Questo certificato contiene i dati di attestazione per la chiave creata da Android Keystore.
  • Verifica che il campo attestationChallenge nell'estensione corrisponda al c_nonce fornito dal protocollo per impedire attacchi di replay.
  • Verifica il valore di tutte le asserzioni nelle estensioni che ti interessano.
  • Esegui un controllo della revoca rispetto ai certificati dell'archivio chiavi Android.

I valori nella prova di attestazione provengono da diverse fonti:

  • Emittente:l'emittente fornisce vari valori e i più comuni vengono inseriti nel formato dei metadati dell'emittente per consentire il filtraggio durante la presentazione.
  • Titolare:valori come il nome del pacchetto e la firma provengono dal titolare. Questi non vengono condivisi tramite le procedure di emissione standard e devono essere ottenuti in modo indipendente dal titolare.
  • Protocollo: valori come il nonce con attestationChallenge provengono dal protocollo.

Per istruzioni più complete sulla convalida dei dati di attestazione, consulta le seguenti risorse:

Formato della prova di attestazione

In una richiesta di credenziali, la prova android_keystore_attestation è inclusa nel seguente esempio:

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

Viene quindi memorizzato nell'oggetto proofs di una richiesta di credenziali.

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

Formato dei metadati dell'emittente

Un emittente indica i tipi di prova che supporta includendo l'oggetto android_keystore_attestation all'interno dell'oggetto proof_types_supported per una determinata configurazione delle credenziali.

Questo è un esempio dell'oggetto android_keystore_attestation per gli emittenti:

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

Questo è un esempio dell'oggetto proof_types_supported esterno:

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

Mappatura delle attestazioni VCI su Android Keystore

Questa tabella fornisce una mappatura informativa per aiutare le entità che conoscono il tipo di prova di attestazione standard OpenID4VCI a capire dove si trovano concetti simili all'interno dell'attestazione Android Keystore.

Rivendicazione di attestazione VCI

Posizione di android_keystore_attestation

Posizione del valore atteso

iss

Chiave pubblica del certificato radice dell'archivio chiavi

N/D

iat

Valore creationDateTime nell'estensione dell'attestazione

N/D

exp

Campo validUntil nel certificato end-entity

N/D

attested_keys

Chiave pubblica contenuta nel certificato foglia di ogni catena

N/D

key_storage

Valore keyMintSecurityLevel nell'estensione dell'attestazione

Emittente selezionata: campo key_mint_security_level nei metadati dell'emittente

user_authentication

Valori userAuthType e noAuthRequired nell'estensione di attestazione

Emittente selezionata: campo user_auth_types nei metadati dell'emittente

nonce

Valore attestationChallenge nell'estensione dell'attestazione

Dal protocollo: valore c_nonce dell'endpoint nonce descritto in VCI

certificazione

N/D

N/D

status

N/D

N/D