Skip to content

Remote WSCA Registration

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

Design Decisions

In the Remote WSCA Registration process, the Wallet Instance (WI) establishes a two-factor authentication based on a hardware-bound key pair and a PIN. The Remote WSCA responds with a Remote WSCA account identifier and stores it alongside the corresponding public keys in its database.

The Wallet Instance begins the Remote WSCA Registration by requesting a challenge from the Remote WSCA, this challenge protects the process against replay attacks. The Wallet Instance generates a hardware-bound key pair on the mobile device and transmits the public key to the Remote WSCA. This key acts as a possession factor for two-factor authentication.

For the second authentication factor, the Wallet Instance asks the user for an initial RWSCA-PIN. As the PIN management on most mobile devices is not able to achieve LoA high, the RWSCA-PIN and its retry counter are managed on the Remote WSCA. As the Remote WSCA must not know the RWSCA-PIN itself, a cryptographic key is derived from the PIN. Neither the RWSCA-PIN nor the PIN-derived key are stored persistently on the Wallet Instance. More details can be found in the document Cryptography

The Remote WSCA 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.

Data Flow

This section describes the data flow of the Remote WSCA Registration in a sequence diagram and a more detailed table. Artifacts in italics are further explained in the data register chapter

Sequence Diagram

Remote WSCA - Account RegistrationRemote WSCA - Account RegistrationUserWallet Instance .App.Remote WSCAWSCA account databaseUserUserWallet Instance (App)Wallet Instance (App)Remote WSCARemote WSCAWSCA account databaseWSCA account database(001)[TLS] </rwscaChallengeEndpoint>()(002)generate rwsca_auth_challenge:sign(nonce, timestamp)rwsca_mac_symk(003)[TLS] <rwsca_auth_challenge>(004)request new Wallet-PIN(005)user_rwsca_pin(006)generate secure randomwi_rwsca_pin_salt(007)generate wi_rwsca_pin_prvk andwi_rwsca_pin_pubk usingKDF(user_rwsca_pin +wi_rwsca_pin_salt)(008)generate wi_rwsca_register_pop:sign(rwsca_auth_challenge,wi_rwsca_pin_pubk)wi_mdvm_auth_prvk,wi_rwsca_pin_prvkre-use MDVM key(009)[TLS] </rwscaRegistrationEndpoint>(wi_rwsca_register_pop, mdvm_token)(010)verify rwsca_auth_challenge fromwi_rwsca_register_pop usingrwsca_mac_symk(011)verify mdvm_token withmdvm_attestation_pubk to ensuredevice authenticity and integrity(012)match wi_mdvm_auth_pubkcontained in wi_rwsca_register_popand mdvm_token(013)verify wi_rwsca_register_pop usingincluded wi_mdvm_auth_pubk(014)verify wi_rwsca_register_pop usingincluded wi_rwsca_pin_pubk(015)generate unique rwsca_account_idand create account withrwsca_account_id,wi_mdvm_auth_pubk,wi_rwsca_pin_pubk,rwsca_pin_retry_counter(016)[TLS] rwsca_account_id(017)store rwsca_account_id

Detailed Description

No Description
001 - 003 The WI requests a challenge from the RWSCA challenge endpoint using an HTTP POST request, the request is unauthenticated. The RWSCA generates a JSON structure containing a random nonce and a timestamp of the current time and MACs it using a symmetric key (rwsca_mac_symk) as a JSON Web Token (JWT), the resulting structure is the rwsca_auth_challenge. The RWSCA responds to the WI with the rwsca_auth_challenge in the HTTP payload. The WI uses the challenge as a transparent string and does not evaluate the JWT claims. The RWSCA does not store the challenge after creation, thus the operation is stateless.
004 - 005 The WI requests a RWSCA-PIN (user_rwsca_pin) from the user. The WI validates that the entered user_rwsca_pin matches the PIN security requirements. In particular, it matches the PIN input against a denylist of trivial, repetitive patterns.
006 The WI generates a cryptographic, random salt (wi_rwsca_pin_salt), that will be used for the key derivation of the RWSCA-PIN. The salt expands the low-entropy Wallet PIN into a high-entropy cryptographic key. The salt must have sufficiently secure randomness and at least 128 bits of length. The salt is stored encrypted for the long-term, as it is required to regenerate the knowledge authentication factor together with the PIN.
007 The WI derives the cryptographic key pair (wi_rwsca_pin_prvk and wi_rwsca_pin_pubk) which is used as the knowledge factor of the two-factor authentication to the RWSCA for subsequent requests. The WI must use HKDF to derive wi_rwsca_pin_prvk from user_rwsca_pin and wi_rwsca_pin_salt, see PIN derivation. This key pair is never stored in the WI, but must be deleted after its intended usage, see PIN caching for details. The user_rwsca_pin must be deleted from memory as soon as the wi_rwsca_pin_prvk is derived.
008 The WI computes a proof of possession by signing the rwsca_auth_challenge for freshness and to enable replay protection and both public keys wi_mdvm_auth_pubk and wi_rwsca_pin_pubk once with the wi_mdvm_auth_prvk from the MDVM token (the actual possession factor) and once with the wi_rwsca_pin_prvk (the knowledge factor). The payload and both signatures are encoded as a JSON Web Signature (JWS) in JSON Serialization. The resulting structure is called wi_rwsca_register_pop. The proof of possession cross-signs each public key to bind both authentication factors together.
009 The WI requests the RWSCA to perform the registration and sends the proof of possession for the two-factor authentication (wi_rwsca_register_pop) und the MDVM token mdvm_token that was issued during wallet activation. If the mdvm_token is not up-to-date, the WI may fetch a fresh one from the MDVM endpoint using the renewal flow for either Android or iOS. The request is unauthenticated (as RWSCA does not know the WI yet at registration).
010 The RWSCA verifies the self-contained rwsca_auth_challenge using its symmetric key (rwsca_mac_symk) and validating that the timestamp is within a valid time interval of 0 minute to +5 minutes.
011 - 013 The RWSCA verifies the received mdvm_token with mdvm_attestation_pubk for authenticity and integrity and checks that it is still valid. The RWSCA has a trusted, out-of-band mechanism towards the MDVM to fetch the valid mdvm_attestation_pubk. The RWSCA verifies the received proof of possession for the WI's possession factor (wi_rwsca_register_pop) using the included wi_mdvm_auth_pubk from the mdvm_token. Lastly, the RWSCA verifies that the used key wi_mdvm_auth_pubk is the same in wi_rwsca_register_pop and mdvm_token.
014 The RWSCA verifies the knowledge factor of the proof of possession (wi_rwsca_register_pop) by verifying the second signature using the included wi_rwsca_pin_pubk.
015 The RWSCA generates a unique Remote WSCA account identifier rwsca_account_id and stores the combination of rwsca_account_id, wi_mdvm_auth_pubk, wi_rwsca_pin_pubk, and an initial retry counter for the PIN in its database to register the new account.
016 The RWSCA responds with the generated RWSCA account identifier rwsca_account_id to the WI.
017 The WI stores the received RWSCA account identifier rwsca_account_id.

