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
andwb_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¶
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:
|
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:
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=="
]
}
{
"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"
}
}
{
"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