identity

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package identity provides decentralized identity (DID) derivation from wallet public keys. DIDs are deterministically derived from compressed secp256k1 public keys and mapped to libp2p peer IDs for P2P networking. Private keys never leave the wallet layer.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BundleFilePath added in v0.7.0

func BundleFilePath(langoDir string) string

BundleFilePath returns the path to the local identity bundle file.

func CanonicalBundleBytes added in v0.7.0

func CanonicalBundleBytes(b *IdentityBundle) ([]byte, error)

CanonicalBundleBytes returns the deterministic JSON encoding of the canonical bundle fields (Version, SigningKey, SettlementKey, LegacyDID). CreatedAt and Proofs are excluded so the same key set always produces the same bytes.

func ComputeDIDv2 added in v0.7.0

func ComputeDIDv2(b *IdentityBundle) (string, error)

ComputeDIDv2 computes the content-addressed DID v2 string from an IdentityBundle. The ID is SHA-256(canonical bytes)[:20] hex-encoded. Same key set + same legacy DID always produces the same DID v2.

func HasBundleFile added in v0.7.0

func HasBundleFile(langoDir string) bool

HasBundleFile reports whether a local identity bundle file exists.

func ParseDIDPublicKey added in v0.7.0

func ParseDIDPublicKey(didStr string) ([]byte, error)

ParseDIDPublicKey extracts the raw public key bytes from a v1 DID string without deriving a peer ID. Returns an error for v2 DIDs (content-addressed, no embedded public key — use BundleResolver instead).

func StoreBundleFile added in v0.7.0

func StoreBundleFile(langoDir string, bundle *IdentityBundle) error

StoreBundleFile writes the identity bundle atomically. Uses write-to-temp-and-rename to avoid partial files on crash.

func StoreKnownBundle added in v0.7.0

func StoreKnownBundle(langoDir string, didV2 string, bundle *IdentityBundle) error

StoreKnownBundle persists a remote peer's IdentityBundle to disk.

func VerifyMessageSignature added in v0.7.0

func VerifyMessageSignature(didStr string, message, signature []byte) error

VerifyMessageSignature verifies a secp256k1-keccak256 signature against a v1 DID. For v2 DIDs, use the verifier map pattern (BundleResolver → pubkey → verify).

Types

type BundleProofs added in v0.7.0

type BundleProofs struct {
	Legacy  []byte `json:"legacy,omitempty"`  // secp256k1+keccak256 signature over canonical
	Ed25519 []byte `json:"ed25519,omitempty"` // Ed25519 signature over canonical
	MLDSA65 []byte `json:"mldsa65,omitempty"` // ML-DSA-65 signature over canonical
}

BundleProofs contains ownership proofs over the canonical bundle.

type BundleProvider added in v0.7.0

type BundleProvider struct {
	// contains filtered or unexported fields
}

BundleProvider manages the local agent's v2 identity. It creates and caches the IdentityBundle, derives the DID v2, and provides Ed25519 signing.

BundleProvider does NOT implement VerifyDID for remote peers — that responsibility belongs to BundleResolver.

func NewBundleProvider added in v0.7.0

func NewBundleProvider(cfg BundleProviderConfig) (*BundleProvider, error)

NewBundleProvider creates a BundleProvider. If a bundle file exists, it is loaded and verified. Otherwise, a new bundle is created, proofs generated, and the bundle stored to disk.

func (*BundleProvider) Algorithm added in v0.7.0

func (p *BundleProvider) Algorithm() string

Algorithm returns the signing algorithm identifier.

func (*BundleProvider) Bundle added in v0.7.0

func (p *BundleProvider) Bundle() *IdentityBundle

Bundle returns the current IdentityBundle.

func (*BundleProvider) DID added in v0.7.0

func (p *BundleProvider) DID(_ context.Context) (*DID, error)

DID returns the v2 DID for this agent.

func (*BundleProvider) DIDString added in v0.7.0

func (p *BundleProvider) DIDString(ctx context.Context) (string, error)

DIDString returns the DID v2 string for the Signer.DID() interface.

func (*BundleProvider) HasPQKey added in v0.7.0

func (p *BundleProvider) HasPQKey() bool

HasPQKey reports whether a PQ signing key is available.

func (*BundleProvider) LegacyDID added in v0.7.0

func (p *BundleProvider) LegacyDID(ctx context.Context) (*DID, error)

