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 ¶
- func BundleFilePath(langoDir string) string
- func CanonicalBundleBytes(b *IdentityBundle) ([]byte, error)
- func ComputeDIDv2(b *IdentityBundle) (string, error)
- func HasBundleFile(langoDir string) bool
- func ParseDIDPublicKey(didStr string) ([]byte, error)
- func StoreBundleFile(langoDir string, bundle *IdentityBundle) error
- func StoreKnownBundle(langoDir string, didV2 string, bundle *IdentityBundle) error
- func VerifyMessageSignature(didStr string, message, signature []byte) error
- type BundleProofs
- type BundleProvider
- func (p *BundleProvider) Algorithm() string
- func (p *BundleProvider) Bundle() *IdentityBundle
- func (p *BundleProvider) DID(_ context.Context) (*DID, error)
- func (p *BundleProvider) DIDString(ctx context.Context) (string, error)
- func (p *BundleProvider) HasPQKey() bool
- func (p *BundleProvider) LegacyDID(ctx context.Context) (*DID, error)
- func (p *BundleProvider) PQAlgorithm() string
- func (p *BundleProvider) PQPublicKey() []byte
- func (p *BundleProvider) PublicKey(_ context.Context) ([]byte, error)
- func (p *BundleProvider) SignMessage(_ context.Context, message []byte) ([]byte, error)
- func (p *BundleProvider) SignPQ(_ context.Context, message []byte) ([]byte, error)
- func (p *BundleProvider) VerifyDID(did *DID, peerID peer.ID) error
- type BundleProviderConfig
- type BundleResolver
- type DID
- type DIDAlias
- type IdentityBundle
- type KeyProvider
- type LocalIdentityProvider
- type MemoryBundleCache
- type Provider
- type PublicKeyEntry
- type WalletDIDProvider
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BundleFilePath ¶ added in v0.7.0
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
HasBundleFile reports whether a local identity bundle file exists.
func ParseDIDPublicKey ¶ added in v0.7.0
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
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
SignMessage signs a message with the Ed25519 identity key.
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 ¶
DIDFromPublicKey creates a v1 DID from a compressed secp256k1 public key.
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
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
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.