Skip to content

Issuance of Wallet Instance Attestation (WIA)

This flow describes the process of issuing a wallet attestation (WIA) as introduced here in the blueprint.

Design Decisions

In the WIA issuance process, the WI uses the established one-factor authentication from the registration process to request a fresh issuance of Wallet Instance Attestations (WIAs).

The process uses app attestations of Platform Attestation Provider (PAP) for every issuance to get assurance about the integrity of the mobile app and its device. Additionally, the Wallet Instance generates a hardware-bound key pair on the mobile device and transmits the public key to the Wallet Backend. This key acts as a possession factor for one-factor authentication. The key generation must utilize the most secure key store available on the mobile device, such as a Secure Element, StrongBox, SecureEnclave or TEE. A proof of possession for the private key is done by signing the challenge.

The Wallet Provider Backend (WB) analyses the provided app attestation and does additional checks on vulnerability management and user-initiated revocation before issuing and returning a batch of one-time WIAs. The WB issues the WIA as a JWT as defined in attestation-based client authentication, using x509 certificate as trust mechanism to sign the WIA. The WI provides multiple keys and proof of possessions and the WB issues multiple corresponding WIAs, such that they can be used in a one-time use by the WI (which prevents linkability).

We decided to use stateless challenges instead of stateful challenges stored in the backend, as binding using wi_wia_pop for the app attestation challenge is sufficiently secure to protect against replay attacks.

ToDo

  • integrate mobile device vulnerability management
  • add Android key attestations for wi_wia_prvk[]
  • add rate limiting/replay attack detection based on wb_auth_challenge and wb_wi_id

Data Flow

This section described the data flow of the Wallet Registration in a sequence diagram and a more detailed table. Artifacts in italics are further explained in the data register of the decomposition chapter.

Sequence Diagram

Issuance of Wallet Instance Attestation (WIA)Issuance of Wallet Instance Attestation (WIA)Wallet Backend .WB.Wallet Instance . App .WI.Platform Attestation Provider .PAP.Wallet Backend (WB)Wallet Backend (WB)Wallet Instance / App (WI)Wallet Instance / App (WI)Platform Attestation Provider (PAP)Platform Attestation Provider (PAP)(001)[TLS] HTTP POST</challengeEndpoint>(002)generate wb_auth_challenge:sign(nonce, timestamp)wb_mac_symk(003)[TLS] HTTP 200<wb_auth_challenge>(004)generate wi_wb_auth_pop:sign(wb_auth_challenge)wi_wb_auth_prvk(005)generate (wi_wia_prvk[],wi_wia_pubk[])(006)generate (wi_wia_pop[]):sign(wb_auth_challenge, andwi_wia_pubk)wi_wia_prvk(007)generate wi_app_attest_challenge:hash(wb_wi_id + wi_wb_auth_pop +wi_wia_pop[])(008)request app attestation usingwi_app_attest_challenge(009)generate and return pap_app_attest(010)[TLS] HTTP POST </wiaEndpoint>wb_wi_id, wi_wb_auth_pop,wi_wia_pop[], pap_app_attest(011)verify wb_auth_challenge fromwi_wb_auth_pop and wi_wia_pop[]using wb_mac_symk(012)generate wi_app_attest_challenge:hash(wb_wi_id + wi_wb_auth_pop +wi_wia_pop[])(013)verify pap_app_attest usingGoogle/Apple keys andwi_app_attest_challenge(014)lookup wi_wb_auth_pubk from thedatabase using wb_wi_id(015)verify wi_wb_auth_pop usingwi_wb_auth_pubk(016)verify wi_wia_pop[] using includedwi_wia_pubk(017)check if the wallet instance is revokedfor any reasons, e.g. user-initiated orvulnerability management(018)generate wb_wia[]:(wi_wia_pubk[])wb_wia_auth_prvk(019)[TLS] HTTP 200 wb_wia[]

Detailed Description

