Skip to main content

Security

The security of your users' data and digital assets is our top priority at Privy. We recognize our role as a critical dependency for our customers' apps and greatly appreciate the responsibility that comes with that.

Privy's internal architecture and infrastructure has gone through several rounds of security reviews, audits, and pentesting, which you can read more about here. We treat security as a constantly-moving target, and undergo these reviews and audits on a regular basis to surface and address new issues.

Implementing, maintaining, and testing security in your app is a huge undertaking. We've taken careful effort to use the best practices for securing your users' data and digital assets.

Below, you can read more about some of these practices:

App Authentication

Methods

Privy supports multiple methods for authenticating your end-users and verifying their identity. Today, this includes:

We do not support regular password-based verification given users' tendencies to use and reuse easy-to-guess passwords, and the high incidence of password database breaches.

Tokens

Once a user verifies their identity through one of the methods listed above, Privy issues the user an access token and a refresh token to store the user's authenticated session in your app.

Access Token

The access token is a JSON Web Token (JWT) signed by a Privy Ed25519 key specific to your app. This signature ensures that this token could have only been produced by Privy, and cannot be spoofed. In your frontend, Privy uses this access token to determine whether the user is authenticated or not. Your backend should use the access token on incoming requests to determine if the request originated from an authenticated user.

The access token has a lifetime of one hour, to ensure that authenticated sessions can be easily revoked and to restrict the window of vulnerability in the unlikely case that the access token is exposed outside of your app.

Refresh Token

The refresh token is used to refresh the user's session once their access token has expired. It has a lifetime of 30 days, to ensure that users don't have to frequently login again, but can only be used once. This ensures that the refresh token can only be used to refresh an existing session, and never to create an entirely new session.

If the Privy SDK detects that the access token or refresh token has been tampered with, it will immediately log the user out and will destroy the corresponding session in Privy's backend.

User Data Management

Encryption and Backups

All of Privy's databases are encrypted at rest. Privy takes full database snapshots daily and uploads transaction logs for database instances to backup storage every 5 minutes. These snapshots are stored for 7 days, meaning Privy can safely restore databases to any point in the last week (with 5 minute granularity) as needed.

TLS Encryption and Traffic Management

All traffic is encrypted with a minimum supported TLS version of 1.2 and HSTS. All traffic to the Privy console (https://console.privy.io), the Privy API (https://auth.privy.io), and related subdomains is routed through Cloudflare. All of Privy's servers run within private VPCs on AWS.

API Authentication

All requests to Privy's API to query or update user data must be authenticated by the app's API secret. This secret is never stored in a Privy database and cannot be recovered after it has been generated by the app developer.

Embedded Wallets

tip

Privy embedded wallets are hardware-secured, fully self-custodial, and easy to integrate in only a few lines of code. Neither Privy nor integrating applications ever have access to embedded wallet private keys.

Architecture and Custody

Privy's embedded wallets have three core components:

  • the Privy API, which stores wallet metadata for a given user, such as their wallet address
  • the isolated iframe, which manages the user's private key and handles wallet operations
  • the Privy SDK, which exposes a high-level interface for apps to interact with the embedded wallet.
Embedded wallets.

Architecture of the Embedded Wallet

By design, the embedded wallet's private key is only ever stored in-memory within the isolated iframe. The private key is never saved to any database and does not persist past the iframe's lifetime.

The iframe runs on an entirely separate domain from your app. Since modern browsers partition storage across domains, this design ensures that neither your app's code nor the Privy SDK can access the raw private key. Put simply, embedded wallets are strictly non-custodial, for both your app and Privy.

Key Management

Creating and splitting the private key

When a user creates an embedded wallet, the isolated iframe securely generates a public-private keypair for the user by choosing 128 bits of entropy at random using a CSPRNG, and converting the bits to a mnemonic via BIP-39. From this mnemonic, the iframe then derives the wallet's public key (and by extension, the wallet addres) and private key.

The iframe then splits the private key into three shares using Shamir's Secret Sharing:

  1. Device share, which is persisted on the user's device.
    • In a browser environment, this is stored in the iframe's local storage.
    • In a mobile environment, this is first encrypted by the device's secure enclave, and the encrypted share is then persisted to the device's keychain. This share is only decrypted as necessary.
  2. Auth share, which is encrypted and stored by Privy. The Privy SDK will retrieve this share for a user when they login to your app.
  3. Recovery share, which is encrypted either by user-provided entropy (a strong password) or by Privy.
    • If encrypted by user-provided entropy, only the user can decrypt the recovery share. Privy never sees this share or the user's password.
    • If encrypted by Privy, Privy uses a secure encryption key stored in a hardware security module (HSM). The HSM will only decrypt this share if the decryption request includes the user's access token. Note that in the case you do not require a passcode from your users, you are trusting Privy's use of HSMs. We therefore recommend you prompt users to set a recovery passcode upfront.

The full private key is only ever assembled in-memory, and is never persisted anywhere. At least two of three shares must be present to constitute the full private key.

info

Threat models, like UX, are not one-size-fits-all. Depending on your application, the users you serve and the digital assets they interact with, your requirements for threat models and UX will vary. In kind, Privy offers multiple secure recovery options across the spectrum of threat models, to allow you to choose what's right for your app.

These tradeoffs will improve over time and we are actively building out support for further options, including passkeys or storing the encrypted recovery share in a user's cloud account or password manager.

Using the private key

When the embedded wallet needs to use the private key to produce a signature, the Privy SDK will pass the message for the signature to the isolated iframe. The iframe will then reconstitute the private key in-memory, using the device share and the auth share, to compute the signature using ECDSA. The iframe then passes the signature back to the Privy SDK and flushes the assembled private key from memory.

Using the private key on a new device

When a user accesses your app on a new device, the iframe will retrieve the auth share for your user during the login process. Then, depending on how you've configured recovery, the iframe will request the decrypted recovery share for your user by:

  • prompting the user to enter their passcode, if using user-entropy for recovery
  • requesting the private key's HSM using the user's auth token, if using automatic recovery

With the auth share and the recovery share, the iframe is then able to compute a new device share for the new device. This device share allows your user to continue using the wallet on that device, without needing to repeatedly recover it.

Wallet recovery

With Privy's architecture, a user is able to recover their private key even if they lose their device or if they lose access to your app. This even works if Privy is offline.

  • If the user loses access to their device and is unable to retrieve their device share, they can combine their auth share and decrypt their recovery share to reconstitute the full private key.
  • If the user loses access to your app and is unable to retrieve their auth share, they can combine their device share and decrypt their recovery share to reconstitute the full private key.

In all of these cases, Privy rotates keys to ensure compromised devices or authentication methods cannot be combined to maliciously reconstitute the private key.

Third-Party Reviews

Privy's internal infrastructure has undergone multiple rounds of audits by third-party testers and developers, as well as a round of pentesting. Security is a constantly moving target and no system is secure in perpetuity. We regularly undergo audits to surface and address new issues.

All of Privy’s cryptographic libraries (notably around Shamir Secret Sharing) are open-sourced and have undergone external audits. You can check out these results here.

We will be setting up a bug bounty program in the near future. For more information, please get in touch with our team at [email protected].