rpcert

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 21 Imported by: 0

README

go-eudi-rpcert

Regulatory identity for EUDI Wallet relying parties:

  • WRPAC — access-certificate profile checks (ETSI TS 119 411-8 V1.1.1: NCP/QCP-n/l-eudiwrp policy OIDs, contact SAN, KU/EKU, entitlement OIDs) and chain validation against AccessCA trust anchors.
  • WRPRC — registration certificates as JWT (JOSE typ rc-wrp+jwt) or CWT (COSE typ label-16 media type application/rc-wrp+cwt) per ETSI TS 119 475 V1.2.1 §5.2: issuer signature via WRPRCIssuer anchors, validity window (exp ≤ iat + 12 months), Annex A.2 entitlements, registered credential/claim extraction for scope checks.
  • RegistrationRef — the RPRC_19a registration reference (client name, unique ID, registry URI, intended-use identifier) always embedded in authorization requests.
  • ts5 — data model + typed client for the TS5 v1.3 Registrar API (GET /wrp, GET /wrp/{identifier}, GET /wrp/check-intended-use), JWS-signed responses, cursor pagination, per-registry key pinning.

Framework-free: injectable HTTP doer and clock, typed errors, no logging. All JOSE/COSE/X.509 via github.com/gmb-eudi/go-eudi-crypto; trust anchors only via github.com/gmb-eudi/go-eudi-trust.

Status: pre-v1 (not yet tagged/published — CI resolves sibling gmb-eudi modules once they are). Functionally, WP-07 is complete (T-07.1–T-07.9):

  • ts5 data model — golden-decode + schema-drift tests + fuzz target (T-07.1).
  • LoadWRPAC profile checks: policy OID, contact SAN, KU/EKU, Annex A.2 entitlement extraction, plus the internal/testpki synthetic CA builder reused by every later task's tests (T-07.2).
  • WRPAC.ValidateAgainst, chaining the WRPAC to AccessCA trust anchors via go-eudi-trust (granted + time-valid anchors only, issuing-territory- then-EU order, fail closed on cache expiry or no trust path — T-07.3).
  • ParseWRPRC + WRPRC.Verify for the JWT form (rc-wrp+jwt): parse-without-trust then verify-before-trust — chain to WRPRCIssuer anchors, issuer-signature check via go-eudi-crypto, validity window (exp ≤ iat + 12 months), Annex A.2 entitlement and wrprc policy-OID checks, plus registered credential/claim extraction for downstream scope checks (T-07.4).
  • The CWT form over COSE_Sign1 (RFC 8392/9052/9360) — the same ParseWRPRC/Verify matrix with hardened CBOR decoding and the COSE typ label 16 carried as the full media type application/rc-wrp+cwt (T-07.5).
  • RegistrationRef builder/serializer for the RPRC_19a registration reference, always embedded in built requests (T-07.6, pulled forward for WP-08).
  • RegistrarClient.GetWRP/GetWRPByID: TS5 v1.3 GET /wrp + GET /wrp/{identifier}, cursor-paginated, JWS-signed-response verified (per-registry key pinning, Provenance in the report), physicalAddress/ postalAddress rejected before it can enter a struct (T-07.7).
  • RegistrarClient.CheckIntendedUse (JWS-signed boolean) + IntendedUseActive/ IntendedUseStatus, the revokedAt monitoring predicate driving err:registrar:intended-use-revoked (T-07.8).
  • RegistrarClient.VerifyIntermediaryLinkage: confirms via the Registrar API that a client's usesIntermediary lists the operator by identifier — the only way to check this (TS5 v1.3 §2.1 Note; not present in any certificate) — superseding WRPAC.IsIntermediaryCapable as the authoritative check (T-07.9).

See SPECREFS.md for pinned spec versions.

Documentation

Overview

Package rpcert implements the regulatory-identity layer of an EUDI Wallet relying party (verifier): WRPAC access-certificate profile checks and trust-anchor validation (ETSI TS 119 411-8 V1.1.1), WRPRC registration certificates in JWT and CWT form (ETSI TS 119 475 V1.2.1), the RPRC_19a registration reference embedded in every authorization request, and a typed client for the TS5 v1.3 Registrar API (CIR (EU) 2025/848).

