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 de 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 el almacén de claves de Android, 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 el almacén de claves de Android, el sistema puede generar un certificado de certificación. Este certificado está firmado por una clave protegida por el hardware del dispositivo, que se encadena 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 se estructura con un certificado de hoja seguido de certificados intermedios.

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

Pasos para la verificación

Los emisores 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 generada por el almacén de claves de Android.
  • Verifica que el campo attestationChallenge de la extensión coincida con el c_nonce proporcionado por 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:

  • Emisor: El emisor proporciona varios valores, y los más comunes se colocan en el formato de metadatos del emisor para permitir el filtrado en la presentación.
  • Titular: Los valores, como el nombre del paquete y la firma, provienen del titular. No se comparten a través de 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 cómo validar los datos de certificación, consulta los siguientes recursos:

Formato de la prueba de certificación

En una solicitud de credencial, 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 credencial determinada.

Este es un ejemplo del objeto android_keystore_attestation para emisores:

{
  "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 declaraciones de certificación de VCI a Android Keystore

En esta tabla, se proporciona una asignación informativa para ayudar a las entidades que conocen el tipo de prueba de certificación estándar de OpenID4VCI a comprender dónde se encuentran 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 del almacén de claves

N/A

iat

Valor de 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 incluida en el certificado de hoja de cada cadena

N/A

key_storage

Valor de keyMintSecurityLevel en la extensión de certificación

Emisor seleccionado: Campo key_mint_security_level en los metadatos del emisor

user_authentication

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

Emisor seleccionado: Campo user_auth_types en los metadatos del emisor

nonce

Valor de attestationChallenge en la extensión de certificación

Del protocolo: Valor de c_nonce del extremo de nonce que se describe en la VCI

certificación

N/A

N/A

estado

N/A

N/A