LegacyDID returns the v1 DID for backward compatibility.

func (*BundleProvider) PQAlgorithm added in v0.7.0

func (p *BundleProvider) PQAlgorithm() string

PQAlgorithm returns the PQ signing algorithm identifier.

func (*BundleProvider) PQPublicKey added in v0.7.0

func (p *BundleProvider) PQPublicKey() []byte

PQPublicKey returns the ML-DSA-65 public key bytes, or nil if unavailable.

func (*BundleProvider) PublicKey added in v0.7.0

func (p *BundleProvider) PublicKey(_ context.Context) ([]byte, error)

PublicKey returns the Ed25519 public key.

func (*BundleProvider) SignMessage added in v0.7.0

func (p *BundleProvider) SignMessage(_ context.Context, message []byte) ([]byte, error)

SignMessage signs a message with the Ed25519 identity key.

func (*BundleProvider) SignPQ added in v0.7.0

func (p *BundleProvider) SignPQ(_ context.Context, message []byte) ([]byte, error)

SignPQ signs a message with the ML-DSA-65 PQ signing key.

func (*BundleProvider) VerifyDID added in v0.7.0

func (p *BundleProvider) VerifyDID(did *DID, peerID peer.ID) error

VerifyDID checks that a v1 DID matches the claimed peer ID. For v2 DIDs, use BundleResolver instead.

type BundleProviderConfig added in v0.7.0

type BundleProviderConfig struct {
	SigningKey       ed25519.PrivateKey
	SettlementPub    []byte // compressed secp256k1 public key from wallet
	PQSigningKeySeed []byte // 32-byte HKDF seed for ML-DSA-65 (optional, nil = no PQ)
	LangoDir         string
	Legacy           *WalletDIDProvider
	Logger           *zap.SugaredLogger
}

BundleProviderConfig holds the configuration for creating a BundleProvider.

type BundleResolver added in v0.7.0

type BundleResolver interface {
	ResolveBundle(did string) (*IdentityBundle, error)
}

BundleResolver looks up IdentityBundles for remote peers by DID v2 string. Implementations are populated during handshakes and gossip.

type DID

type DID struct {
	ID        string  `json:"id"`                  // "did:lango:<hex>" or "did:lango:v2:<hash>"
	PublicKey []byte  `json:"publicKey,omitempty"` // signing key (v1: secp256k1, v2: empty until resolved)
	PeerID    peer.ID `json:"peerId,omitempty"`    // libp2p peer ID (v1: derived, v2: empty until resolved)
	Version   int     `json:"version"`             // 1 or 2
}

DID represents a decentralized identifier. For v1 (did:lango:<hex>): PublicKey and PeerID are populated from the DID string. For v2 (did:lango:v2:<hash>): PublicKey and PeerID are empty (requires BundleResolver).

func DIDFromPublicKey

func DIDFromPublicKey(pubkey []byte) (*DID, error)

DIDFromPublicKey creates a v1 DID from a compressed secp256k1 public key.

func ParseDID

func ParseDID(didStr string) (*DID, error)

ParseDID parses a DID string into a DID struct. Supports both v1 and v2 formats. V1 (did:lango:<hex>): PublicKey and PeerID are populated from the embedded key. V2 (did:lango:v2:<hash>): Version=2, PublicKey=nil, PeerID="" (requires BundleResolver).

type DIDAlias added in v0.7.0

type DIDAlias struct {
	// contains filtered or unexported fields
}

DIDAlias maps v2 DID ↔ v1 DID for session/reputation continuity. When a peer has both a v1 and v2 DID, CanonicalDID returns the v1 DID to preserve existing session and reputation data.

func NewDIDAlias added in v0.7.0

func NewDIDAlias() *DIDAlias

NewDIDAlias creates a new empty alias registry.

func (*DIDAlias) CanonicalDID added in v0.7.0

func (a *DIDAlias) CanonicalDID(did string) string

CanonicalDID returns the canonical DID for session/reputation lookups. If the input is a v2 DID with a known v1 alias, returns the v1 DID. Otherwise returns the input unchanged.

func (*DIDAlias) RegisterFromBundle added in v0.7.0

func (a *DIDAlias) RegisterFromBundle(bundle *IdentityBundle, didV2 string)

RegisterFromBundle registers the v2 ↔ v1 alias from an IdentityBundle.

type IdentityBundle added in v0.7.0