Dual path per ADR-0003: validate + attach WRPRCs where a Member State issues them; always embed the RegistrationRef; consume the Registrar API directly for onboarding verification, intended-use lifecycle monitoring and intermediary-linkage checks.

Index

Constants

View Source
const (
	EntitlementServiceProvider           = "https://uri.etsi.org/19475/Entitlement/Service_Provider"
	EntitlementQEAAProvider              = "https://uri.etsi.org/19475/Entitlement/QEAA_Provider"
	EntitlementNonQEAAProvider           = "https://uri.etsi.org/19475/Entitlement/Non_Q_EAA_Provider"
	EntitlementPubEAAProvider            = "https://uri.etsi.org/19475/Entitlement/PUB_EAA_Provider"
	EntitlementPIDProvider               = "https://uri.etsi.org/19475/Entitlement/PID_Provider"
	EntitlementQCertESealProvider        = "https://uri.etsi.org/19475/Entitlement/QCert_for_ESeal_Provider"
	EntitlementQCertESigProvider         = "https://uri.etsi.org/19475/Entitlement/QCert_for_ESig_Provider"
	EntitlementRQSealCDsProvider         = "https://uri.etsi.org/19475/Entitlement/rQSealCDs_Provider"
	EntitlementRQSigCDsProvider          = "https://uri.etsi.org/19475/Entitlement/rQSigCDs_Provider"
	EntitlementESigESealCreationProvider = "https://uri.etsi.org/19475/Entitlement/ESig_ESeal_Creation_Provider"
)

Entitlement URIs — ETSI TS 119 475 V1.2.1 Annex A.2 (exhaustive; also the vocabulary of TS5 v1.3 `entitlements`).

View Source
const (
	FormatJWT = "jwt"
	FormatCWT = "cwt"
)

WRPRC serialization formats (WP-07 README public interface).

View Source
const (
	CredentialFormatSDJWTVC = "dc+sd-jwt" //nolint:gosec // G101: OpenID4VP data-format identifier, not a credential (name matches gosec's "cred" heuristic)
	CredentialFormatMdoc    = "mso_mdoc"
)

Credential format identifiers used in WRPRC/TS5 credential entries — OpenID4VP 1.0 Annex B format ids (data formats, not crypto algorithms; hard rule 4 concerns algorithms only).

View Source
const WRPRCPolicyOID = "0.4.0.19475.3.1"

WRPRCPolicyOID — ETSI TS 119 475 §6.1.3: itu-t(0) identified-organization(4) etsi(0) eudiwrpa(19475) policy-identifiers(3) wrprc(1). policy_id must reference it (OVR-6.1.3-01/-02).

Variables

