Implementa la certificación respaldada por hardware para las credenciales digitales

En un flujo típico de emisión de credenciales digitales que usa la especificación OpenID for Verifiable Credential Issuance (OpenID4VCI), una entidad emisora debe saber que la clave dentro de la credencial que se firmará se almacena en una ubicación segura. El tipo de prueba android_keystore_attestation, un formato para usar con OpenID4VCI, proporciona un informe firmado por hardware desde Android Keystore, lo que garantiza que la clave esté bloqueada en un entorno de ejecución confiable (TEE) o StrongBox y que no se pueda exportar ni clonar.

Descripción general de la certificación de hardware

Cuando se genera una clave en Android Keystore, el sistema puede generar un certificado de certificación. Este certificado está firmado por una clave protegida por el hardware del dispositivo, que se vincula a una raíz de confianza que posee Google.

La prueba android_keystore_attestation es un array de cadenas de certificados X.509. Cada cadena representa una sola clave de autenticación y está estructurada por un certificado de hoja seguido de certificados intermedios.

  • Certificado de hoja: Contiene la clave y una extensión de certificación específica de Android.
  • Certificados intermedios: Conectan la hoja a la raíz de Android.

Pasos para la verificación

Las entidades emisoras deben realizar varias validaciones en la certificación.

  • Busca el certificado en la cadena que contiene la extensión de certificación de Android (por lo general, el certificado de hoja). Este certificado contiene los datos de certificación de la clave acuñada por Android Keystore.
  • Verifica que el campo attestationChallenge de la extensión coincida con el c_nonce que proporciona el protocolo para evitar ataques de reproducción.
  • Verifica el valor de todas las aserciones en las extensiones que te interesan.
  • Realiza una verificación de revocación en los certificados de Android Keystore.

Los valores de la prueba de certificación provienen de varias fuentes:

  • Entidad emisora: La entidad emisora proporciona varios valores, y los más comunes se colocan en el formato de metadatos de la entidad emisora para permitir el filtrado en la presentación.
  • Titular: Los valores, como el nombre del paquete y la firma, provienen del titular. Estos no se comparten a través de los procedimientos de emisión estándar y deben obtenerse de forma independiente del titular.
  • Protocolo: Los valores, como el nonce con attestationChallenge, provienen del protocolo.

Para obtener instrucciones más completas sobre la validación de los datos de certificación, consulta los siguientes recursos:

Formato de prueba de certificación

En una solicitud de credenciales, la prueba android_keystore_attestation se incluye en el siguiente ejemplo:

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

Luego, se almacena en el objeto proofs de una solicitud de credenciales.

{
  "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 de metadatos de la entidad emisora

Una entidad emisora indica los tipos de prueba que admite incluyendo el objeto android_keystore_attestation dentro del objeto proof_types_supported para una configuración de credenciales determinada.

Este es un ejemplo del objeto android_keystore_attestation para entidades emisoras:

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

Este es un ejemplo del objeto proof_types_supported externo:

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

Cómo asignar reclamos de certificación de VCI a Android Keystore

En esta tabla, se proporciona una asignación informativa para ayudar a las entidades familiarizadas con el tipo de prueba de certificación OpenID4VCI estándar a comprender dónde se ubican conceptos similares dentro de la certificación de Android Keystore.

Reclamo de certificación de VCI

Ubicación de android_keystore_attestation

Ubicación del valor esperado

iss

Clave pública del certificado raíz de Keystore

N/A

iat

Valor creationDateTime en la extensión de certificación

N/A

exp

Campo validUntil en el certificado de hoja

N/A

attested_keys

Clave pública contenida en el certificado de hoja de cada cadena

N/A

key_storage

Valor keyMintSecurityLevel en la extensión de certificación

Entidad emisora seleccionada: campo key_mint_security_level en los metadatos de la entidad emisora

user_authentication

Valores userAuthType y noAuthRequired en la extensión de certificación

Entidad emisora seleccionada: campo user_auth_types en los metadatos de la entidad emisora

nonce

Valor attestationChallenge en la extensión de certificación

Desde el protocolo: valor c_nonce del extremo nonce que se describe en VCI

certification

N/A

N/A

status

N/A

N/A