RWSCA Challenge JWT

The rwsca_auth_challenge encapsulates a verifiable challenge, that is generated and verified by the RWSCA. As the producer and consumer is the RWSCA, a MAC key rwsca_mac_symk is used for efficiency.

The rwsca_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 rwsca_auth_challenge:

Header

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

Signed by rwsca_mac_symk

Proof of possession JWS in JSON Serialization

The wi_rwsca_register_pop is a dual-authentication factor of the Wallet App, that creates a proof of the wi_mdvm_auth_prvk and the wi_rwsca_pin_prvk over the rwsca_auth_challenge.

The wi_rwsca_register_pop contains:

  • JOSE Header typ as recommended by JWT BCP
  • JOSE Header alg indicating ECDSA NIST P-256
  • JOSE Header wi_rwsca_pin_pubk containing the serialized wi_rwsca_pin_pubk
  • JWT Claim rwsca_auth_challenge containing the serialized rwsca_auth_challenge
  • JWT Claim aud referencing the URL of the RWSCA

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

Below is a non-normative example of a wi_rwsca_register_pop:

Protected headers:

{
  "typ": "wi-rwsca-register-pop+jose+json",
  "alg": "ES256",
  "wi_rwsca_pin_pubk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "mT3LI0y2LBP1mxbkHQhVrdi633qQEUJCyib1ot62flI",
    "y": "mVNKt_c8BV1vTK20ParZL5uQzDfPo_ZZXa5udKVsGao"
  }
}
Payload:
{
  "rwsca_auth_challenge": "eyJ0eXAiOiJyd3NjZC1hdXRoLWNoYWxsZW5nZStqd3QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MzgzMTQ4NzYsIm5vbmNlIjoiMGRmOGQ2OTMtODUzOS00NGRkLThjMjItMTk1NDYyODZiNjQ4IiwiaWF0IjoxNzM4MzExMjc2fQ.RIcCxQglW04Z8Tw0xH1erUx2Qbbppgv-0P-84Qh3MiE",
  "aud": "https://wallet-provider-backend.eudi-wallet.de"
}

Signed by wi_mdvm_auth_prvk and wi_rwsca_pin_prvk

Complete JWS example:

{
  "payload"    : "SGVsbG8sIHdvcmxkIQ",
  "signatures" : [
    {
      "protected" : "eyJraWQiOiIxIiwiYWxnIjoiUlMyNTYifQ",
      "signature" : "XAwNAgj-Dw5CBeWG4_6LwQyJrQaAGVJmtqkl21QcIxedNV8Ft0he02eU8Ih60jjNe5FbQxrgfA84JA0isb7NkdczEW_kfX9Fknh-tdypyymrPTsP9bhLKUYfQ7nglWgVf1tukFqkAVZOLdfV7ri9we_bqZblM0pD5ysbu6hjhkLbXSSe_ZD0QfKmJFDaIHWBlB2Z0BeqSmyGQTbO6ZpmxXzICz0ANqTsCrJe6TU2CE6i1mDm0arL12VdcqO9JjD7iQkWppfD3kmRCGsSk3jdJpyWUDCYSKlPVaJJElaffwYjIBevCgfMHFO8ALwpUJc_cFcwBsyalo25JzUSzBNaXg"
    },
    {
      "protected" : "eyJraWQiOiIyIiwiYWxnIjoiRVMyNTYifQ",
      "signature" : "ckfVpM4ECSrhDGitxe5smT-z65t3C238JyrHkJw3kiOAunPTRYzHD50wzvNGXG45nUlwl7Ybg8GPlOCNyJeonw"
    }
  ]
}