type IdentityBundle struct {
	Version       int             `json:"version"`
	Generation    uint32          `json:"generation"`               // Ed25519 key derivation generation (default 0)
	SigningKey    PublicKeyEntry  `json:"signing_key"`              // Ed25519 primary signing key
	SettlementKey PublicKeyEntry  `json:"settlement_key"`           // secp256k1 (from wallet)
	LegacyDID     string          `json:"legacy_did,omitempty"`     // did:lango:<secp256k1-hex> for v1 compat
	PQGeneration  uint32          `json:"pq_generation,omitempty"`  // ML-DSA key derivation generation (default 0)
	PQSigningKey  *PublicKeyEntry `json:"pq_signing_key,omitempty"` // ML-DSA-65 PQ signing key (nil if unavailable)
	Proofs        BundleProofs    `json:"proofs"`
	CreatedAt     time.Time       `json:"created_at"`
}

IdentityBundle is a public identity document containing signing and settlement keys with dual proofs. It is not secret — the bundle is shared with peers via handshake and gossip.

func LoadBundleFile added in v0.7.0

func LoadBundleFile(langoDir string) (*IdentityBundle, error)

LoadBundleFile reads and parses the local identity bundle. Returns (nil, nil) if the file does not exist.

func LoadKnownBundle added in v0.7.0

func LoadKnownBundle(langoDir string, didV2 string) (*IdentityBundle, error)

LoadKnownBundle loads a cached remote peer bundle from disk. Returns (nil, nil) if not found.

type KeyProvider added in v0.7.0

type KeyProvider interface {
	PublicKey(ctx context.Context) ([]byte, error)
}

KeyProvider is the minimal interface for public key retrieval. wallet.WalletProvider satisfies this via Go structural typing.

type LocalIdentityProvider added in v0.7.0

type LocalIdentityProvider interface {
	DID(ctx context.Context) (*DID, error)
	Bundle() *IdentityBundle
	LegacyDID(ctx context.Context) (*DID, error)
	SignMessage(ctx context.Context, message []byte) ([]byte, error)
	PublicKey(ctx context.Context) ([]byte, error)
	Algorithm() string
	DIDString(ctx context.Context) (string, error)
}

LocalIdentityProvider is the interface for local agent identity operations. It combines DID retrieval with signing capabilities. Remote DID verification is handled separately by BundleResolver.

type MemoryBundleCache added in v0.7.0

type MemoryBundleCache struct {
	// contains filtered or unexported fields
}

MemoryBundleCache is a simple in-memory BundleResolver populated during handshakes and gossip card exchanges.

func NewMemoryBundleCache added in v0.7.0

func NewMemoryBundleCache() *MemoryBundleCache

NewMemoryBundleCache creates a new empty bundle cache.

func (*MemoryBundleCache) ResolveBundle added in v0.7.0

func (c *MemoryBundleCache) ResolveBundle(did string) (*IdentityBundle, error)

ResolveBundle looks up a bundle by DID v2 string.

func (*MemoryBundleCache) Store added in v0.7.0

func (c *MemoryBundleCache) Store(didV2 string, bundle *IdentityBundle)

Store caches an IdentityBundle under its DID v2.

type Provider

type Provider interface {
	// DID returns the DID for the current identity key.
	DID(ctx context.Context) (*DID, error)
	// VerifyDID checks that a DID matches the claimed peer ID.
	VerifyDID(did *DID, peerID peer.ID) error
}

Provider creates and verifies DIDs.

type PublicKeyEntry added in v0.7.0

type PublicKeyEntry struct {
	Algorithm string `json:"algorithm"`
	PublicKey []byte `json:"public_key"`
}

PublicKeyEntry describes a public key with its algorithm.

type WalletDIDProvider

type WalletDIDProvider struct {
	// contains filtered or unexported fields
}

WalletDIDProvider derives DIDs from a public key provider.

func NewProvider

func NewProvider(keys KeyProvider, logger *zap.SugaredLogger) *WalletDIDProvider

NewProvider creates a new WalletDIDProvider.

func (*WalletDIDProvider) DID

func (p *WalletDIDProvider) DID(ctx context.Context) (*DID, error)

DID returns the DID for the current wallet, caching the result since the wallet key does not change.

func (*WalletDIDProvider) VerifyDID

func (p *WalletDIDProvider) VerifyDID(did *DID, peerID peer.ID) error

VerifyDID checks that a DID's public key produces the claimed peer ID.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL