Skip to content

Wallet Registration

This flow describes the wallet registration process as part of the broader wallet activation as introduced here.

Design Decisions

In the wallet registration process, the Wallet Instance (WI) first proves its authenticity and integrity to the Wallet Backend (WB) and then establishes a hardware-bound key pair for subsequent authentication of the Wallet Instance to the Wallet Backend. The Wallet Backend responds with a Wallet Instance identifier and stores it alongside the corresponding public key in its database.

The Wallet Instance begins the wallet registration by requesting a challenge from the Wallet Backend, this challenge is part of the replay attacks protection and ensures the freshness of the request. The Wallet Instance uses app attestations from the mobile platform to prove its authenticity and integrity utilizing this challenge. The Wallet Backend verifies this proof using attestation keys provided by the Platform Attestation Provider (PAP). To limit costs for obtaining app attestations from the PAP, the Wallet Instance enforces rate limits, causing the process to fail if the limit is exceeded.

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 of the Wallet Instance to the Wallet Backend. The key generation must utilize the most secure key store available on the mobile device, such as Secure Element, StrongBox, SecureEnclave or TEE. A proof of possession for the private key is done by signing the challenge.

The Wallet Backend does not need to store any session data or state related to a specific Wallet Instance during the registration process. Instead, the process relies on cryptographically signed ("self-contained") challenges to verify the authenticity of the Wallet Instance.

ToDo

  • integrate mobile device vulnerability management
  • add Android key attestations
  • add rate limiting/replay attack detection based on wb_auth_challenge

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

Wallet RegistrationWallet RegistrationWallet 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_prvk andwi_wb_auth_pubk(005)generate wi_wb_register_pop:sign(wb_auth_challenge andwi_wb_auth_pubk)wi_wb_auth_prvk(006)generate wi_app_attest_challenge:hash(wi_wb_register_pop)(007)request app attestation usingwi_app_attest_challenge(008)generate and return pap_app_attest(009)request registration:[TLS] HTTP POST</registrationEndpoint>wi_wb_register_pop, pap_app_attest(010)generate wi_app_attest_challenge:hash(wi_wb_register_pop)(011)verify pap_app_attest usingGoogle/Apple keys andwi_app_attest_challenge(012)verify wi_wb_register_pop usingincluded wi_wb_auth_pubk andwb_auth_challenge(013)persist new wallet instance recordwith wb_wi_id and wi_wb_auth_pubk(014)registration complete:[TLS] HTTP 200 wb_wi_id(015)store wb_wi_id

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 key and nonce must have sufficient security properties, 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 must use the challenge as a transparent string and not evaluate the JWT claims.
004 The WI generates a new hardware-bound key pair (wi_wb_auth_prvk and wi_wb_auth_pubk) which is used as one-factor authentication to the WB for subsequent requests. The WI must leverage the most secure, local key storage available, i.e. a Secure Element, StrongBox, SecureEnclave or TEE. See cryptography chapter for details on crypto parameters.
005 The WI computes a proof of possession of the newly generated wi_wb_auth_prvk by signing the wb_auth_challenge and encoding it as a JSON Web Token (JWT). The resulting structure is called wi_wb_register_pop.
006 The WI computes a hash from the newly generated 'wi_wb_register_pop' 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. See crypto chapter or App attestation guidelines for more details.
007 The WI utilizes platform mechanism from the user device (UD) to generate the app attestation pap_app_attest using the wi_app_attest_challenge. By providing the hash of the authentication key pair, the app attestation is bound to this particular registration request and thus it is ensured that pap_app_attest and wi_wb_register_pop 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 services.
008 The UD 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 registration and display an error to the user.
009 The WI requests the WB to perform the registration, it sends the one-factor authentication key with the proof of possession (wi_wb_register_pop) and the app attestation (pap_app_attest). The request is unauthenticated (as WB does not know the WI yet at registration) and state-less.
010 The WB computes a hash of the received wi_wb_register_pop using SHA-256 to re-generate the same wi_app_attest_challenge that was used by the WI for the app attestation in Step 006.
011 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.
012 The WB verifies the received proof of possession of the WI authentication key (wi_wb_register_pop) using the included wi_wb_auth_pubk with ECDSA and the signed challenge (wb_auth_challenge). Additionally, the WB verifies the self-contained wb_auth_challenge using its symmetric key (wb_mac_symk) and validating that the timestamp is within a valid time interval of 0 minute to +5 minutes.
013 The WB generates an Wallet Instance identifier wb_wi_id and stores the combination of wb_wi_id and wi_wb_auth_pubk in its database to register the new WI.
014 The WB responds with the generated Wallet Instance identifier wb_wi_id to the WI.
015 The WI stores the received Wallet Instance identifier wb_wi_id.

Wallet Challenge JWT

The wb_auth_challenge encapsulates a verifiable challenge, that is generated and verified by the Wallet Backend. As the producer and consumer is the Wallet Backend, a MAC key wb_mac_symk is used for efficiency reasons to ensure the integrity and authenticity of the challenge.

The wb_auth_challenge contains: - JOSE Header typ: as recommended by JWT BCP - JOSE Header alg: indicating HMAC-SHA256 as MAC algorithm - JWT Claim nonce: containing at least 128 bits of random - JWT Claim iat current time, indicating the issuance date

Below is a non-normative example of a wb_auth_challenge:

Header

{
  "typ": "wb-auth-challenge+jwt",
  "alg": "HS256"
}
Payload
{
  "nonce": "564edacb-ad81-420c-a74e-6cfbaa713d48",
  "iat": 1726214250
}

Signed by wb_mac_symk

Proof of possession JWT

The wi_wb_register_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_register_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_wb_auth_pubk - 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.

Below is a non-normative example of a wi_wb_register_pop:

Protected headers:

{
  "typ": "wi-wb-register-pop+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "W01hRxCicJTneWe2-e9vXFk8GNiQpCf3NcU16xxnNVM",
    "y": "ZKN0Cy6Zzb9hBni7BKKzynK2DibeWgXe2BwXizp0KIQ"
  }
}
Payload:
{
  "wb_auth_challenge": "eyJ0eXAiOiJ3Yi1hdXRoLWNoYWxsZW5nZStqd3QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzgzMTQ4NzQsIm5vbmNlIjoiZmEwYTMxMGUtOTFkMi00NjFjLWJhMDAtY2MzNWE5OTVmMTY2IiwiaWF0IjoxNzM4MzExMjc0fQ.7QpBVKvwuukioYhLX402ay-DwTv5H3x-hhovev72i58",
  "aud": "https://wallet-provider-backend.eudi-wallet.de"
}

Signed by wi_wb_auth_prvk