View Source
var (
	ErrMalformed = errors.New("rpcert: malformed input")

	// WRPAC profile checks (ETSI TS 119 411-8 §6.6.1 / TS 119 475 Annex A)
	ErrChainEmpty         = errors.New("rpcert: certificate chain is empty")
	ErrPolicyOID          = errors.New("rpcert: no eudiwrp certificate policy OID (TS 119 411-8 GEN-6.6.1-03)")
	ErrContactSAN         = errors.New("rpcert: no contact SAN - URI, email or telephone otherName (TS 119 411-8 GEN-6.6.1-07)")
	ErrKeyUsage           = errors.New("rpcert: keyUsage lacks digitalSignature (WP-07 Decision 3)")
	ErrExtKeyUsage        = errors.New("rpcert: extended key usage restricts wallet-facing use (WP-07 Decision 3)")
	ErrUnknownEntitlement = errors.New("rpcert: unknown OID under id-etsi-wrpa-entitlement arc (TS 119 475 Annex A.2)")

	// Trust-anchor validation (fail closed — CLAUDE.md rules 6/7)
	ErrNoTrustPath = errors.New("rpcert: no chain to a valid trust anchor")

	// WRPRC (ETSI TS 119 475 §5.2 / §6.1.3)
	ErrWRPRCFormat  = errors.New("rpcert: WRPRC is neither a compact JWS nor a COSE_Sign1 (GEN-5.2.1-01)")
	ErrWRPRCType    = errors.New("rpcert: WRPRC typ header mismatch (GEN-5.2.2-01 / GEN-5.2.3-01)")
	ErrClaimMissing = errors.New("rpcert: required WRPRC claim missing (GEN-5.2.4-01/-02)")
	ErrSignature    = errors.New("rpcert: WRPRC signature verification failed")
	ErrExpired      = errors.New("rpcert: WRPRC expired")
	ErrValidity     = errors.New("rpcert: WRPRC validity window violated (GEN-5.2.4-08)")
	ErrEntitlement  = errors.New("rpcert: WRPRC lacks a TS 119 475 Annex A.2 entitlement (GEN-5.2.4-03)")
	ErrPolicyID     = errors.New("rpcert: WRPRC policy_id lacks the wrprc policy OID (TS 119 475 OVR-6.1.3-01)")

	// RegistrationRef (ARF RPRC_19a / ADR-0003 decision 2)
	ErrRegistrationRef = errors.New("rpcert: incomplete registration reference")

	// TS5 Registrar API client
	ErrNoRegistrarKey       = errors.New("rpcert: no verification key configured for registry")
	ErrResponseSignature    = errors.New("rpcert: registrar response JWS verification failed")
	ErrStaleResponse        = errors.New("rpcert: registrar response too old")
	ErrRegistrarStatus      = errors.New("rpcert: registrar returned an error status")
	ErrRegistrarUnavailable = errors.New("rpcert: registrar unreachable")
	ErrWRPNotFound          = errors.New("rpcert: wallet-relying party not found in registry")
	ErrPagination           = errors.New("rpcert: inconsistent pagination in registrar response")
	ErrTooManyPages         = errors.New("rpcert: registrar pagination exceeded page cap")
	ErrIntendedUseNotFound  = errors.New("rpcert: intended use not found on registered WRP")
	ErrIntendedUseRevoked   = errors.New("rpcert: intended use revoked or not yet active")
	ErrNotLinked            = errors.New("rpcert: client does not list operator as intermediary (TS5 v1.3 usesIntermediary)")
)

Sentinel errors. Services map them to err:domain:reason problem codes (docs/conventions.md): ErrIntendedUseRevoked → err:registrar:intended-use-revoked; ErrRegistrarUnavailable/-Status → err:registrar:unavailable; ErrWRPNotFound/ErrNotLinked → err:client:not-registered; ErrNoTrustPath (or a propagated trust.ErrCacheExpired) → err:trust:anchor-unavailable. No HTTP semantics here (ADR-0004); no attribute values in messages, ever (hard rule 3). NOTE: this var block is the complete sentinel set for the whole library. WP-07 Tasks 4/5/9 (WRPRC/registrar linkage) consume the sentinels already declared below — do not redefine ErrRegistrationRef or replace this file.

Functions

func IntendedUseActive

func IntendedUseActive(iu ts5.IntendedUse, at time.Time) (bool, error)

IntendedUseActive evaluates the intended-use lifecycle window (ETSI TS 119 475 / TS5 IntendedUse): active iff createdAt <= at and (revokedAt absent OR at < revokedAt-day-midnight). Revocation is effective from 00:00:00 UTC of revokedAt (WP-07 Decision 10 — fail-closed reading of "end date for the validity"): the entire revokedAt calendar day already counts as revoked. A revoked/not-yet-active use returns (false, ErrIntendedUseRevoked); malformed dates — including an empty createdAt — fail closed with ErrMalformed (never silently treated as active; RevokedAt stays optional and absent-means-not-revoked).

Types

type Doer

type Doer interface {
	Do(req *http.Request) (*http.Response, error)
}

