Documentation
¶
Overview ¶
Package trust — JWKSKeyResolver implements SD-JWT VC spec §5.3 key resolution with a multi-endpoint discovery chain for maximum interoperability.
Package trust provides a unified trust evaluation interface for all credential formats.
This package bridges the gap between different credential formats' trust models:
- W3C VC 2.0 Data Integrity: uses DIDs for key identification
- SD-JWT VC: uses x5c certificate chains with issuer URLs
- ISO mDOC: uses IACA certificate chains with document signer certificates
The key distinction is between:
- Name-to-key RESOLUTION: Given a name (DID), fetch the associated public key
- Name-to-key VALIDATION: Given a name and key, verify the binding is trusted
When DIDs are used, go-trust can perform resolution. When certificates are used (SD-JWT x5c, mDOC MSO), the key is already present, so only validation is needed.
This package uses types from github.com/sirosfoundation/go-trust/pkg/trustapi and adds vc-specific logic like GetEffectiveAction() for policy routing.
Index ¶
- Constants
- type AllowAllEvaluator
- type CachedDecision
- type CachingTrustEvaluator
- func (c *CachingTrustEvaluator) Cache() *TrustCache
- func (c *CachingTrustEvaluator) Clear()
- func (c *CachingTrustEvaluator) Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
- func (c *CachingTrustEvaluator) Invalidate(req *EvaluationRequest)
- func (c *CachingTrustEvaluator) Stop()
- func (c *CachingTrustEvaluator) SupportsKeyType(kt KeyType) bool
- type CombinedTrustService
- type CompositeEvaluator
- type CompositeStrategy
- type EvaluationRequest
- type GoTrustEvaluator
- func (e *GoTrustEvaluator) Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
- func (e *GoTrustEvaluator) GetClient() *authzenclient.Client
- func (e *GoTrustEvaluator) ResolveKey(ctx context.Context, verificationMethod string) (crypto.PublicKey, error)
- func (e *GoTrustEvaluator) SupportsKeyType(kt KeyType) bool
- type JWKSKeyResolver
- type JWKSResolverConfig
- type KeyResolver
- type KeyType
- type LocalTrustConfigdeprecated
- type LocalTrustEvaluatordeprecated
- func (e *LocalTrustEvaluator) AddTrustedRoot(cert *x509.Certificate)
- func (e *LocalTrustEvaluator) Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
- func (e *LocalTrustEvaluator) GetTrustedRoots() []*x509.Certificate
- func (e *LocalTrustEvaluator) SupportsKeyType(kt KeyType) bool
- type Role
- type TrustCache
- func (c *TrustCache) Clear()
- func (c *TrustCache) Get(req *EvaluationRequest) *TrustDecision
- func (c *TrustCache) Invalidate(req *EvaluationRequest)
- func (c *TrustCache) InvalidateSubject(subjectID string)
- func (c *TrustCache) Len() int
- func (c *TrustCache) Set(req *EvaluationRequest, decision *TrustDecision)
- func (c *TrustCache) SetWithTTL(req *EvaluationRequest, decision *TrustDecision, ttl time.Duration)
- func (c *TrustCache) Stop()
- type TrustCacheConfig
- type TrustDecision
- type TrustEvaluator
- type TrustOptions
- type X5CCertChain
Examples ¶
Constants ¶
const ( // DefaultTrustCacheTTL is the default TTL for trust decisions. // Trust decisions are relatively stable, so a longer TTL is appropriate. DefaultTrustCacheTTL = 5 * time.Minute // MaxTrustCacheTTL is the maximum TTL for trust decisions. MaxTrustCacheTTL = 1 * time.Hour )
const ( // DefaultJWKSCacheTTL is the default TTL for cached JWKS entries. DefaultJWKSCacheTTL = 5 * time.Minute // DefaultJWKSMaxCapacity is the default max capacity for the JWKS cache. DefaultJWKSMaxCapacity = 100 )
const ( KeyTypeJWK = trustapi.KeyTypeJWK KeyTypeX5C = trustapi.KeyTypeX5C RoleIssuer = trustapi.RoleIssuer RoleVerifier = trustapi.RoleVerifier RoleWalletProvider = trustapi.RoleWalletProvider RolePIDProvider = trustapi.RolePIDProvider RoleCredentialIssuer = trustapi.RoleCredentialIssuer RoleCredentialVerifier = trustapi.RoleCredentialVerifier RoleAny = trustapi.RoleAny )
Constants re-exported from trustapi for convenience.
const (
// ErrMsgNilRequest is returned when an evaluation request is nil.
ErrMsgNilRequest = "evaluation request is nil"
)
Error messages for trust evaluation. These are package-level constants to ensure consistency across evaluator implementations.
const ( // TrustFrameworkNone indicates no trust framework validation occurred. // Used by AllowAllEvaluator when operating without a PDP. TrustFrameworkNone = "none" )
TrustFramework constants for common trust framework identifiers.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AllowAllEvaluator ¶
type AllowAllEvaluator struct{}
AllowAllEvaluator is a TrustEvaluator that always returns trusted=true. This is used when no PDP URL is configured ("allow all" mode).
In "allow all" mode:
- All trust evaluation requests return Trusted=true
- The TrustFramework is set to "none" to indicate no trust validation occurred
- Key resolution is not supported (returns an error)
This provides a consistent behavior across applications when trust evaluation is not required or during development/testing scenarios.
func NewAllowAllEvaluator ¶
func NewAllowAllEvaluator() *AllowAllEvaluator
NewAllowAllEvaluator creates a trust evaluator that accepts all requests. Use this when operating in "allow all" mode without a PDP.
Example ¶
package main
import (
"fmt"
"github.com/SUNET/vc/pkg/trust"
)
func main() {
evaluator := trust.NewAllowAllEvaluator()
fmt.Printf("%T\n", evaluator)
}
Output: *trust.AllowAllEvaluator
func (*AllowAllEvaluator) Evaluate ¶
func (e *AllowAllEvaluator) Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
Evaluate implements TrustEvaluator. Always returns trusted=true for supported key types.
Example ¶
package main
import (
"context"
"fmt"
"github.com/SUNET/vc/pkg/trust"
)
func main() {
ctx := context.Background()
evaluator := trust.NewAllowAllEvaluator()
req := trust.NewEvaluationRequest("https://issuer.example.com", trust.KeyTypeJWK, nil)
decision, err := evaluator.Evaluate(ctx, req)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("trusted:", decision.Trusted)
fmt.Println("reason:", decision.Reason)
fmt.Println("framework:", decision.TrustFramework)
}
Output: trusted: true reason: allow all mode: no PDP configured framework: none
func (*AllowAllEvaluator) ResolveKey ¶
func (e *AllowAllEvaluator) ResolveKey(ctx context.Context, verificationMethod string) (crypto.PublicKey, error)
ResolveKey attempts to resolve a key but is not supported in allow-all mode. Key resolution requires an actual PDP service to resolve DIDs and verify trust.
func (*AllowAllEvaluator) SupportsKeyType ¶
func (e *AllowAllEvaluator) SupportsKeyType(kt KeyType) bool
SupportsKeyType implements TrustEvaluator. Supports JWK and X5C key types.
Example ¶
package main
import (
"fmt"
"github.com/SUNET/vc/pkg/trust"
)
func main() {
evaluator := trust.NewAllowAllEvaluator()
fmt.Println("supports JWK:", evaluator.SupportsKeyType(trust.KeyTypeJWK))
fmt.Println("supports X5C:", evaluator.SupportsKeyType(trust.KeyTypeX5C))
}
Output: supports JWK: true supports X5C: true
type CachedDecision ¶
type CachedDecision struct {
Decision *TrustDecision
CachedAt time.Time
ExpiresAt time.Time
}
CachedDecision wraps a TrustDecision with cache metadata.
type CachingTrustEvaluator ¶
type CachingTrustEvaluator struct {
// contains filtered or unexported fields
}
CachingTrustEvaluator wraps a TrustEvaluator with caching.
func NewCachingTrustEvaluator ¶
func NewCachingTrustEvaluator(evaluator TrustEvaluator, config TrustCacheConfig) *CachingTrustEvaluator
NewCachingTrustEvaluator creates a caching wrapper around a TrustEvaluator.
func (*CachingTrustEvaluator) Cache ¶
func (c *CachingTrustEvaluator) Cache() *TrustCache
Cache returns the underlying cache for advanced operations.
func (*CachingTrustEvaluator) Clear ¶
func (c *CachingTrustEvaluator) Clear()
Clear removes all entries from the cache.
func (*CachingTrustEvaluator) Evaluate ¶
func (c *CachingTrustEvaluator) Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
Evaluate checks the cache first, then delegates to the wrapped evaluator.
func (*CachingTrustEvaluator) Invalidate ¶
func (c *CachingTrustEvaluator) Invalidate(req *EvaluationRequest)
Invalidate removes an entry from the cache.
func (*CachingTrustEvaluator) Stop ¶
func (c *CachingTrustEvaluator) Stop()
Stop stops the cache's automatic expiration.
func (*CachingTrustEvaluator) SupportsKeyType ¶
func (c *CachingTrustEvaluator) SupportsKeyType(kt KeyType) bool
SupportsKeyType delegates to the wrapped evaluator.
type CombinedTrustService ¶
type CombinedTrustService interface {
TrustEvaluator
KeyResolver
}
CombinedTrustService combines evaluation and resolution capabilities. This is the full interface for trust management across all credential formats.
type CompositeEvaluator ¶
type CompositeEvaluator struct {
// contains filtered or unexported fields
}
CompositeEvaluator combines multiple TrustEvaluators with configurable strategy.
func NewCompositeEvaluator ¶
func NewCompositeEvaluator(strategy CompositeStrategy, evaluators ...TrustEvaluator) *CompositeEvaluator
NewCompositeEvaluator creates a composite evaluator with the given strategy.
Example ¶
package main
import (
"context"
"fmt"
"github.com/SUNET/vc/pkg/trust"
)
func main() {
ctx := context.Background()
// Create a composite evaluator with two AllowAll evaluators using FirstSuccess strategy
eval1 := trust.NewAllowAllEvaluator()
eval2 := trust.NewAllowAllEvaluator()
composite := trust.NewCompositeEvaluator(trust.StrategyFirstSuccess, eval1, eval2)
req := trust.NewEvaluationRequest("https://issuer.example.com", trust.KeyTypeJWK, nil)
decision, err := composite.Evaluate(ctx, req)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("trusted:", decision.Trusted)
fmt.Println("supports JWK:", composite.SupportsKeyType(trust.KeyTypeJWK))
}
Output: trusted: true supports JWK: true
func (*CompositeEvaluator) AddEvaluator ¶
func (c *CompositeEvaluator) AddEvaluator(eval TrustEvaluator)
AddEvaluator adds an evaluator to the composite.
func (*CompositeEvaluator) Evaluate ¶
func (c *CompositeEvaluator) Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
Evaluate implements TrustEvaluator.
func (*CompositeEvaluator) SupportsKeyType ¶
func (c *CompositeEvaluator) SupportsKeyType(kt KeyType) bool
SupportsKeyType returns true if any evaluator supports the given key type.
type CompositeStrategy ¶
type CompositeStrategy int
CompositeStrategy determines how multiple evaluators are combined.
const ( // StrategyFirstSuccess returns success on the first positive decision. // This is useful for "any trust source" scenarios. StrategyFirstSuccess CompositeStrategy = iota // StrategyAllMustSucceed requires all evaluators to return a positive decision. // This is useful for "all trust sources must agree" scenarios. StrategyAllMustSucceed // StrategyFallback tries evaluators in order, returning the first non-error result. // This is useful for "try local first, then remote" scenarios. StrategyFallback )
type EvaluationRequest ¶
type EvaluationRequest struct {
trustapi.EvaluationRequest
}
EvaluationRequest contains the parameters for a trust evaluation. This embeds trustapi.EvaluationRequest and adds vc-specific methods.
func NewEvaluationRequest ¶
func NewEvaluationRequest(subjectID string, keyType KeyType, key any) *EvaluationRequest
NewEvaluationRequest creates a new EvaluationRequest with the given parameters. This is a convenience constructor.
Example ¶
package main
import (
"fmt"
"github.com/SUNET/vc/pkg/trust"
)
func main() {
req := trust.NewEvaluationRequest(
"https://issuer.example.com",
trust.KeyTypeJWK,
nil,
)
fmt.Println("subject:", req.SubjectID)
fmt.Println("key type:", req.KeyType)
}
Output: subject: https://issuer.example.com key type: jwk
func (*EvaluationRequest) GetEffectiveAction ¶
func (r *EvaluationRequest) GetEffectiveAction() string
GetEffectiveAction returns the action name to use for policy routing. Priority: 1. Explicit Action field, 2. Composed from Role + CredentialType/DocType, 3. Role alone
This is vc-specific logic that maps credential types to go-trust policy names.
Example ¶
package main
import (
"fmt"
"github.com/SUNET/vc/pkg/trust"
)
func main() {
// With explicit role set
req := trust.NewEvaluationRequest("https://issuer.example.com", trust.KeyTypeJWK, nil)
req.Role = trust.RoleIssuer
req.CredentialType = "PID"
fmt.Println("PID issuer action:", req.GetEffectiveAction())
// With a verifier role
req2 := trust.NewEvaluationRequest("https://verifier.example.com", trust.KeyTypeJWK, nil)
req2.Role = trust.RoleVerifier
fmt.Println("verifier action:", req2.GetEffectiveAction())
}
Output: PID issuer action: pid-provider verifier action: credential-verifier
type GoTrustEvaluator ¶
type GoTrustEvaluator struct {
// contains filtered or unexported fields
}
GoTrustEvaluator implements TrustEvaluator using go-trust AuthZEN client. It can validate both JWK and x5c key types against a Policy Decision Point.
func NewGoTrustEvaluator ¶
func NewGoTrustEvaluator(pdpURL string) *GoTrustEvaluator
NewGoTrustEvaluator creates a trust evaluator using go-trust with a known PDP URL.
func NewGoTrustEvaluatorWithClient ¶
func NewGoTrustEvaluatorWithClient(client *authzenclient.Client) *GoTrustEvaluator
NewGoTrustEvaluatorWithClient creates a trust evaluator with a pre-configured client.
func NewGoTrustEvaluatorWithDiscovery ¶
func NewGoTrustEvaluatorWithDiscovery(ctx context.Context, baseURL string) (*GoTrustEvaluator, error)
NewGoTrustEvaluatorWithDiscovery creates a trust evaluator using AuthZEN discovery.
func (*GoTrustEvaluator) Evaluate ¶
func (e *GoTrustEvaluator) Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
Evaluate implements TrustEvaluator.
func (*GoTrustEvaluator) GetClient ¶
func (e *GoTrustEvaluator) GetClient() *authzenclient.Client
GetClient returns the underlying AuthZEN client for advanced usage.
func (*GoTrustEvaluator) ResolveKey ¶
func (e *GoTrustEvaluator) ResolveKey(ctx context.Context, verificationMethod string) (crypto.PublicKey, error)
ResolveKey implements KeyResolver for DID-based resolution.
func (*GoTrustEvaluator) SupportsKeyType ¶
func (e *GoTrustEvaluator) SupportsKeyType(kt KeyType) bool
SupportsKeyType implements TrustEvaluator.
type JWKSKeyResolver ¶
type JWKSKeyResolver struct {
// contains filtered or unexported fields
}
JWKSKeyResolver resolves issuer public keys using a multi-endpoint discovery chain per SD-JWT VC §5.3 with fallbacks for maximum interoperability:
- .well-known/jwt-vc-issuer → inline jwks or jwks_uri (SD-JWT VC §5.3 primary)
- .well-known/openid-credential-issuer → authorization_servers → AS metadata → jwks_uri
- .well-known/openid-configuration → jwks_uri (OIDC Discovery)
- .well-known/oauth-authorization-server → jwks_uri (RFC 8414)
Resolved JWKS are cached per issuer URL. Keys are matched by kid.
func NewJWKSKeyResolver ¶
func NewJWKSKeyResolver(config JWKSResolverConfig) *JWKSKeyResolver
NewJWKSKeyResolver creates a new resolver for SD-JWT VC issuer key resolution. The parseJWK function must be provided to convert JWK maps to crypto.PublicKey (this avoids coupling pkg/trust to pkg/jose).
func (*JWKSKeyResolver) InvalidateIssuer ¶
func (r *JWKSKeyResolver) InvalidateIssuer(issuerURL string)
InvalidateIssuer removes a cached JWKS for a specific issuer. Useful when key rotation is detected (e.g., kid not found in cached JWKS).
func (*JWKSKeyResolver) Len ¶
func (r *JWKSKeyResolver) Len() int
Len returns the number of issuers currently cached.
func (*JWKSKeyResolver) ResolveKeyByKID ¶
func (r *JWKSKeyResolver) ResolveKeyByKID(ctx context.Context, issuerURL, kid string) (crypto.PublicKey, map[string]any, error)
ResolveKeyByKID resolves the public key for the given issuer and kid. Returns the public key and the JWK map (for trust evaluation).
Per SD-JWT VC §5.3, the metadata is fetched from {issuer}/.well-known/jwt-vc-issuer. Resolved JWKS are cached per issuer URL.
func (*JWKSKeyResolver) Stop ¶
func (r *JWKSKeyResolver) Stop()
Stop stops the cache's automatic expiration goroutine.
type JWKSResolverConfig ¶
type JWKSResolverConfig struct {
// HTTPClient is the HTTP client used for fetching metadata and JWKS.
// If nil, a default client with 30s timeout is used.
HTTPClient *http.Client
// CacheTTL is the time-to-live for cached JWKS entries per issuer.
// Default: 5 minutes.
CacheTTL time.Duration
// MaxCapacity is the maximum number of issuers to cache.
// Default: 100.
MaxCapacity uint64
// ParseJWKToPublicKey converts a JWK map to a crypto.PublicKey.
// If nil, a default implementation using lestrrat-go/jwx is expected
// to be injected by the caller (avoids coupling pkg/trust to pkg/jose).
ParseJWKToPublicKey func(jwkData any) (crypto.PublicKey, error)
}
JWKSResolverConfig contains configuration for the JWKSKeyResolver.
type KeyResolver ¶
type KeyResolver interface {
// ResolveKey retrieves the public key for the given verification method.
ResolveKey(ctx context.Context, verificationMethod string) (crypto.PublicKey, error)
}
KeyResolver resolves public keys from identifiers. This is used when the key needs to be fetched (DID-based credentials).
type LocalTrustConfig
deprecated
type LocalTrustConfig struct {
// TrustedRoots are the trusted root certificates.
TrustedRoots []*x509.Certificate
// AllowedRoles limits which roles are accepted. Nil means all roles.
AllowedRoles []string
// Clock is used for time-based validation. If nil, time.Now() is used.
Clock func() time.Time
}
LocalTrustConfig configures a LocalTrustEvaluator.
Deprecated: See LocalTrustEvaluator deprecation notice.
type LocalTrustEvaluator
deprecated
type LocalTrustEvaluator struct {
// contains filtered or unexported fields
}
LocalTrustEvaluator implements TrustEvaluator using local trust anchors.
Deprecated: LocalTrustEvaluator performs trust evaluation locally without consulting an AuthZEN PDP. For harmonized trust management across applications, use NewTrustEvaluatorFromConfig instead, which returns AllowAllEvaluator when no PDP URL is configured (returning trusted=true for all requests).
LocalTrustEvaluator is retained for backward compatibility and testing purposes.
func NewLocalTrustEvaluator ¶
func NewLocalTrustEvaluator(config LocalTrustConfig) *LocalTrustEvaluator
NewLocalTrustEvaluator creates a new local trust evaluator.
func (*LocalTrustEvaluator) AddTrustedRoot ¶
func (e *LocalTrustEvaluator) AddTrustedRoot(cert *x509.Certificate)
AddTrustedRoot adds a trusted root certificate.
func (*LocalTrustEvaluator) Evaluate ¶
func (e *LocalTrustEvaluator) Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
Evaluate implements TrustEvaluator.
func (*LocalTrustEvaluator) GetTrustedRoots ¶
func (e *LocalTrustEvaluator) GetTrustedRoots() []*x509.Certificate
GetTrustedRoots returns all trusted root certificates.
func (*LocalTrustEvaluator) SupportsKeyType ¶
func (e *LocalTrustEvaluator) SupportsKeyType(kt KeyType) bool
SupportsKeyType implements TrustEvaluator.
type TrustCache ¶
type TrustCache struct {
// contains filtered or unexported fields
}
TrustCache caches trust evaluation results to avoid repeated remote calls. It uses a composite key based on SubjectID, KeyType, Role, and key fingerprint.
func NewTrustCache ¶
func NewTrustCache(config TrustCacheConfig) *TrustCache
NewTrustCache creates and starts a new trust decision cache.
func (*TrustCache) Get ¶
func (c *TrustCache) Get(req *EvaluationRequest) *TrustDecision
Get retrieves a cached trust decision for the given request. Returns nil if not found or expired.
func (*TrustCache) Invalidate ¶
func (c *TrustCache) Invalidate(req *EvaluationRequest)
Invalidate removes a specific entry from the cache.
func (*TrustCache) InvalidateSubject ¶
func (c *TrustCache) InvalidateSubject(subjectID string)
InvalidateSubject removes all entries for a subject from the cache. This is useful when a subject's trust status is known to have changed.
func (*TrustCache) Len ¶
func (c *TrustCache) Len() int
Len returns the number of items currently in the cache.
func (*TrustCache) Set ¶
func (c *TrustCache) Set(req *EvaluationRequest, decision *TrustDecision)
Set stores a trust decision in the cache.
func (*TrustCache) SetWithTTL ¶
func (c *TrustCache) SetWithTTL(req *EvaluationRequest, decision *TrustDecision, ttl time.Duration)
SetWithTTL stores a trust decision with a custom TTL.
func (*TrustCache) Stop ¶
func (c *TrustCache) Stop()
Stop stops the cache's automatic expiration goroutine.
type TrustCacheConfig ¶
type TrustCacheConfig struct {
// TTL is the time-to-live for cached decisions. Default: 5 minutes.
TTL time.Duration
// MaxCapacity is the maximum number of items in the cache.
// If 0, no capacity limit is applied (items only expire by TTL).
MaxCapacity uint64
}
TrustCacheConfig contains configuration for the trust cache.
type TrustDecision ¶
type TrustDecision = trustapi.TrustDecision
TrustDecision represents the result of a trust evaluation.
type TrustEvaluator ¶
type TrustEvaluator interface {
// Evaluate checks if the given key is trusted for the specified subject and role.
// This is used when the key is already known (SD-JWT x5c, mDOC certificates).
Evaluate(ctx context.Context, req *EvaluationRequest) (*TrustDecision, error)
// SupportsKeyType returns true if this evaluator can handle the given key type.
SupportsKeyType(kt KeyType) bool
}
TrustEvaluator evaluates whether a name-to-key binding is trusted. This extends trustapi.TrustEvaluator to work with our EvaluationRequest.
func NewTrustEvaluatorFromConfig ¶
func NewTrustEvaluatorFromConfig(pdpURL string) TrustEvaluator
NewTrustEvaluatorFromConfig creates the appropriate TrustEvaluator based on configuration. If pdpURL is empty, returns an AllowAllEvaluator (trusted=true for all requests). If pdpURL is set, returns a GoTrustEvaluator that queries the PDP for trust decisions.
This provides harmonized trust management across applications:
- Empty PDP URL: "allow all" mode - resolved keys are always considered trusted
- Non-empty PDP URL: "default deny" mode - trust decisions require PDP approval
Example ¶
package main
import (
"fmt"
"github.com/SUNET/vc/pkg/trust"
)
func main() {
// Empty PDP URL returns an AllowAll evaluator
evaluator := trust.NewTrustEvaluatorFromConfig("")
fmt.Printf("%T\n", evaluator)
}
Output: *trust.AllowAllEvaluator
type TrustOptions ¶
type TrustOptions = trustapi.TrustOptions
TrustOptions contains additional options for trust evaluation.
type X5CCertChain ¶
type X5CCertChain = trustapi.X5CCertChain
X5CCertChain is a helper type for x5c certificate chains.