No Description
001 The WI requests the WB to generate a challenge (wb_auth_challenge). The request is unauthenticated and state-less.
002 The WB generates a structure containing a random nonce and and a timestamp of the current time and MACs it using a symmetric key (wb_mac_symk) as a JSON Web Token (JWT). The resulting structure is called the challenge (wb_auth_challenge). The MAC and nonce must have sufficient security, information on algorithms and key lengths can be found in the cryptography chapter.
003 The WB responds with the challenge (wb_auth_challenge) to the WI. The WI uses the challenge as a transparent string and not evaluate the JWT claims.
004 The WI computes a proof of possession of its wi_wb_auth_prvk by signing the wb_auth_challenge using ECDSA and encoding it as a JSON Web Token (JWT). The resulting structure is called wi_wb_auth_pop.
005 The WI generates a list of one or more new hardware-bound key pairs (wi_wia_prvk[] and wi_wia_pubk[]) which is used as the client attestation key for the wallet attestation (WIA). The WI must leverage the most secure, local key storage available, i.e. a Secure Element, StrongBox, SecureEnclave or TEE. The key must have sufficient security, information on algorithms and key lengths can be found in the cryptography chapter.
006 The WI computes a list of one or more proof of possessions of its wi_wia_prvk[] by signing the wb_auth_challenge using ECDSA and encoding it as a JSON Web Token (JWT). The resulting structure is called wi_wia_pop.
007 The WI computes a hash from its account identifier wb_wi_id, the wi_wb_auth_pop and the wi_wia_pop[] using SHA-256 to generate a challenge wi_app_attest_challenge for the app attestation. This step is necessary as the DeviceCheck AppAttest on iOS has a limited input size.
008 The WI utilizes platform mechanism from the the user device (UD) and the Platform Attestation Provider (PAP) to generate the app attestation pap_app_attest using the wi_app_attest_challenge. By providing the hash of the account identifier and the proof of possessions, the app attestation is bound to this particular WIA request and thus it is ensured that pap_app_attest and resulting WIAs belong to the same device, that was asserted during app attestation. The detailed contents and format for the request are described in the app attestation guideline. The WI must enforce it's own rate-limiting to avoid excessive amount of requests to the Platform Attestation Provider (PAP).
009 The PAP returns the app attestation pap_app_attest to the WI. The detailed contents and format of the Android Play Integrity verdict token and iOS AppAttest result are described in the app attestation guideline. If the app attestation fails, the WI must abort the WIA issuance and display an error to the user.
010 The WI requests the WB to issue a WIA, it sends its account identifier wb_wi_id, the wi_wb_auth_pop, the wi_wia_pop[] and the app attestation (pap_app_attest). The request is authenticated.
011 The WB verifies the self-contained wb_auth_challenge contained in using its symmetric key (wb_mac_symk) and validating that the timestamp is within a valid time interval of 0 minute to +5 minutes.
012 The WB re-computes the hash wi_app_attest_challenge from the transmitted wb_wi_id, the wi_wb_auth_pop and the wi_wia_pop[], just like the WI for the app attestation in Step 007.
013 The WB verifies the received app attestation pap_app_attest using platform-specific mechanism and keys. The detailed verification process and how to fetch the public keys is described in the app attestation guideline.
014 The WB fetches the public key for the possession factor wi_wb_auth_pubk from the database using the provided account identifier wb_wi_id.
015 The WB verifies the received proof of possession of the WI authentication key (wi_wb_auth_pop) using the included wi_wb_auth_pubk with ECDSA and the signed challenge (wb_auth_challenge).
016 The WB verifies the received proof of possessions of the WIA keys (wi_wia_prvk[]) using the included wi_wia_pubk[] with ECDSA and the signed challenge (wb_auth_challenge).
017 The WB does additional checks on the WI and its user account, including:
  • information from the vulnerability management
  • user-initiated revocation
This may result in the WIA issuance being aborted.
018 The WB generates a Wallet Instance Attestation wb_wia for each public key provided by the WI in wi_wia_pubk[] and signs them with its wb_wia_auth_prvk that is associated on a trust list.
019 The WB returns the list of Wallet Instance Attestations wb_wia[] to the WI.

Wallet Challenge JWT

Defined in Wallet Registration

Proof of Possession JWT for Authentication

The wi_wb_auth_pop is a possession-based authentication factor of the Wallet App, that creates a proof of the wi_wb_auth_prvk over the wb_auth_challenge.

The wi_wb_auth_pop contains: - JOSE Header typ as recommended by JWT BCP - JOSE Header alg indicating ECDSA NIST P-256 - JWT Claim wb_auth_challenge containing the serialized wb_auth_challenge - JWT Claim aud referencing the URL of the Wallet Provider Backend

Note: There is no jti parameter for potential enhanced replay protection, as we can reuse the wb_auth_challenge for this purpose. There is also no iat or exp parameter, because the wb_auth_challenge already includes a trusted timestamp. There is also no iat or exp parameter, which is added by the WI, because the wb_auth_challenge already includes a trusted timestamp.

Below is a non-normative example of a wi_wb_auth_pop:

Protected headers:

