Encrypted Identity Data
This guide applies only to the Identity package.
Privy encrypts the my_identity data with the merchant public key. The
merchant backend decrypts it with the matching private key.
Key provisioning
Each Identity-package merchant has a unique RSA key pair. Privy gives the private key one time, at onboarding, with the other merchant credentials.
Store the private key in the merchant backend secret manager. Do not put the private key in a browser or mobile application.
Privy keeps the matching public key and uses it to encrypt identity data.
Encryption format
Privy encrypts only the my_identity section. It sends my_contact_data as
plaintext in the same JWT.
The identity JSON fits in one RSA-4096 block. Privy encrypts it directly with RSA-4096 and PKCS#1 v1.5 padding. The format does not use hybrid or AES encryption.
The JWT data claim has this form:
Code
The decrypted my_identity JSON has this form. All values are fictitious:
Code
identity_card and selfie are download URLs. They are not inline images.
Decrypt with Node.js
Verify the JWT first. Then decrypt data.my_identity on the merchant backend:
Code
The built-in Node.js crypto.privateDecrypt rejects RSA_PKCS1_PADDING for
private decryption after the CVE-2023-46809 fix. This behavior applies to
current Node.js 18.19, 20, and 22 releases. The node-forge example performs
PKCS#1 v1.5 unpadding.
Other languages provide direct equivalents:
- Go:
rsa.DecryptPKCS1v15 - PHP:
openssl_private_decrypt - Python:
PKCS1v15
Verify the JWT signature before decryption. Decrypt identity data only on the merchant backend.