Doer is the injected HTTP client (ADR-0004: no framework, no global http.DefaultClient). Services wire the platform-kit correlation-propagating client here; tests wire httptest.Server.Client().

type IntendedUseQuery

type IntendedUseQuery struct {
	RPIdentifier          string // rpidentifier (required)
	IntendedUseIdentifier string // intendeduseidentifier
	CredentialFormat      string // credentialformat
	ClaimPath             string // claimpath
	CredentialMeta        string // credentialmeta
	PolicyURL             string // policyurl
}

IntendedUseQuery mirrors GET /wrp/check-intended-use (TS5 v1.3 OpenAPI): rpidentifier is mandatory; the other five are optional narrowing filters.

type IntermediaryRef

type IntermediaryRef struct {
	Subject string
	Name    string
}

IntermediaryRef identifies the intermediary the WRP acts through (TS 119 475 Table 10 `intermediary`; Annex C uses subfield "name", Table 10 says "sname" — both accepted, see README corrections).

type KeyProvenance

type KeyProvenance string

KeyProvenance records how a registrar verification key was obtained, for the verification report's provenance (WP-07 Decision 8; README Decisions).

const (
	// ProvenancePinned — key came from explicit per-registry config
	// (until MS registrars publish keys uniformly).
	ProvenancePinned KeyProvenance = "pinned"
	// ProvenanceTrustService — key resolved via the trust service
	// wrprc_issuer/registrar metadata (wired in WP-09).
	ProvenanceTrustService KeyProvenance = "trust-service"
)

type LangValue

type LangValue struct {
	Lang  string `json:"lang"`
	Value string `json:"value"`
}

