Pepper service for keyless accounts
AIP-81 - Pepper service for keyless accounts
Section titled “AIP-81 - Pepper service for keyless accounts”Summary
Section titled “Summary”In keyless accounts an end user needs a private blinding factor (pepper) as an input in the privacy-preserving account address derivation: as long as the pepper is not leaked, the link between the account and the provider/dApp owner behind it remains hidden.
This AIP proposes a solution to manange pepper for the end users without actually storing them by deploying a public service (operated by Aptos Labs) that computes the pepper as a verifiable unpredictable function (VUF) of some session data (namely, the ephemeral public key from the end user and the authorization token (the JWT) from the OIDC provider).
This is a fundamental building block keyless accounts infrastructure.
Motivation
Section titled “Motivation”This is a fundamental building block keyless accounts infrastructure.
Impact
Section titled “Impact”DApp/SDK developers need to implement the interaction with pepper service in order to support the keyless flow.
Alternative solutions
Section titled “Alternative solutions”Let dApp end users to manage their own pepper?
Section titled “Let dApp end users to manage their own pepper?”The whole point of using keyless accounts is to save users from memorizing extra secrets, and this breaks the point.
Let dApp service owners to manage the pepper?
Section titled “Let dApp service owners to manage the pepper?”It would make keyless account dApp-dependent: if the dependency dApp dies, all the dependent accounts are not accessible.
Specification
Section titled “Specification”Preliminaries
Section titled “Preliminaries”A few data items involved in the pepper service interaction is briefly explained below. For the full glossaries, see keyless account specification.
A pair of ephemeral private key (ESK) and ephemeral public key (EPK) is generated each time the user logs in to the OIDC provider in order to use a keyless flow-enabled app. A keyless transaction requires an ephemeral signature generated using the ESK.
An EPK expiry date is a timestamp specified for every EPK. If an EPK’s expiry date is past, the EPK is considered expired and cannot be used to sign transactions.
EPK blinder are some random bytes used to blind EPK and its expiry date
when committing them into the nonce field of the sign request sent to the OIDC provider.
(The issued JWT will contained the same nonce.)
Public parameters
Section titled “Public parameters”Nonce derivation
Section titled “Nonce derivation”A function derive_nonce() is required to commit user’s EPK, EPK blinder and the expiry timestamp into a nonce.
The nonce is then sent to the OIDC provider and signed as part of JWT payload.
The same function needs to be implemented as part of the ZK relation, so SNARK-friendly hash function should be preferred.
Verifiable unpredictable function (VUF)
Section titled “Verifiable unpredictable function (VUF)”Roughly speaking, a VUF is a mapping f(x) implicitly determined by a key pair sk, pk such that:,
- for a random input
x, it is hard to predictf(x)without private keysk; - for an output
yclaimed to bef(x), anyone can verify if the claim is true using the public keypk.
These properties make the VUF output a good candidate for the pepper used in the keyless account flow.
Some concrete VUF schemes applicable here:
- BLS VUF (over BLS12-381 G1 group, refered to as
Bls12381G1Blsbelow). - Pinkas VUF.
Below we refer to the VUF scheme being used in pepper calculation as vuf,
the evaluation function as vuf.eval,
and the vuf output entropy as vuf_entropy.
Pepper base hasher
Section titled “Pepper base hasher”A cryptographic hash function H with output bit-length hash_bit_len is needed to hash a VUF output into a bit string,
for further processing.
Constraints on vuf and H
Section titled “Constraints on vuf and H”At instantiation time, vuf_entropy >= hash_bit_len ~= 256 must be ensured in order to get 256-bit pepper,
as required by AIP-61.
Instantiation in reference implementation
Section titled “Instantiation in reference implementation”The reference implementation uses:
- Poseidon hash function over BN254 as the nonce derivation funciton;
- Pinkas VUF as the VUF;
BCSCryptoHashof structPinkasPepperas the pepper bash hasher.
Publish VUF public key
Section titled “Publish VUF public key”The pepper service should publish its VUF public key by opening an endpoint for anyone to fetch its public key.
Here is an example response from the reference implementation.
{ "public_key": "b601ec185c62da8f5c0402d4d4f987b63b06972c11f6f6f9d68464bda32fa502a5eac0adeda29917b6f8fa9bbe0f498209dcdb48d6a066c1f599c0502c5b4c24d4b057c758549e3e8a89ad861a82a789886d69876e6c6341f115c9ecc381eefd" // pinkas vuf public key serialized and hexlified}Pepper request (the input)
Section titled “Pepper request (the input)”The pepper request from user should contain the following data items.
- User ephemeral public key (EPK)
- EPK expiry date
- EPK blinder
- JWT
- UID key (optional, default value:
"sub") - SLIP-0010 derivation path
(optional, default value:
"m/44'/637'/0'/0'/0'")
Here’s an example request in JSON.
{ "epk": "002020fdbac9b10b7587bba7b5bc163bce69e796d71e4ed44c10fcb4488689f7a144", // EPK serialized and hexlified "exp_date_secs": 1710800689, // The EPK expiry date represented in seconds seince unix epoch "epk_blinder": "00000000000000000000000000000000000000000000000000000000000000", // The EPK blinder hexlified "jwt_b64": "xxxx.yyyy.zzzz", "uid_key": "email", "derivation_path": "m/44'/637'/0'/0'/0'"}Pepper request verification
Section titled “Pepper request verification”Following the notation from the JSON example above, the pepper request should be rejected if any of the following checks fails.
epkshould be valid.- Decoding
jwt_b64into JSONsjwt.header,jwt.payload,jwt.sigshould succeed, andjwt.payloadshould contain the following claims.jwt.payload.nonce: a customizable field that keyless account scheme use to put commitment of user’s ephemeral public key.jwt.payload.sub: the user ID issued by the provider (or whatever field specified byuid_keyin the request)jwt.payload.iss: the providerjwt.payload.aud: the client ID of the app issued by the providerjwt.payload.iat: JWT generation time
- Ensure
epkis committed injwt.nonce, i.e.,jwt.nonce == derive_nonce(epk_blinder, exp_date_secs, epk). jwt.payload.issandjwt.headershould identiy a currently active JWT verification key (a.k.a JWK).- Verification of
jwt.sigwithjwt.payloadand the referenced JWK should pass. exp_date_secsshould neither be in the past, nor too far in the future beyondjwt.iatplus a configured duration (default: 10,000,000 secs or ~115.74 days).
Pepper processing
Section titled “Pepper processing”- Let
uid_valbe the user ID fromjwt.payloadindicated byuid_key. - Obtain byte string
pepper_inputas BCS serialization of data items(jwt.payload.iss, uid_key, uid_val, jwt.payload.aud). - Compute
pepper_baseasvuf.eval(vuf_sk, input). - Compute
master_pepperasH(pepper_base). - Optionally:
- derive byte string
derived_pepperfrom(master_pepper, derivation_path)per key derivation scheme SLIP-0010; - derive byte string
id_commitmentfrom(derived_pepper, jwt.payload.aud, uid_key, uid_val)per AIP-61; - obtain an
AnyPublicKeyobjectpkby upcasting(jwt.payload.iss, id_commitment); - obtain byte string
keyless_pk_bytesas BCS serialization ofpk; - compute byte string
auth_keyas SHA3-256 of concatenation ofkeyless_pk_bytesand byte0x02, where0x02represents the account authenticator single key mode; - obtain
initial_account_address := auth_key.
- derive byte string
- Return
derived_pepperand optionallyinitial_account_address.
Below is an example pepper JSON response used in the reference implementation.
{ "pepper": "854bd1eb56dfe35467493723360bb547a3f06c7ffc0c59733191fb05e8743f", // `derived_pepper` hexlified "address": "0x56f36f5c9fd3f07f9ae0704b7980dd2598afebdd1dc952c60775cd9a5c7c0731" // the initial account address}Reference Implementation
Section titled “Reference Implementation”https://github.com/aptos-labs/aptos-core/tree/main/keyless/pepper
Testing (Optional)
Section titled “Testing (Optional)”Testing should be done as part of end-to-end testing of keyless accounts.
Risks and Drawbacks
Section titled “Risks and Drawbacks”The proposed pepper service is centralized, making it a single point of failure in the keyless transaction flow. This can be mitigated by multiple deployments for now, which is easy to maintain due to its stateless nature. In the future, a decentralized pepper service potentially run as part of Aptos validators can fully resolve the issue.
If the VUF private key is lost, all keyless accounts are inaccessible (unless the pepper is locally cached on user end).
If the VUF private key is leaked, the link between a keyless account and the OIDC provider/dApp owner is no longer private. For example, Google now may know which keyless account is derived from the JWT it signed.
Future Potential
Section titled “Future Potential”If the pepper service is instantiated with a weighted VUF (e.g., Pinkas VUF), it has the potential to be decentralized:
- VUF private key needs to be shared between Aptos validators using a thresholded weighted key sharing scheme.
- A pepper request will be broadcasted to all validators and the pepper is obtained by verifying and aggregating enough pepper responses from validators.
Timeline
Section titled “Timeline”Suggested implementation timeline
Section titled “Suggested implementation timeline”2024.01-03
Suggested developer platform support timeline
Section titled “Suggested developer platform support timeline”SDK support are implemented in lock step with pepper service development.
Suggested deployment timeline
Section titled “Suggested deployment timeline”Release 1.10
Security Considerations
Section titled “Security Considerations”See risks and drawbacks.