xades

package
v0.35.0 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

README

XAdES toolkit

Package auth/xades provides protocol-neutral XAdES signing and verification. It uses strict profiles and caller-owned trust services instead of resolving untrusted URIs or making network requests from the XML verifier.

Supported capabilities

  • XAdES Baseline-B generation with SigningCertificateV2
  • XAdES-EPES explicit signature policies
  • enveloped, enveloping, and detached packaging
  • RSA PKCS#1 v1.5, RSA-PSS, and ECDSA signatures
  • SHA-256, SHA-384, and SHA-512 safe suites
  • Exclusive Canonical XML 1.0 and Canonical XML 1.1
  • explicit X.509 trust roots, intermediates, key usages, and verification time
  • caller-provided revocation checks without implicit network access
  • RFC 3161 timestamp client and verifier boundaries for Baseline-T
  • validated certificate, OCSP, and CRL evidence containers for long-term validation
  • legacy SigningCertificate verification only when explicitly enabled

Archive timestamp renewal and automatic trust-service discovery are not implemented. Those functions require application-specific retention, trust, and network policy and should be layered on the interfaces in this package.

Baseline-B

identity, err := signing.NewIdentityPEM(certificatePEM, privateKeyPEM, password)
if err != nil {
    return err
}

signed, err := xades.SignEnveloped(document, identity, &xades.Options{
    Suite: xades.SuitePSSSHA256Exclusive,
})

New signatures use SigningCertificateV2. SignEnveloping embeds the signed XML in a ds:Object. SignDetached signs external XML but only records its URI; it does not dereference that URI.

Detached verification

Detached content must be supplied by an explicit resolver:

result, err := xades.VerifyWithOptions(ctx, signature, &xades.ValidationOptions{
    Resolver: xades.ResolverFunc(func(ctx context.Context, uri string) ([]byte, error) {
        return trustedDocumentStore.Load(ctx, uri)
    }),
})

The resolver should enforce its own URI allowlist, size limit, timeout, and authorization policy. Scy never falls back to HTTP, filesystem, or other URI resolution.

Certificate trust and revocation

Cryptographic signature validity and certificate trust are separate checks. Configure trust explicitly when trust is required:

result, err := xades.VerifyWithOptions(ctx, signed, &xades.ValidationOptions{
    Time: verificationTime,
    Trust: &xades.TrustPolicy{
        Roots:          roots,
        Intermediates:  intermediates,
        KeyUsages:      []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
        Revocation:     revocationChecker,
    },
})

UseSystemRoots must be enabled deliberately. A RevocationChecker receives the already constructed certificate path and can use stapled evidence, local caches, OCSP, or CRLs. The XML verifier itself never performs network I/O.

Signature policies

To create an EPES signature, hash the authoritative policy document with the selected suite and supply its identifier and digest. During verification, a PolicyResolver can provide the authoritative bytes; Scy compares their digest with the signed property.

Timestamps and long-term evidence

AddSignatureTimestamp adds an XAdES SignatureTimeStamp using a caller-owned TimestampClient. VerifyWithOptions requires a TimestampVerifier whenever a timestamp is present. The verifier is responsible for RFC 3161 token signature, policy, nonce, TSA chain, time, and message-imprint validation.

AddLongTermValidationEvidence only embeds material after an EvidenceValidator accepts it and requires a signature timestamp. Verification likewise rejects embedded evidence unless a validator is configured. This keeps OCSP, CRL, and trust-network policy outside XML parsing.

Verification safety

  • Only built-in AlgorithmSuite values or values returned by SafeSuite work.
  • Arbitrary transform and canonicalization URIs are rejected.
  • Signatures must contain exactly one data reference and one SignedProperties reference.
  • Same-document object IDs must resolve uniquely.
  • Detached references require an explicit resolver.
  • Embedded timestamps and long-term evidence require explicit validators.
  • Certificate pinning and certificate-path trust can be required independently.
  • Signed and detached XML inputs have default 32 MiB and 256-level depth limits; callers can lower them through signing and validation options.

Applications should generally lower these limits to match their document profile when XML can be supplied by untrusted parties.

Documentation

Overview

Package xades provides protocol-neutral XAdES signing and verification.

The package deliberately accepts only whitelisted SHA-2, RSA, RSA-PSS, ECDSA, and canonicalization suites. It supports structured enveloped, enveloping, and explicitly resolved detached signatures, and contains no protocol-specific transport or token behavior.

Index

Constants

