PassKey

Passkeys provide a significant advantage by freeing users from the need to manually manage and secure private keys. Instead of relying on traditional 12-word seed phrases, users can simply use a passkey-enabled device to manage their wallet. The hardware securely stores the passkey, while the hardware vendor (e.g., Apple/Google) ensures secure backup, providing both convenience and safety.

Additionally, Elytro wallet's default validatorarrow-up-right already supports passkey signature verification, further simplifying the user experience. This integration enables users to authenticate transactions and manage their wallets using passkeys, ensuring a seamless and secure interaction with Elytro wallet.

How passkey works in Elytro wallet

Passkey create process

  1. A passkey is generated from a client-server handshake, with the frontend using the @passwordless-id/webauthnarrow-up-right library to prompt the user to create a passkey.

  2. For WebAuthn and passkeys, the most common format is a 64-byte uncompressed public key, consisting of the X and Y coordinates. However, in Elytro wallet, this public key is converted into a bytes32 format.

    Once a passkey is generated, its public key is used to calculate a unique bytes32 string. This bytes32 string is then set as the passkey public key owner in Elytro wallet. The conversion from the public key to the bytes32 key hash is performed as follows:

    public static publicKeyToKeyhash(publicKey: ECCPoint | RSAPublicKey): string {
        if (typeof publicKey === 'object' && Object.prototype.hasOwnProperty.call(publicKey, 'x') && Object.prototype.hasOwnProperty.call(publicKey, 'y')) {
            // ES256
            const es256Key = publicKey as ECCPoint;
            return WebAuthN.p256PublicKeyToKeyhash(es256Key);
        } else if (typeof publicKey === 'object' && Object.prototype.hasOwnProperty.call(publicKey, 'e') && Object.prototype.hasOwnProperty.call(publicKey, 'n')) {
            // RS256
            const rs256Key = publicKey as RSAPublicKey;
            return WebAuthN.rs256PublicKeyToKeyhash(rs256Key);
        } else {
            throw new Error('invalid publicKey');
        }
    }
  1. In the Elytro wallet smart contract, this passkey will be a parameter in the addOwners function and will be stored as the passkey public key in the Elytro wallet smart contract.

Passkey verification process

For each ERC-4337 transaction, a signed UserOperation is sent to the bundler. Each UserOperation includes a unique UserOperation hash. The passkey is used to sign this UserOperation hash, ensuring that the transaction is authenticated by the rightful owner before being processed by the bundler.

  1. The frontend will prompt the user to sign this UserOperation hash using their passkey.

  1. Once the passkey signature is generated, the frontend will compose the UserOperation signature in the following format.

  1. When this UserOperation is sent to the bundler, the Elytro wallet smart contract will verify the signature using the validatorarrow-up-right logic. Once the verification is successfully passed by the validator, the UserOperation transaction will be considered valid and will proceed. The passkey verification logic is implemented in the code as shown below:

How are Passkeys Managed Across Devices and Restored?

Both Apple and Google offer built-in solutions for passkey synchronization and recovery:

For Apple users, passkeys generated on one device are automatically synced across other devices via iCloud Keychain, as long as the user is signed in with their Apple ID. For more details, please refer to Apple's Passkeys documentationarrow-up-right.

For Google users, passkeys are seamlessly synced across devices using Google Password Manager. For more information, please refer to Google's Passkeys supported environmentsarrow-up-right.

Last updated