LangValue is a TS 119 475 §5.2.4 localized string ({lang, value} — note: the WRPRC uses "value" where TS5's MultiLangString uses "content").

type LinkageResult

type LinkageResult struct {
	Linked     bool
	OperatorID string
	ClientID   string
	Provenance Provenance
}

LinkageResult reports whether a client registers the operator as one of its intermediaries (TS5 v1.3 §2.1 usesIntermediary). Provenance carries the registry + key trust basis for the verification report.

type PinnedRegistrarKeys

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

PinnedRegistrarKeys is the config-driven pinning implementation: one public key per registry base URL (TS5 §3.2.2 leaves key discovery to deployment — see WP-07 README Decisions).

func NewPinnedRegistrarKeys

func NewPinnedRegistrarKeys(keys map[string]crypto.PublicKey) *PinnedRegistrarKeys

NewPinnedRegistrarKeys copies the provided registry-URI → key map.

func (*PinnedRegistrarKeys) KeyFor

func (p *PinnedRegistrarKeys) KeyFor(registryURI, _ string) (crypto.PublicKey, KeyProvenance, error)

KeyFor returns the pinned key for registryURI (kid ignored — one key per registry in the pinned model).

type Provenance

type Provenance struct {
	RegistryURI   string
	KeyProvenance KeyProvenance
}

Provenance is attached to the verification report so an operator can see which registry answered and how its signing key was trusted.

type RegisteredCredential

type RegisteredCredential struct {
	Format         string
	DoctypesOrVCTs []string
	AllClaims      bool
	Claims         []ts5.ClaimPath
}

RegisteredCredential mirrors one WRPRC credentials/provides_attestations entry (TS 119 475 Tables 8/9). It maps 1:1 onto dcql.RegisteredCredential (WP-05) for WithinScope checks; AllClaims=true when the claim list is absent (WP-07 Decision 12, OID4VP §6.1 semantics).

type RegistrarClient

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

RegistrarClient is a typed TS5 v1.3 Registrar API client with JWS response verification. Framework-free: injected Doer + clock (ADR-0004).

func NewRegistrarClient

func NewRegistrarClient(doer Doer, keys RegistrarKeys, opts ...RegistrarOption) *RegistrarClient

NewRegistrarClient builds the client.

func (*RegistrarClient) CheckIntendedUse

func (c *RegistrarClient) CheckIntendedUse(ctx context.Context, registryURI string, q IntendedUseQuery) (bool, error)

CheckIntendedUse calls GET /wrp/check-intended-use and returns the JWS-signed boolean result (TS5 v1.3 §3.2.2: "JWS-signed boolean TRUE or FALSE response, based on if the queried parameter set can be found in the Registrar's Intended use information"). Verification reuses the same fetch/verifyResponse wiring as GetWRP/GetWRPByID (T-07.7) — one trust decision path for every registrar endpoint (hard rule 4: alg selection stays inside eudicrypto.VerifyJWS via c.fetch).

func (*RegistrarClient) GetWRP

func (c *RegistrarClient) GetWRP(ctx context.Context, registryURI string, q WRPQuery) ([]ts5.WalletRelyingParty, error)

GetWRP queries GET /wrp and joins all cursor pages (TS5 v1.3 §3.2.2).

func (*RegistrarClient) GetWRPByID

func (c *RegistrarClient) GetWRPByID(ctx context.Context, registryURI, identifier string) (*ts5.WalletRelyingParty, error)

GetWRPByID queries GET /wrp/{identifier} (TS5 v1.3 §3.2.2).

func (*RegistrarClient) IntendedUseStatus

func (c *RegistrarClient) IntendedUseStatus(ctx context.Context, registryURI, rpIdentifier, intendedUseID string) error

IntendedUseStatus resolves the WRP via GET /wrp/{identifier}, locates the named intended use and evaluates its lifecycle. Returns nil when active, ErrIntendedUseRevoked when revoked/not-yet-active (-> err:registrar:intended-use-revoked), ErrIntendedUseNotFound when the id is absent. Used by the portal's periodic monitoring (ADR-0003 decision 3).

func (*RegistrarClient) LastProvenance

func (c *RegistrarClient) LastProvenance() Provenance

LastProvenance returns the provenance of the most recent verified response (for the report). Safe for concurrent use.

func (*RegistrarClient) VerifyIntermediaryLinkage

func (c *RegistrarClient) VerifyIntermediaryLinkage(ctx context.Context, registryURI, clientIdentifier, operatorIdentifier string) (LinkageResult, error)

VerifyIntermediaryLinkage confirms, via the Registrar API, that the client's usesIntermediary array lists the operator by identifier. Per TS5 v1.3 §2.1 (Note: "isIntermediary … available for verification only via the Registrar's API") this relationship is NOT in any certificate, so this API call is the authoritative check (ADR-0003 decision 3; supersedes WRPAC.IsIntermediaryCapable — WP-07 Decision 2). Fail closed: ErrNotLinked when the operator is absent, ErrWRPNotFound when the client is unknown.

type RegistrarKeys

type RegistrarKeys interface {
	KeyFor(registryURI, kid string) (crypto.PublicKey, KeyProvenance, error)
}

RegistrarKeys resolves a registrar's JWS verification key. kid is the JWS "kid" header (may be empty when a registry publishes a single key).

type RegistrarOption

type RegistrarOption func(*RegistrarClient)

RegistrarOption configures a RegistrarClient.

func WithClock

func WithClock(clock func() time.Time) RegistrarOption

WithClock injects the clock (docs/conventions.md time rule).

func WithMaxPages

func WithMaxPages(n int) RegistrarOption

WithMaxPages caps cursor pagination (fail closed against a runaway registrar).

func WithMaxResponseAge

func WithMaxResponseAge(d time.Duration) RegistrarOption

WithMaxResponseAge sets the freshness window for the response iat (WP-07 Decision 7).

type RegistrationRef

type RegistrationRef struct {
	ClientName    string
	ClientID      string
	RegistryURI   string
	IntendedUseID string
}

RegistrationRef is the RPRC_19a registration reference embedded in EVERY authorization request (ADR-0003 decision 2) — with or without an attached WRPRC — so wallets can query the registrar themselves: the client's display name, its registered unique identifier, the national registry API URL (CIR (EU) 2025/848 Art. 3(5)) and the intended-use identifier.

func NewRegistrationRef

func NewRegistrationRef(clientName, clientID, registryURI, intendedUseID string) (RegistrationRef, error)

NewRegistrationRef validates and builds the reference. All four fields are required (ADR-0003 names all four); an incomplete reference cannot be built, so WP-08 can guarantee "always present" structurally.

func (RegistrationRef) Claims

func (r RegistrationRef) Claims() (map[string]any, error)

Claims returns the reference as request-object claim values for WP-08's request builder (RPRC_19a extension).

func (RegistrationRef) MarshalJSON

func (r RegistrationRef) MarshalJSON() ([]byte, error)

MarshalJSON serializes the reference; an incomplete reference fails, so a half-built RegistrationRef can never reach a request object.

func (*RegistrationRef) UnmarshalJSON

func (r *RegistrationRef) UnmarshalJSON(data []byte) error

UnmarshalJSON parses the wire shape written by MarshalJSON and validates completeness, so a corrupted or truncated stored value fails loudly rather than silently decoding to a zero-value reference (hard rule 7, fail closed) — MarshalJSON alone made RegistrationRef write-only under encoding/json (the default field-name-matching reflection cannot map "registry_uri" etc. back onto ClientName/ClientID/RegistryURI/ IntendedUseID), which broke WP-08's Session/SessionStore JSON round-trip contract (Session embeds RegistrationRef directly).

func (RegistrationRef) Validate

func (r RegistrationRef) Validate() error

Validate re-checks completeness (WP-08 calls it before request build).

type StatusRef

type StatusRef struct {
	Index int64  `json:"idx"`
	URI   string `json:"uri"`
}

StatusRef points into the issuer's Token Status List (TS 119 475 GEN-6.2.6.1-04: status.status_list.{idx,uri}). Checked by the service via go-statuslist (WP-04) — see WP-07 Decision 11.

type SupervisoryContact

type SupervisoryContact struct {
	Email string `json:"email,omitempty"`
	Phone string `json:"phone,omitempty"`
	URI   string `json:"uri,omitempty"`
}

SupervisoryContact — TS 119 475 Table 7 supervisory_authority.

type WRPAC

type WRPAC struct {
	Chain                 []*x509.Certificate
	Entitlements          []string
	IsIntermediaryCapable bool
}

WRPAC is the operator's (or an intermediary's) wallet-relying party access certificate (CIR (EU) 2025/848 Art. 7 / Annex IV).

