PowerAuth Integration

This page explains how the keystore authorizes a wallet request with the user’s PowerAuth activation, and why it relies on device signatures rather than PowerAuth codes. The PowerAuth activation id is also the keystore’s unitId.

Request Checks

Before any HSM operation on a user request, the keystore runs these checks in order:

  1. Envelope decryption. The keystore asks PowerAuth Server for the decryption key of the temporary key named in the request, and decrypts the body. This proves that the request was encrypted for this activation and keeps it confidential. It does not prove who the user is.
  2. Unit check. The unit must exist (400 unit_not_found) and must not be revoked (409 unit_revoked).
  3. Signed-request validation. The keystore verifies the signed request inside the envelope: every device signature against the device public keys stored for the unit, then aud, sub, the iat window and the single-use jti. This is the user’s authorization.
  4. Activation status. PowerAuth Server confirms that the activation is ACTIVE, and the request matches stored device public key(s).
  5. HSM operation. Only then does the keystore call the HSM through PKCS#11. To create a key, the HSM generates a key pair, wraps the private key under the wrap key of its domain and seals the result under the bind key. To sign, the HSM opens the seal, unwraps the key, signs and destroys the key. The HSM keeps no per-user keys. See HSM Setup.

Request flow

The diagram shows the target design of the user endpoints. Implemented so far: the software wrapped-key format and the SoftHSM2 provisioning scripts. Not yet implemented: the runtime HSM operations (PKCS#11 wrapping, sealing and signing), the REST endpoints and the PowerAuth Server calls.

Role of the Wallet Integration Server

  • Registers the activation as a unit during the activation, before the commit (POST /v1/pa/units), and revokes the unit when the activation is removed.
  • Serves the PowerAuth vault unlock.
  • Forwards every user request of the wallet unchanged. It cannot read the encrypted bodies and cannot sign with a user’s keys, because the keystore itself verifies the device signatures.

REST API Overview

Action Endpoint (POST /v1/…) Caller authentication Encrypted Key purpose
Register a unit and create its user-signing keys pa/units Backend token no USER_SIGNING
Revoke a unit pa/units/{unitId}/revocation Backend token no –
Sign with the user-signing keys pa/units/{unitId}/signatures Device signature yes USER_SIGNING
Create the WIA key eudi/units/{unitId}/wallet-instance-keys Device signature yes WALLET_INSTANCE
Issue a WIA and sign proof-of-possession (PoP) JWTs eudi/units/{unitId}/wallet-instance-attestations Device signature yes WALLET_INSTANCE
Create credential keys with a key attestation (KA) and an optional proof JWT eudi/units/{unitId}/credential-keys Device signature yes CREDENTIAL
Sign key-binding JWTs (KB-JWT) eudi/units/{unitId}/key-binding-signatures Device signature yes CREDENTIAL
  • Device signature: the user unlocks the PowerAuth vault with PIN or biometry, and PowerAuth Server verifies it. The vault then releases the device private keys, which sign the request (both keys for a hybrid activation). The keystore verifies these signatures. No PowerAuth code reaches the keystore.
  • Backend token: a call of the Wallet Integration Server authenticated as a backend caller: a bearer token now, mutual TLS later.
  • Encrypted: the request and response bodies are encrypted end to end between the wallet and the keystore. Every call from the wallet is encrypted; backend calls are not.

Why Device Signatures Rather Than PowerAuth Codes

PowerAuth codes are symmetric: PowerAuth Server knows the same secrets and could compute a valid code itself. Certifying that the user has sole control of the keys, as required for a WSCA/WSCD or for eIDAS level of assurance high, needs evidence that only the user’s device can produce. The PowerAuth code therefore only unlocks the vault, and the keystore accepts only signatures made with the device private keys.

Last updated on Nov 11, 2026 (21:37) Edit on Github Send Feedback

develop

Secure Keystore