Skip to content

Client-Side Signing and Key Migration

Currently, many decentralized identity approaches delegate signing operations to the PDS, where the private keys are stored and managed. This architecture has several limitations:

  • Reduced client autonomy and control over signing operations
  • Increased security risk as the PDS holds the private keys
  • Limited ability to operate without PDS connectivity
  • Potential privacy concerns as the PDS can track all signature operations
  • Challenges with key portability across different PDS providers

This page outlines methods for performing cryptographic signing operations directly on the client side rather than delegating this responsibility to the Personal Data Server (PDS). It specifies two approaches for managing signing keys on the client: (1) deterministic key generation using RFC6979, and (2) random key generation with import/export capabilities for multi-device usage. By enabling client-side signing, we can enhance security, privacy, and user sovereignty while maintaining a seamless multi-device experience.

A formal specification for client-side signing can be found in the wip-05.

This proposal introduces a shift from PDS-delegated signing to client-side signing where:

  1. Private keys are generated and stored on the client device
  2. Signing operations are performed locally without transmitting private keys
  3. Signed data is then sent to the PDS for distribution in the network
  4. Authentication with the PDS uses a separate mechanism than the main identity signing keys

Method 1: Wallet-Based Deterministic Signing

Section titled “Method 1: Wallet-Based Deterministic Signing”

This method leverages existing wallet infrastructure to perform deterministic signing operations without exposing private keys.

  1. User authorizes the application to connect with their wallet

  2. Application requests specific signing capabilities through the wallet’s permission system

  3. Pseudocode to generate a deterministic private key using the wallet’s signing API:

    // Example of using wallet signing API instead of direct key derivation
    // NOTE: Wallet must implement RFC6979 compliant deterministic signatures
    let pathIndex = 0;
    let isValidKey = false;
    let candidatePrivateKey;
    let derivationPath;
    while (!isValidKey) {
    // TODO: derivationPath is based on BIP44 standard for HD wallets, we need to define a standard for web5
    derivationPath = `m/44'/0'/0'/0/${pathIndex}`;
    // Request signature from wallet with current derivation path
    const signatureResult = await wallet.sign({
    didMethod: "did:ckb",
    keyType: "secp256k1",
    data: "signingKey",
    derivationPath: derivationPath,
    });
    // Use signatureResult as seed input to generate a candidate private key
    candidatePrivateKey = await crypto.subtle.digest(
    "SHA-256",
    new TextEncoder().encode(signatureResult)
    );
    // Convert to appropriate format for checks
    const keyArray = new Uint8Array(candidatePrivateKey);
    // Check if key is valid for the selected curve, for secp256k1, key must be > 0 and < curve order
    const curveOrder = new BigInt(
    "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
    );
    const keyBigInt = bytesToBigInt(keyArray);
    isValidKey = keyBigInt > 0 && keyBigInt < curveOrder;
    if (!isValidKey) {
    // If invalid, try with an incremented path index
    pathIndex++;
    }
    }
    // Now candidatePrivateKey contains a valid private key derived from the signature
    // Use it for application-specific cryptographic operations
    // This key will be the same across devices if using the same wallet seed
  4. To rotate keys, the application can request the wallet to generate a new key pair using the same derivation path but with a new index.

With this approach:

  • Private keys never leave the secure wallet environment
  • Key derivation happens within trusted, audited code
  • Hardware security modules (HSMs) or secure enclaves can be leveraged
  • Consistent signatures can be produced across devices using the same wallet recovery phrase
  • Applications cannot extract or misuse private key material

Multi-device support is achieved through wallet recovery mechanisms:

  • Users back up their wallet recovery phrase (typically BIP39 mnemonic)
  • The same wallet can be restored on multiple devices
  • Signing operations produce identical results across all devices

For this approach to work seamlessly:

  • Applications must integrate with standard wallet connection protocols
  • A standard derivation path scheme should be established for web5 did
  • Applications should verify wallet compatibility before attempting operations
  • Wallets should provide testing capabilities to verify correct signature generation

Method 2: Random Key Generation with Import/Export

Section titled “Method 2: Random Key Generation with Import/Export”

This approach generates random keys and provides functionality to securely export and import them across devices.

  1. Generate a random private key using a cryptographically secure random number generator:
    privateKey = secureRandomBytes(32)
  2. Derive the public key from the private key:
    publicKey = derivePublicKey(privateKey)
  3. Store the private key securely on the device
  1. Encrypt the private key with a user-provided password:
    encryptedKey = encrypt(privateKey, password)
  2. Generate export format (e.g., JSON, QR code) with metadata:
    {
    "version": "1.0",
    "keyType": "secp256k1",
    "encryptedKey": "base64EncodedEncryptedKey",
    "salt": "base64EncodedSalt",
    "iv": "base64EncodedIV"
    }
  3. Import on other devices by decrypting with the same password

The PDS API would need to be extended to:

  1. Accept client-signed data instead of requiring the PDS to perform signing
  2. Verify the signature against the registered public key
  3. Support registration of client-generated public keys
  • Key material must never be transmitted unencrypted
  • Client-side key storage should leverage platform security features (Keychain, TPM, etc.)
  • Recovery phrases or backup mechanisms must be implemented securely
  • Authentication between client and PDS remains separate from identity signing keys
  • Implementation should protect against side-channel attacks

Client libraries and applications implementing this proposal should:

  1. Provide deterministic or random key generation methods
  2. Implement secure key storage using platform-specific mechanisms
  3. Support standardized import/export formats for randomly generated keys
  4. Include clear user guidance on key management
  5. Provide methods to rotate keys if compromised

This proposal can maintain compatibility with existing PDS infrastructure by:

  1. Supporting both client-side signing and PDS delegation during transition
  2. Providing migration paths for users to move from PDS-managed keys to client-managed keys
  3. Using the same signature formats and verification methods