func LoadWRPAC

func LoadWRPAC(chain [][]byte) (*WRPAC, error)

LoadWRPAC parses a WRPAC chain (leaf first; each element PEM or DER) and runs the TS 119 411-8 profile checks. Each broken element yields its own sentinel (T-07.2 acceptance):

  • certificatePolicies includes an eudiwrp policy OID (TS 119 411-8 GEN-6.6.1-03, OIDs from §5.3) → ErrPolicyOID
  • contact SAN: URI / rfc822Name / telephone otherName (TS 119 411-8 GEN-6.6.1-07 [CHOICE]) → ErrContactSAN
  • keyUsage includes digitalSignature (WP-07 Decision 3: the WRPAC signs OID4VP request objects) → ErrKeyUsage
  • EKU absent, anyExtendedKeyUsage or clientAuth (WP-07 Decision 3) → ErrExtKeyUsage
  • entitlement OIDs under 0.4.0.19475.1 map to Annex A.2 URIs; unknown arc children rejected (fail closed) → ErrUnknownEntitlement

func (*WRPAC) ValidateAgainst

func (w *WRPAC) ValidateAgainst(src trust.AnchorSource) error

ValidateAgainst chains the WRPAC to AccessCA trust anchors from the trust service (CLAUDE.md rule 6; CIR (EU) 2025/848 Art. 7 — access-certificate providers operate under Member State supervision, their CAs are the AccessCA anchor set). Uses the package clock (clock.go).

type WRPQuery

type WRPQuery struct {
	Identifier            string
	LegalName             string
	TradeName             string
	Policy                string
	Entitlement           string
	CredentialMeta        string
	CredentialFormat      string
	UsesIntermediary      string
	IsIntermediary        *bool
	IntendedUseIdentifier string
	Limit                 int
}