{
  "typ": "wi-wb-auth-pop+jwt",
  "alg": "ES256"
}
Payload:
{
  "wb_auth_challenge": "eyJ0eXAiOiJ3Yi1hdXRoLWNoYWxsZW5nZStqd3QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzgzMTQ4NzQsIm5vbmNlIjoiZmEwYTMxMGUtOTFkMi00NjFjLWJhMDAtY2MzNWE5OTVmMTY2IiwiaWF0IjoxNzM4MzExMjc0fQ.7QpBVKvwuukioYhLX402ay-DwTv5H3x-hhovev72i58",
  "aud": "https://wallet-provider-backend.eudi-wallet.de"
}

Signed by wi_wb_auth_prvk

Wallet Instance Attestation (WIA)

The wb_wia is a signed attestation of the Wallet Provider backend, attesting to the validity of the Wallet Instance towards Issuers and Relying Parties. The format is described in Section 5.1 of attestation-based client authentication.

In accordance to the rules defined in the draft, the wb_wia contains: - JOSE Header typ as recommended by JWT BCP - JOSE Header alg indicating ECDSA NIST P-256 - JOSE Header x5c containing the x509 certificate chain of the Wallet Provider - JWT Claim iss: referencing the URL of the Wallet Provider Backend - JWT Claim sub: referencing the client_id of the Wallet Provider Backend - JWT Claim cnf: containing the serialized wi_wia_pubk - JWT Claim iat: current time, indicating the issuance date of the WIA - JWT Claim exp: current time + expiration time interval, indicating the expiration data of the WIA

Below is a non-normative example of a wb_wia:

Protected headers:

{
  "typ": "oauth-client-attestation+jwt",
  "alg": "ES256",
  "x5c": [
    "MIIBETCBuQIJAM6k5TM9MgHEMAkGByqGSM49BAEwEjEQMA4GA1UEAwwHdGVzdC5kZTAeFw0yNDExMTExMjMwMTRaFw0yNTExMTExMjMwMTRaMBIxEDAOBgNVBAMMB3Rlc3QuZGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATQivHxcyv56XIfjt6EeyekabQ44oXSvplQXwE42c5SKheiZyhKfjhATMdpNQKV+2WnNX28Dwlv/mBQkA2pPe98MAkGByqGSM49BAEDSAAwRQIgcn7PP74vJ82nUxVQA4nt++IzWK+xYX2jGe9oh/5R9CICIQCsCjry+BL5biHKY6Pp8hUSsGqpMCV2uza/lhq4C4RoWg=="
  ]
}
Payload:
{
  "iss": "https://wallet-provider-backend.eudi-wallet.de",
  "sub": "de.bmi.eudi-wallet.wallet-provider-backend",
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "32jtyqhBGxKxqeihaRsmW449oB9hcMUSgNCxDjHfADo",
      "y": "3ARvwMghvfz7zAcGEdwQj2h5DQU64BezdaSthn7qJzk"
    }
  },
  "iat": 1750742508,
  "exp": 1750828908
}

Signed by wb_wia_auth_prvk

Proof of Possession JWT for Wallet Instance Attestation (WIA)

The wi_wia_pop is a proof of possession signed by the Wallet Instance, attesting to the possession and usage of the WIA towards Issuers. The format is described in Section 5.2 of attestation-based client authentication.

In accordance to the rules defined in the draft, the wi_wia_pop contains: - JOSE Header typ as recommended by JWT BCP - JOSE Header alg indicating ECDSA NIST P-256 - JOSE Header jwk containing the serialized wi_wia_pubk - JWT Claim wb_auth_challenge containing the serialized wb_auth_challenge - JWT Claim jti containing a UUID - JWT Claim aud referencing the URL of the Wallet Provider Backend

Note: The Wallet Backend is using the challenge for replay protection instead of jti, but the draft of attestation-based client authentication requires jti to be present in any case.

Below is a non-normative example of a wi_wia_pop:

Protected headers:

{
  "typ": "oauth-client-attestation-pop+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "32jtyqhBGxKxqeihaRsmW449oB9hcMUSgNCxDjHfADo",
    "y": "3ARvwMghvfz7zAcGEdwQj2h5DQU64BezdaSthn7qJzk"
  }
}
Payload:
{
  "wb_auth_challenge": "eyJ0eXAiOiJ3Yi1hdXRoLWNoYWxsZW5nZStqd3QiLCJhbGciOiJIUzI1NiJ9.eyJub25jZSI6IjhjM2YyODM4LTU1Y2QtNGE0MC1iOTg5LWEzMzYyNDhkOGNlOCIsImlhdCI6MTc1MDc0MjUwOH0.VD0P5y2EZbut0_JxCd_nwo0RNDZhndzO7M2xWzZ7xyA",
  "jti": "d25d00ab-552b-46fc-ae19-98f440f25064",
  "aud": "https://wallet-provider-backend.eudi-wallet.de"
}

Signed by wi_wia_pop_prvk