A Go library for signing, verifying and encrypting XML. It also provides XML canonicalization, XPath/XSLT, offline certificate and signature evidence verification, and supported SAML WebSSO flows. Builds without CGO.
- Sign and verify XML documents with XMLDSig, including enveloped, enveloping and detached signatures.
- Encrypt and decrypt XML or bytes with AES-GCM, using direct keys, RSA-OAEP, AES Key Wrap or ECDH-ES/ConcatKDF.
- Select, transform and canonicalize XML with XPath, XSLT and canonicalization APIs for documents, subtrees and node sets.
- Work with keys, certificates and signature evidence using PEM/DER, protected PKCS#8/PKCS#12 containers, offline PKIX validation, CMS, timestamps and supported XAdES profiles.
- Build solicited SAML WebSSO flows for service providers and identity providers, with signed metadata, POST/Redirect/Artifact bindings, bearer and holder-of-key ECP, and state/replay stores. Separate APIs handle logout, identifier management, authority queries and assertion retrieval.
The optional CLI exposes operations through the same public APIs.
Requires Go 1.27.3 or later. To try the library in a new project:
mkdir invoice-demo
cd invoice-demo
go mod init example.com/invoice-demo
go get github.com/skarm/xmlsecSave the following as main.go. It generates a temporary ECDSA key, signs an
invoice, serializes and reparses the signed XML, then verifies the signature
against that key and the expected root element.
package main
import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"fmt"
"log"
"github.com/skarm/xmlsec/document"
"github.com/skarm/xmlsec/xmldsig"
)
func main() {
ctx := context.Background()
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
log.Fatal(err)
}
doc, err := document.Parse(ctx, []byte(
`<Invoice xmlns="urn:example:invoice" ID="invoice-1"><Amount currency="EUR">125.00</Amount></Invoice>`,
), document.DefaultLimits())
if err != nil {
log.Fatal(err)
}
signed, err := xmldsig.SignEnveloped(ctx, doc, key, xmldsig.SignOptions{})
if err != nil {
log.Fatal(err)
}
xml, err := signed.XML(ctx)
if err != nil {
log.Fatal(err)
}
received, err := document.Parse(ctx, xml, document.DefaultLimits())
if err != nil {
log.Fatal(err)
}
verified, err := xmldsig.Verify(ctx, received, key.Public(), xmldsig.VerifyOptions{
ExpectedRoot: document.Name{Space: "urn:example:invoice", Local: "Invoice"},
})
if err != nil {
log.Fatal(err)
}
// Read application data from the verified snapshot.
fmt.Println("Verified:", verified.Root().Name().Local)
}Run it with go run .. Expected output:
Verified: Invoice
The generated key is only for this example. In an application, use your own signing key and obtain the verification key from a trusted configuration. Keys and certificates embedded in XML do not establish trust.
Public APIs live in packages such as document, xmldsig, xmlenc and
transform under github.com/skarm/xmlsec; the module root has no Go package.
If you already have this repository checked out, run go run ./examples/basic
for a similar signing and verification example.
- Immutable XML snapshots. Signing, decrypting and replacing XML return new documents. Use element and node handles from the relevant snapshot; after verification, read the authenticated content from the verified result.
- Explicit trust and coverage. The application supplies trusted keys and identifies the content it expects to be signed. Certificate trust and protocol validation are separate from XML signature verification.
- Controlled resource access. Parsers and operations expose limits; external resources require explicit resolvers and policies. Offline trust verification does not automatically fetch certificates or revocation data.
- Context-aware operations. Operations accept
context.Contextfor cancellation. See the API guide for ownership, concurrency and I/O contracts, and streaming and memory for storage behavior and record processing.
The API is experimental. The library implements specific profiles of the listed standards; full standards conformance and an independent security audit have not been established.
The document security parser rejects DTDs and external entities. Explicit
document.ParseOptions{NonValidating: true} and XPath/XSLT language input provide
bounded, nonvalidating DTD processing with explicit external resource policy; see
XML input profiles. XSD validation is
unsupported. The XPath/XSLT engine implements selected XPath 1.0/2.0/3.0/3.1
and XSLT 1.0/2.0/3.0 features. Complete Basic XSLT conformance remains open;
validation profiles define the required suite checks.
Schema awareness and W3C streamable execution are unsupported. SAML support covers
solicited WebSSO, including encrypted assertions, identifiers and attributes,
SLO, Artifact/SOAP, bearer and X.509 holder-of-key ECP/PAOS, and NameID management.
See SAML integration for supported editions and state contracts,
and authority integration for queries, assertion retrieval
and NameID Mapping.
See compatibility for supported profiles, exclusions and known interoperability differences, and standards for primary sources. Contributors maintain a requirements and evidence register; its consistency checks do not establish full standards conformance.
- XML signatures: basic signing, detached signatures, multiple signatures and KeyInfo.
- Encryption and trust: encryption, key formats and certificate and evidence verification.
- XML processing: XPath/XSLT guide, transform examples and streaming and memory.
- SAML: integration guide, authority queries and mapping, WebSSO example and Redirect binding.
- Reference: API guide, all examples, CLI, package architecture and security policy.
From the repository root, with Go, make and a POSIX shell:
make check race examplesSee testing and profiling for lint, fuzzing and optional native
interoperability checks. Build the CLI with make build (bin/xmlsec), or run
go run ./cmd/xmlsec --help.
MIT. Third-party notices are retained in adapted sources and licenses. See XPath/XSLT source provenance for origins and local modifications.