WRPQuery mirrors the GET /wrp query parameters (TS5 v1.3 OpenAPI). Empty fields are omitted; IsIntermediary is a *bool so "unset" ≠ "false".

type WRPRC

type WRPRC struct {
	Raw    []byte
	Format string // FormatJWT | FormatCWT
	Chain  []*x509.Certificate

	Name                  string
	LegalName             string // sub_ln (legal person)
	GivenName             string // sub_gn (natural person)
	FamilyName            string // sub_fn (natural person)
	Subject               string // sub — registered WRP identifier (GEN-5.2.4-02)
	Country               string
	RegistryURI           string
	SrvDescription        [][]LangValue
	Entitlements          []string
	PrivacyPolicy         string
	InfoURI               string
	SupportURI            string
	SupervisoryAuthority  SupervisoryContact
	PolicyIDs             []string
	CertificatePolicy     string
	PublicBody            bool
	IssuedAt              time.Time
	ExpiresAt             time.Time // zero = no exp claim
	Status                *StatusRef
	Purpose               []LangValue
	IntendedUseID         string
	RegisteredCredentials []RegisteredCredential
	ProvidesAttestations  []RegisteredCredential
	Intermediary          *IntermediaryRef
}

WRPRC is a parsed wallet-relying party registration certificate (ETSI TS 119 475 §5.2; CIR (EU) 2025/848 Art. 8 / Annex V).

func ParseWRPRC

func ParseWRPRC(raw []byte) (*WRPRC, error)

ParseWRPRC parses a WRPRC in JWT or CWT form WITHOUT verifying its signature — call (*WRPRC).Verify next (TS 119 475 GEN-5.2.1-01: "signed JSON Web Token (JWT) or CBOR Web Token (CWT)").

func (*WRPRC) Verify

func (r *WRPRC) Verify(src trust.AnchorSource, clock func() time.Time) error

Verify validates the WRPRC end-to-end, fail closed:

  1. signer chain (x5c/x5chain, leaf first) to WRPRCIssuer anchors — CLAUDE.md rule 6; ETSI TS 119 475 GEN-5.2.1-03 (the provider's signing certificate is published on a trusted list)
  2. token signature with the leaf key via go-eudi-crypto — GEN-5.2.1-04 (JAdES B-B) / GEN-5.2.1-05 (COSE per RFC 9052/9360)
  3. validity window — GEN-5.2.4-01 iat, GEN-5.2.4-07/-08 exp ≤ iat+12mo
  4. entitlements include ≥1 Annex A.2 entitlement — GEN-5.2.4-03
  5. policy_id references the wrprc policy OID — OVR-6.1.3-01/-02

Verify-before-trust: no payload-derived field (validity, entitlements, policy_id, credential list) is acted upon until the chain (1) and the cryptographic signature (2) both pass — the extraction that ParseWRPRC performed is only trustworthy after this point.

Status-list state (status.status_list) is NOT checked here — services check it via go-statuslist (WP-04); Verify only surfaces StatusRef (WP-07 Decision 11).

Directories

Path Synopsis
internal
testpki
Package testpki generates the WP-07 test PKI at test runtime: an access-CA / WRPRC-issuer CA and end-entity certificates with every TS 119 411-8 profile knob the T-07.2 matrix mutates.
Package testpki generates the WP-07 test PKI at test runtime: an access-CA / WRPRC-issuer CA and end-entity certificates with every TS 119 411-8 profile knob the T-07.2 matrix mutates.
Package ts5 models the EC TS5 v1.3 "Common formats and API for Relying Party Registration information" data model (§2) and the JWS payload envelopes of its Registrar API (Annex A OpenAPI).
Package ts5 models the EC TS5 v1.3 "Common formats and API for Relying Party Registration information" data model (§2) and the JWS payload envelopes of its Registrar API (Annex A OpenAPI).

Jump to

Keyboard shortcuts

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