Class Identity

Represents the root cryptographic identity derived from a seed phrase.

An Identity is the foundation of the Me2eM protocol. It allows for the hierarchical derivation of isolated Handles and SubHandles for different contexts (e.g., email, social, specific devices) from a single master seed, ensuring zero cross-contamination of cryptographic material.

The Identity provides two derivation entry points:

  • Identity.deriveHandle — derives a top-level Handle.
  • Identity.deriveSubHandle — atomically derives a SubHandle by its full path (Handle name + SubHandle name). Used primarily for stateless session verification on the server side.

Implements

Methods

  • Initializes a new Identity from a BIP39 mnemonic seed phrase or raw seed bytes.

    The seed is the full 64-byte BIP39 seed (PBKDF2-HMAC-SHA512 output, as produced by get64ByteSeedFromMnemonic). It is used as the HKDF-SHA256 input key material; HKDF info strings are unchanged.

    Parameters

    • seed: string | Uint8Array

      A 64-byte raw Uint8Array seed, or a hex-encoded string of 64 bytes.

    Returns Promise<Identity>

    A Promise resolving to a new Identity instance.

    MALFORMED/FORMAT if the provided seed is not exactly 64 bytes (or the hex string is not 128 characters).

    const seed = await get64ByteSeedFromMnemonic('abandon abandon ... art');
    const identity = await Identity.fromSeed(seed);
  • Derives a new, cryptographically isolated Handle for a specific context.

    Each Handle is derived deterministically. The same name will always produce the same Handle from the same Identity, but different names produce completely unrelated keys.

    Parameters

    • name: string

      The context identifier (e.g., '[email protected]', 'station-001').

    • Optionalmetadata: HandleMetadata

      Optional metadata to associate with this Handle.

    Returns Promise<Handle>

    A Promise resolving to the derived Handle.

    const handle = await identity.deriveHandle('station-001', {
    displayName: 'Berlin Station #001'
    });
  • Atomically derives a SubHandle from this Identity by its full path.

    This method performs the equivalent of:

    const handle = await identity.deriveHandle(handleName);
    const sub = await handle.deriveSubHandle(subName);

    but in a single call, without exposing the intermediate Handle.

    It is the recommended entry point for stateless session verification, because the server only needs the Identity and the path from the token.

    The resulting SubHandle is cryptographically identical to the one produced by Handle.deriveSubHandle(subName) on the same Identity.

    Parameters

    • handleName: string

      The parent Handle name.

    • subName: string

      The SubHandle name.

    • Optionalmetadata: SubHandleMetadata

      Optional SubHandle metadata with constraints.

    Returns Promise<SubHandle>

    A Promise resolving to the derived SubHandle with path [handleName, subName].

    // Server-side stateless verification
    const sub = await identity.deriveSubHandle('station-001', 'connector-1');
    const publicKey = sub.getPublicKey();
  • Signs arbitrary data with the root private key (implements Signer).

    This is what makes an Identity acceptable as the signer argument of Attestation.issue — the raw private key never leaves the Identity.

    Parameters

    • data: Uint8Array

      The data to be signed, as a Uint8Array.

    Returns Promise<Uint8Array>

    A Promise resolving to the 64-byte Ed25519 signature.

    If the Identity has been disposed.

  • Issues an attestation binding a derived Handle key to its name and grant. The subject public key is always derived internally — it is impossible to attest a foreign key, and the resulting subjectId always matches the handle reconstructed via Identity.deriveSubHandle.

    Parameters

    • name: string
    • grant: AttestationGrant

      Constraints verifiers will enforce for this handle and (via subNamePatterns) for the SubHandles it may attest.

    • Optionalopts: {
          ttlSeconds?: number;
          expiresAt?: number;
          jti?: string;
          now?: number;
      }
      • OptionalttlSeconds?: number
      • OptionalexpiresAt?: number
      • Optionaljti?: string
      • Optionalnow?: number

    Returns Promise<Attestation>

    An attestation signed by the Identity root key (the Identity passes itself to Attestation.issue as the Signer). Store it with the Handle — it is a public artifact, not a secret.

    MALFORMED/FORMAT if the name is not canonicalizable or the grant is invalid.

    const A = await identity.attestHandle('station-001', {
    audiences: ['ev-app.com'],
    scopes: ['charge:start', 'charge:stop', 'charge:status'],
    maxSessionTtl: 7200,
    subNamePatterns: ['connector-*', 'meter-*'],
    });
  • Retrieves the public key of the root Identity.

    The returned array is a defensive copy — mutating it does not affect the Identity.

    Returns Uint8Array

    A Uint8Array containing the 32-byte Ed25519 public key.

  • Redacted serialization contract: JSON.stringify(identity) exposes only the object kind and the public identifier — never key material or seed-derived state.

    Returns {
        kind: string;
        id: string;
    }

    • kind: string
    • id: string