Documentation
¶
Overview ¶
Package didcomm implements DIDComm Messaging v2.1 specification.
DIDComm Messaging is a secure, private communication methodology built atop the decentralized design of DIDs. It provides:
- End-to-end encryption between parties identified by DIDs
- Authentication of message senders
- Routing through mediators for asynchronous delivery
- Protocol negotiation and extensibility
This package is integrated with the vc project's existing infrastructure:
- keyresolver: For DID document and key resolution via AuthZEN
- trust: For trust evaluation of communication partners
- jose: For JWK/JWT operations
- signing: For cryptographic signing operations
Architecture ¶
The package is organized into sub-packages:
- message: Core message types (plaintext, signed, encrypted)
- crypto: JWE encryption (ECDH-ES, ECDH-1PU) and JWS signing
- transport: HTTP and WebSocket transport implementations
- routing: Forward messages and mediator support
- protocol: Built-in protocols (Trust Ping, OOB, Discover Features)
- agent: High-level Agent API for building DIDComm applications
Build Tags ¶
This package requires the "didcomm" build tag:
go build -tags=didcomm ./... go test -tags=didcomm ./pkg/didcomm/...
Quick Start ¶
import (
"github.com/SUNET/vc/pkg/didcomm"
"github.com/SUNET/vc/pkg/didcomm/message"
"github.com/SUNET/vc/pkg/didcomm/agent"
)
// Create a DIDComm agent
a := agent.New(agent.Config{
DID: "did:web:example.com",
Resolver: didcomm.NewResolver("https://pdp.example.com"),
})
// Send a message
msg := message.New(
message.WithType("https://example.com/protocols/1.0/ping"),
message.WithTo([]string{"did:web:recipient.com"}),
)
err := a.Send(ctx, msg)
Specification ¶
This implementation follows DIDComm Messaging v2.1: https://identity.foundation/didcomm-messaging/spec/v2.1/
Interoperability ¶
The implementation is tested against the didcomm-rust reference implementation via eclipse-xfsc/didcomm-v2-connector UniFFI bindings.
Index ¶
- Constants
- Variables
- type DIDCommService
- type DIDDocument
- type KeyAgreementKey
- type PackOptions
- type PackResult
- func Pack(ctx context.Context, msg *message.Message, opts PackOptions) (*PackResult, error)
- func PackAnoncrypt(ctx context.Context, msg *message.Message, recipientKeys []jwk.Key) (*PackResult, error)
- func PackAuthcrypt(ctx context.Context, msg *message.Message, senderKey jwk.Key, ...) (*PackResult, error)
- func PackPlaintext(msg *message.Message) (*PackResult, error)
- func PackSigned(ctx context.Context, msg *message.Message, signerKey jwk.Key) (*PackResult, error)
- type Resolver
- type Service
- type UnpackOptions
- type UnpackResult
- type VerificationKey
- type VerificationMethod
Examples ¶
Constants ¶
const ( // MediaTypePlaintext is the media type for plaintext DIDComm messages MediaTypePlaintext = "application/didcomm-plain+json" // MediaTypeSigned is the media type for signed DIDComm messages (JWS) MediaTypeSigned = "application/didcomm-signed+json" // MediaTypeEncrypted is the media type for encrypted DIDComm messages (JWE) MediaTypeEncrypted = "application/didcomm-encrypted+json" )
MediaType constants for DIDComm message formats. Per DIDComm v2.1 spec Section 2.4.
const ( // Trust Ping 2.0 ProtocolTrustPing = "https://didcomm.org/trust-ping/2.0" MessageTypePing = "https://didcomm.org/trust-ping/2.0/ping" MessageTypePingResponse = "https://didcomm.org/trust-ping/2.0/ping-response" // Discover Features 2.0 ProtocolDiscoverFeatures = "https://didcomm.org/discover-features/2.0" MessageTypeQuery = "https://didcomm.org/discover-features/2.0/queries" MessageTypeDisclose = "https://didcomm.org/discover-features/2.0/disclose" // Out-of-Band 2.0 ProtocolOutOfBand = "https://didcomm.org/out-of-band/2.0" MessageTypeInvitation = "https://didcomm.org/out-of-band/2.0/invitation" // Routing 2.0 ProtocolRouting = "https://didcomm.org/routing/2.0" MessageTypeForward = "https://didcomm.org/routing/2.0/forward" )
Protocol URIs for built-in DIDComm protocols.
const ( // Key Agreement Algorithms (for encryption) AlgECDHES = "ECDH-ES" // Anonymous encryption AlgECDH1PU = "ECDH-1PU" // Authenticated encryption // Content Encryption Algorithms EncA256GCM = "A256GCM" // Recommended for anoncrypt EncA256CBCHS512 = "A256CBC-HS512" // Required for authcrypt // Signing Algorithms AlgEdDSA = "EdDSA" // Ed25519 (Required) AlgES256 = "ES256" // P-256 (Required) AlgES256K = "ES256K" // secp256k1 (Required) AlgES384 = "ES384" // P-384 // Key Agreement Curves CurveX25519 = "X25519" // Required CurveP256 = "P-256" // Required CurveP384 = "P-384" // Required // Signing Curves CurveEd25519 = "Ed25519" // Required CurveSecp256k1 = "secp256k1" // Required )
Algorithm identifiers per DIDComm v2.1 spec.
const OOBQueryParam = "_oob"
OOB URL parameter name for Out-of-Band invitations.
const ServiceTypeDIDComm = "DIDCommMessaging"
DIDCommMessaging service type for DID document service entries.
Variables ¶
var ( // Message errors ErrInvalidMessage = errors.New("didcomm: invalid message") ErrMissingID = errors.New("didcomm: message missing id") ErrMissingType = errors.New("didcomm: message missing type") ErrMissingTo = errors.New("didcomm: message missing to") ErrInvalidMediaType = errors.New("didcomm: invalid media type") ErrMessageExpired = errors.New("didcomm: message expired") ErrInvalidAttachment = errors.New("didcomm: invalid attachment") ErrAttachmentNotFound = errors.New("didcomm: attachment not found") // Cryptographic errors ErrEncryptionFailed = errors.New("didcomm: encryption failed") ErrDecryptionFailed = errors.New("didcomm: decryption failed") ErrSigningFailed = errors.New("didcomm: signing failed") ErrVerificationFailed = errors.New("didcomm: signature verification failed") ErrUnsupportedAlgorithm = errors.New("didcomm: unsupported algorithm") ErrInvalidKey = errors.New("didcomm: invalid key") ErrKeyNotFound = errors.New("didcomm: key not found") // DID resolution errors ErrDIDResolutionFailed = errors.New("didcomm: DID resolution failed") ErrKeyAgreementNotFound = errors.New("didcomm: key agreement key not found") ErrServiceNotFound = errors.New("didcomm: DIDCommMessaging service not found") ErrInvalidDID = errors.New("didcomm: invalid DID") // Transport errors ErrTransportFailed = errors.New("didcomm: transport failed") ErrEndpointNotFound = errors.New("didcomm: endpoint not found") ErrConnectionFailed = errors.New("didcomm: connection failed") ErrTimeout = errors.New("didcomm: operation timed out") // Routing errors ErrRoutingFailed = errors.New("didcomm: routing failed") ErrInvalidForward = errors.New("didcomm: invalid forward message") ErrUnwrapFailed = errors.New("didcomm: failed to unwrap forwarded message") // Protocol errors ErrUnknownProtocol = errors.New("didcomm: unknown protocol") ErrProtocolViolation = errors.New("didcomm: protocol violation") ErrProblemReport = errors.New("didcomm: problem report received") )
Sentinel errors for DIDComm operations. Following ADR-004: Use sentinel errors for expected error conditions.
Functions ¶
This section is empty.
Types ¶
type DIDCommService ¶
type DIDCommService struct {
// ID is the service ID
ID string
// ServiceEndpoint is the URI or DID for message delivery
ServiceEndpoint string
// RoutingKeys are the keys to use for routing/mediation
RoutingKeys []string
// Accept lists the accepted media types
Accept []string
}
DIDCommService represents a DIDCommMessaging service endpoint from a DID document.
type DIDDocument ¶
type DIDDocument struct {
Context []string `json:"@context,omitempty"`
ID string `json:"id"`
VerificationMethod []VerificationMethod `json:"verificationMethod,omitempty"`
KeyAgreement []any `json:"keyAgreement,omitempty"`
Service []Service `json:"service,omitempty"`
}
DIDDocument represents a W3C DID Document. This is a subset of the full DID Document structure, containing fields relevant to DIDComm.
type KeyAgreementKey ¶
type KeyAgreementKey struct {
// ID is the key ID (verification method ID)
ID string
// Type is the key type (e.g., "X25519KeyAgreementKey2020", "JsonWebKey2020")
Type string
// Controller is the DID that controls this key
Controller string
// PublicKey is the raw public key material
// Type depends on the curve: *ecdh.PublicKey for X25519/P-256/P-384
PublicKey any
}
KeyAgreementKey represents a key that can be used for key agreement (encryption).
type PackOptions ¶
type PackOptions struct {
// EncryptionMode specifies the encryption mode.
// "anoncrypt" for anonymous encryption (ECDH-ES)
// "authcrypt" for authenticated encryption (ECDH-1PU)
// Empty string for no encryption
EncryptionMode string
// SignBeforeEncrypt signs the message before encrypting.
// Creates a signed-then-encrypted message.
SignBeforeEncrypt bool
// SignerKey is the private key for signing (required if SignBeforeEncrypt is true)
SignerKey jwk.Key
// SenderKey is the private key for authcrypt (required if EncryptionMode is "authcrypt")
SenderKey jwk.Key
// RecipientKeys are the public keys of the recipients
RecipientKeys []jwk.Key
// Forward wraps the message for routing through mediators
Forward bool
// RoutingKeys are the mediator keys for forwarding
RoutingKeys []jwk.Key
}
PackOptions configures message packing behavior.
type PackResult ¶
type PackResult struct {
// Message is the packed message bytes (JWE, JWS, or plaintext JSON)
Message []byte
// MediaType is the content type of the packed message
MediaType string
// FromKID is the key ID of the sender (if authenticated)
FromKID string
// ToKIDs are the key IDs of the recipients
ToKIDs []string
}
PackResult contains the packed message and metadata.
func Pack ¶
func Pack(ctx context.Context, msg *message.Message, opts PackOptions) (*PackResult, error)
Pack packs a DIDComm message according to the specified options. It can produce plaintext, signed, or encrypted messages.
func PackAnoncrypt ¶
func PackAnoncrypt(ctx context.Context, msg *message.Message, recipientKeys []jwk.Key) (*PackResult, error)
PackAnoncrypt packs a message with anonymous encryption (ECDH-ES).
func PackAuthcrypt ¶
func PackAuthcrypt(ctx context.Context, msg *message.Message, senderKey jwk.Key, recipientKeys []jwk.Key) (*PackResult, error)
PackAuthcrypt packs a message with authenticated encryption (ECDH-1PU).
func PackPlaintext ¶
func PackPlaintext(msg *message.Message) (*PackResult, error)
PackPlaintext packs a message as plaintext JSON (no encryption or signing).
Example ¶
package main
import (
"encoding/json"
"fmt"
"github.com/SUNET/vc/pkg/didcomm"
"github.com/SUNET/vc/pkg/didcomm/message"
)
func main() {
msg := message.New(
message.WithID("msg-001"),
message.WithType(didcomm.MessageTypePing),
message.WithFrom("did:example:alice"),
message.WithTo("did:example:bob"),
message.WithBody(map[string]any{"response_requested": true}),
)
result, err := didcomm.PackPlaintext(msg)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("media type:", result.MediaType)
// Verify the packed message is valid JSON with expected fields
var parsed map[string]any
if err := json.Unmarshal(result.Message, &parsed); err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("id:", parsed["id"])
fmt.Println("type:", parsed["type"])
fmt.Println("from:", parsed["from"])
}
Output: media type: application/didcomm-plain+json id: msg-001 type: https://didcomm.org/trust-ping/2.0/ping from: did:example:alice
func PackSigned ¶
PackSigned packs a message as a signed JWS.
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver provides DID resolution for DIDComm operations. It wraps the existing keyresolver.SmartResolver with DIDComm-specific functionality.
func NewResolver ¶
NewResolver creates a DIDComm resolver using AuthZEN-based DID resolution. The pdpURL is the URL of the AuthZEN Policy Decision Point for trust evaluation.
func NewResolverWithBase ¶
func NewResolverWithBase(base keyresolver.Resolver) *Resolver
NewResolverWithBase creates a DIDComm resolver with a custom base resolver. This allows using different resolution backends.
func (*Resolver) ResolveKeyAgreement ¶
ResolveKeyAgreement resolves key agreement keys for a DID. These keys are used for encryption (ECDH key exchange). For network DIDs, this delegates to go-trust via AuthZEN to extract keyAgreement keys from the resolved DID document. For local DIDs (did:key, did:jwk, did:peer), resolution is performed locally.
func (*Resolver) ResolveService ¶
ResolveService resolves DIDCommMessaging service endpoints for a DID. For network DIDs, this delegates to go-trust via AuthZEN to extract service endpoints from the resolved DID document. For did:peer:2, services are extracted from the inline data.
func (*Resolver) ResolveVerification ¶
ResolveVerification resolves verification keys for a DID. These keys are used for signature verification.
type Service ¶
type Service struct {
ID string `json:"id"`
Type string `json:"type"`
ServiceEndpoint any `json:"serviceEndpoint"`
RoutingKeys []string `json:"routingKeys,omitempty"`
Accept []string `json:"accept,omitempty"`
}
Service represents a service in a DID Document.
type UnpackOptions ¶
type UnpackOptions struct {
// KeyStore provides private keys for decryption
KeyStore crypto.KeyStore
// KeyResolver provides public keys for signature verification
KeyResolver crypto.KeyResolver
// ExpectEncrypted requires the message to be encrypted
ExpectEncrypted bool
// ExpectSigned requires the message to be signed
ExpectSigned bool
}
UnpackOptions configures message unpacking behavior.
type UnpackResult ¶
type UnpackResult struct {
// Message is the unpacked plaintext message
Message *message.Message
// WasEncrypted indicates if the message was encrypted
WasEncrypted bool
// WasSigned indicates if the message was signed
WasSigned bool
// SignerKID is the key ID of the signer (if signed)
SignerKID string
// RecipientKID is the key ID used for decryption (if encrypted)
RecipientKID string
// EncryptionAlgorithm is the algorithm used for encryption
EncryptionAlgorithm string
// SignatureAlgorithm is the algorithm used for signing
SignatureAlgorithm string
}
UnpackResult contains the unpacked message and metadata.
func Unpack ¶
func Unpack(ctx context.Context, data []byte, opts UnpackOptions) (*UnpackResult, error)
Unpack unpacks a DIDComm message, decrypting and/or verifying as needed.
type VerificationKey ¶
type VerificationKey struct {
// ID is the key ID (verification method ID)
ID string
// Type is the key type (e.g., "Ed25519VerificationKey2020", "JsonWebKey2020")
Type string
// Controller is the DID that controls this key
Controller string
// PublicKey is the raw public key material
// Type: ed25519.PublicKey for EdDSA, *ecdsa.PublicKey for ES256/ES256K/ES384
PublicKey any
}
VerificationKey represents a key that can be used for verification (signing).
type VerificationMethod ¶
type VerificationMethod struct {
ID string `json:"id"`
Type string `json:"type"`
Controller string `json:"controller"`
PublicKeyJwk json.RawMessage `json:"publicKeyJwk,omitempty"`
PublicKeyMultibase string `json:"publicKeyMultibase,omitempty"`
}
VerificationMethod represents a verification method in a DID Document.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package agent provides a high-level DIDComm agent implementation.
|
Package agent provides a high-level DIDComm agent implementation. |
|
Package crypto provides cryptographic primitives for DIDComm v2.1 messaging.
|
Package crypto provides cryptographic primitives for DIDComm v2.1 messaging. |
|
Package message provides DIDComm v2.1 message types and operations.
|
Package message provides DIDComm v2.1 message types and operations. |
|
Package protocol implements DIDComm v2.1 protocols.
|
Package protocol implements DIDComm v2.1 protocols. |
|
discoverfeatures
Package discoverfeatures implements the DIDComm Discover Features Protocol 2.0.
|
Package discoverfeatures implements the DIDComm Discover Features Protocol 2.0. |
|
issuecredential
Package issuecredential implements the DIDComm Issue Credential protocol 3.0.
|
Package issuecredential implements the DIDComm Issue Credential protocol 3.0. |
|
oob
Package oob implements the DIDComm Out-of-Band Protocol 2.0.
|
Package oob implements the DIDComm Out-of-Band Protocol 2.0. |
|
pickup
Package pickup implements the DIDComm Pickup Protocol 2.0.
|
Package pickup implements the DIDComm Pickup Protocol 2.0. |
|
presentproof
Package presentproof implements the DIDComm present-proof protocol 3.0.
|
Package presentproof implements the DIDComm present-proof protocol 3.0. |
|
trustping
Package trustping implements the DIDComm Trust Ping Protocol 2.0.
|
Package trustping implements the DIDComm Trust Ping Protocol 2.0. |
|
Package routing implements DIDComm v2.1 message routing.
|
Package routing implements DIDComm v2.1 message routing. |
|
Package transport implements DIDComm v2.1 message transports.
|
Package transport implements DIDComm v2.1 message transports. |