View Source
const (
	CanonicalXML10Method      = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
	CanonicalXML11Method      = "http://www.w3.org/2006/12/xml-c14n11"
	ExclusiveCanonicalization = "http://www.w3.org/2001/10/xml-exc-c14n#"

	DigestMethodSHA384 = "http://www.w3.org/2001/04/xmldsig-more#sha384"
	DigestMethodSHA512 = "http://www.w3.org/2001/04/xmlenc#sha512"

	SignatureMethodRSA384   = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"
	SignatureMethodRSA512   = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
	SignatureMethodPSS256   = "http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1"
	SignatureMethodPSS384   = "http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1"
	SignatureMethodPSS512   = "http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1"
	SignatureMethodECDSA384 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"
	SignatureMethodECDSA512 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"
)
View Source
const (
	DefaultMaxDocumentBytes = 32 << 20
	DefaultMaxXMLDepth      = 256
)
View Source
const (
	DSNamespace              = "http://www.w3.org/2000/09/xmldsig#"
	XAdESNamespace           = "http://uri.etsi.org/01903/v1.3.2#"
	CanonicalizationMethod   = ExclusiveCanonicalization
	EnvelopedSignatureMethod = "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
	DigestMethodSHA256       = "http://www.w3.org/2001/04/xmlenc#sha256"
	SignatureMethodRSA256    = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
	SignatureMethodECDSA256  = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"
	SignedPropertiesType     = "http://uri.etsi.org/01903#SignedProperties"
)

Variables

Functions

func AddLongTermValidationEvidence

func AddLongTermValidationEvidence(ctx context.Context, signedXML []byte, evidence *ValidationEvidence, validator EvidenceValidator, at time.Time) ([]byte, error)

AddLongTermValidationEvidence embeds prevalidated certificate and revocation material. A signature timestamp and an EvidenceValidator are required.

func AddSignatureTimestamp

func AddSignatureTimestamp(ctx context.Context, signedXML []byte, client TimestampClient, hash crypto.Hash) ([]byte, error)

AddSignatureTimestamp upgrades a signed document with an XAdES signature timestamp. The supplied client must validate the TSA response before return.

func SignDetached

func SignDetached(document []byte, referenceURI string, identity *signing.Identity, options *Options) ([]byte, error)

SignDetached creates a detached signature over an XML document. referenceURI is metadata only during generation; SignDetached performs no network access.

func SignEnveloped

func SignEnveloped(document []byte, identity *signing.Identity, options *Options) ([]byte, error)

SignEnveloped adds an enveloped XAdES signature using a whitelisted suite.

func SignEnveloping

func SignEnveloping(document []byte, identity *signing.Identity, options *Options) ([]byte, error)

SignEnveloping creates a Signature document that contains the signed XML in a ds:Object. This mode never resolves external resources.

Types

type AlgorithmSuite

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

AlgorithmSuite is a closed, validated combination of XML canonicalization, digest, and signature algorithms. Construct suites with one of the exported constructors; its fields are intentionally private to prevent unsafe URIs.

func MustSafeSuite

func MustSafeSuite(hash crypto.Hash, canonicalization string, rsaPSS bool) AlgorithmSuite

func SafeSuite

func SafeSuite(hash crypto.Hash, canonicalization string, rsaPSS bool) (AlgorithmSuite, error)

SafeSuite returns a whitelisted suite. Supported hashes are SHA-256, SHA-384, and SHA-512. Canonicalization is limited to Exclusive C14N 1.0, Canonical XML 1.0, or Canonical XML 1.1.

func StandardSuites

func StandardSuites() []AlgorithmSuite

StandardSuites returns all suites accepted by default verification. The returned slice is a copy and can safely be modified by callers.

func (AlgorithmSuite) CanonicalizationMethod

func (s AlgorithmSuite) CanonicalizationMethod() string

func (AlgorithmSuite) DigestMethod

func (s AlgorithmSuite) DigestMethod() string

func (AlgorithmSuite) Hash

func (s AlgorithmSuite) Hash() crypto.Hash

func (AlgorithmSuite) Name

func (s AlgorithmSuite) Name() string

type EvidenceValidator

type EvidenceValidator interface {
	ValidateEvidence(ctx context.Context, evidence *ValidationEvidence, signingChain []*x509.Certificate, at time.Time) error
}

EvidenceValidator validates long-term evidence against the signing path. Implementations decide accepted OCSP/CRL policies and trust anchors.

type Options

type Options struct {
	SigningTime        time.Time
	SignatureID        string
	SignedPropertiesID string
	IncludeChain       bool
	Suite              AlgorithmSuite
	Packaging          Packaging
	ReferenceURI       string
	SignaturePolicy    *SignaturePolicy
	MaxDocumentBytes   int
	MaxXMLDepth        int
}

Options controls deterministic metadata in an XAdES signature. Empty IDs are generated with crypto/rand and an empty SigningTime uses time.Now().

type Packaging

type Packaging string
const (
	PackagingEnveloped  Packaging = "enveloped"
	PackagingEnveloping Packaging = "enveloping"
	PackagingDetached   Packaging = "detached"
)

type PolicyResolver

type PolicyResolver interface {
	ResolvePolicy(ctx context.Context, identifier string) ([]byte, error)
}

PolicyResolver supplies policy bytes for verification. Scy never resolves a policy identifier automatically.

type PolicyResolverFunc

type PolicyResolverFunc func(ctx context.Context, identifier string) ([]byte, error)

func (PolicyResolverFunc) ResolvePolicy

func (f PolicyResolverFunc) ResolvePolicy(ctx context.Context, identifier string) ([]byte, error)

type Resolver

type Resolver interface {
	Resolve(ctx context.Context, uri string) ([]byte, error)
}

Resolver supplies detached content. Scy never dereferences signature URIs itself; applications retain full control over filesystem and network access.

type ResolverFunc

type ResolverFunc func(ctx context.Context, uri string) ([]byte, error)

func (ResolverFunc) Resolve

func (f ResolverFunc) Resolve(ctx context.Context, uri string) ([]byte, error)

type Result

type Result struct {
	Certificate      *x509.Certificate
	SigningTime      time.Time
	SignatureID      string
	SignatureMethod  string
	Trust            *TrustResult
	Packaging        Packaging
	ReferenceURI     string
	TimestampTime    *time.Time
	SignaturePolicy  *SignaturePolicy
	LongTermEvidence *ValidationEvidence
}

Result is the verified identity and XAdES metadata.

func Verify

func Verify(document []byte, expectedCertificate *x509.Certificate, at time.Time) (*Result, error)

Verify verifies a modern signature without certificate-path trust. Use VerifyWithOptions to require trust, restrict algorithms, or allow legacy SigningCertificate properties.

func VerifyWithOptions

func VerifyWithOptions(ctx context.Context, document []byte, options *ValidationOptions) (*Result, error)

VerifyWithOptions verifies XMLDSig integrity, XAdES qualifying properties, optional certificate pinning, and optional certificate-path trust.

type RevocationChecker

type RevocationChecker interface {
	Check(ctx context.Context, certificate, issuer *x509.Certificate, at time.Time) error
}

RevocationChecker validates revocation status without giving the XML parser implicit network access. Implementations may use stapled OCSP responses, caller-managed caches, CRLs, or an explicitly configured network client.

type SignaturePolicy

type SignaturePolicy struct {
	Identifier  string
	Description string
	Digest      []byte
}

SignaturePolicy identifies and hashes an external signature policy for an XAdES-EPES signature. Digest must be computed using the signature suite hash.

type TimestampClient

type TimestampClient interface {
	Timestamp(ctx context.Context, imprint []byte, hash crypto.Hash) ([]byte, error)
}

TimestampClient obtains an RFC 3161 token for the supplied message imprint. Implementations own all TSA transport, authentication, and response checks.

type TimestampVerifier

type TimestampVerifier interface {
	VerifyTimestamp(ctx context.Context, token, imprint []byte, hash crypto.Hash, at time.Time) (time.Time, error)
}

TimestampVerifier validates an RFC 3161 token, including its signature, trust path, policy, nonce (when applicable), and message-imprint binding.

type TrustPolicy

type TrustPolicy struct {
	Roots          *x509.CertPool
	Intermediates  *x509.CertPool
	UseSystemRoots bool
	KeyUsages      []x509.ExtKeyUsage
	DNSName        string
	Revocation     RevocationChecker
}

TrustPolicy defines certificate-path validation independently of XMLDSig cryptographic validation. Roots must be supplied explicitly unless UseSystemRoots is set.

func (*TrustPolicy) Verify

func (p *TrustPolicy) Verify(ctx context.Context, leaf *x509.Certificate, embedded []*x509.Certificate, at time.Time) (*TrustResult, error)

type TrustResult

type TrustResult struct {
	Chains [][]*x509.Certificate
}

TrustResult contains the verified paths selected by crypto/x509.

type ValidationEvidence

type ValidationEvidence struct {
	Certificates  []*x509.Certificate
	OCSPResponses [][]byte
	CRLs          [][]byte
}

ValidationEvidence contains caller-acquired certificate and revocation material for long-term validation. Scy never fetches this material itself.

type ValidationOptions

type ValidationOptions struct {
	ExpectedCertificate           *x509.Certificate
	Time                          time.Time
	Trust                         *TrustPolicy
	AllowedSuites                 []AlgorithmSuite
	AllowLegacySigningCertificate bool
	Resolver                      Resolver
	TimestampVerifier             TimestampVerifier
	RequireTimestamp              bool
	PolicyResolver                PolicyResolver
	RequireSignaturePolicy        bool
	EvidenceValidator             EvidenceValidator
	RequireLongTermEvidence       bool
	MaxDocumentBytes              int
	MaxXMLDepth                   int
}

ValidationOptions controls signature verification. Network access is never implicit: trust and revocation behavior must be supplied explicitly.

Jump to

Keyboard shortcuts

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