### Install goxmldsig via Go Get
Source: https://github.com/russellhaering/goxmldsig/blob/main/README.md
Command to install the goxmldsig package into your Go workspace.
```bash
go get github.com/russellhaering/goxmldsig
```
--------------------------------
### Create Custom Signing Context with ECDSA in Go
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Illustrates creating a flexible signing context using any crypto.Signer implementation, such as ECDSA. This example generates an ECDSA key pair, creates a self-signed certificate, and configures the signing context with ECDSA-SHA256. It then signs an XML element.
```go
package main
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"math/big"
"time"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
// Generate an ECDSA key pair
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
panic(err)
}
// Create a self-signed certificate
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "Example"},
NotBefore: time.Now(),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
}
certDER, err := x509.CreateCertificate(rand.Reader, template, template, &privateKey.PublicKey, privateKey)
if err != nil {
panic(err)
}
// Create signing context with ECDSA signer
// The signer interface allows HSM or other key management solutions
ctx, err := dsig.NewSigningContext(privateKey, [][]byte{certDER})
if err != nil {
panic(err)
}
// Set signature method for ECDSA-SHA256
err = ctx.SetSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256")
if err != nil {
panic(err)
}
// Create and sign an element
element := &etree.Element{Tag: "Document"}
element.CreateAttr("ID", "doc-001")
element.CreateElement("Content").SetText("Signed content")
signedElement, err := ctx.SignEnveloped(element)
if err != nil {
panic(err)
}
doc := etree.NewDocument()
doc.SetRoot(signedElement)
xmlStr, _ := doc.WriteToString()
fmt.Println(xmlStr)
}
```
--------------------------------
### Sign and Validate SAML Assertion in Go
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
This example demonstrates the complete lifecycle of a SAML assertion: generating an RSA key pair, signing an XML assertion using an enveloped signature, and validating the signature against a trusted certificate. It utilizes the etree library for XML manipulation and goxmldsig for cryptographic operations.
```go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"fmt"
"math/big"
"time"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
idpKey, _ := rsa.GenerateKey(rand.Reader, 2048)
idpTemplate := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "Identity Provider"},
NotBefore: time.Now().Add(-1 * time.Hour),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
}
idpCertDER, _ := x509.CreateCertificate(rand.Reader, idpTemplate, idpTemplate, &idpKey.PublicKey, idpKey)
idpCert, _ := x509.ParseCertificate(idpCertDER)
keyStore := &MemoryKeyStore{key: idpKey, cert: idpCertDER}
signingCtx := dsig.NewDefaultSigningContext(keyStore)
assertion := etree.NewElement("saml:Assertion")
assertion.CreateAttr("xmlns:saml", "urn:oasis:names:tc:SAML:2.0:assertion")
assertion.CreateAttr("ID", "_assertion_"+fmt.Sprintf("%d", time.Now().UnixNano()))
assertion.CreateAttr("Version", "2.0")
assertion.CreateAttr("IssueInstant", time.Now().UTC().Format(time.RFC3339))
issuer := assertion.CreateElement("saml:Issuer")
issuer.SetText("https://idp.example.com")
signedAssertion, err := signingCtx.SignEnveloped(assertion)
if err != nil {
panic(err)
}
doc := etree.NewDocument()
doc.SetRoot(signedAssertion)
xmlBytes, _ := doc.WriteToBytes()
validationCtx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{idpCert},
})
receivedDoc := etree.NewDocument()
receivedDoc.ReadFromBytes(xmlBytes)
validated, err := validationCtx.Validate(receivedDoc.Root())
if err != nil {
fmt.Println("Validation failed:", err)
return
}
fmt.Println("Validation Successful")
}
type MemoryKeyStore struct {
key *rsa.PrivateKey
cert []byte
}
func (ks *MemoryKeyStore) GetKeyPair() (*rsa.PrivateKey, []byte, error) {
return ks.key, ks.cert, nil
}
```
--------------------------------
### Create Canonical XML 1.0 (REC) Canonicalizer in Go
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Demonstrates how to create and use the Canonical XML 1.0 (REC) and Canonical XML 1.0 (REC) With Comments canonicalizers. These are used for preparing XML documents for signing by ensuring a consistent representation, with one variant preserving comments and the other removing them. It shows how to get the algorithm URI and canonicalize an XML element.
```go
package main
import (
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
// Canonical XML 1.0 (Recommendation)
canonicalizer := dsig.MakeC14N10RecCanonicalizer()
fmt.Println("Algorithm:", canonicalizer.Algorithm())
// Output: http://www.w3.org/TR/2001/REC-xml-c14n-20010315
// With comments variant
withComments := dsig.MakeC14N10WithCommentsCanonicalizer()
fmt.Println("With Comments:", withComments.Algorithm())
// Output: http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments
// Example usage
doc := etree.NewDocument()
doc.ReadFromString(``)
// Without comments - removes XML comments
noCommentCanon, _ := canonicalizer.Canonicalize(doc.Root())
fmt.Println("No comments:", string(noCommentCanon))
// With comments - preserves XML comments
withCommentCanon, _ := withComments.Canonicalize(doc.Root())
fmt.Println("With comments:", string(withCommentCanon))
}
```
--------------------------------
### Embed XML Signature Type in Go Structs
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Shows how to define a Go struct (SAMLResponse) that embeds the `sigtypes.Signature` type for XML marshaling and unmarshaling. This allows applications to easily include and parse XML digital signatures within their data structures, such as SAML responses. The example demonstrates unmarshaling XML data into the struct and accessing signature details.
```go
package main
import (
"encoding/xml"
"fmt"
sigtypes "github.com/russellhaering/goxmldsig/types"
)
// SAML Response structure with embedded signature
type SAMLResponse struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol Response"
ID string `xml:"ID,attr"
Version string `xml:"Version,attr"
IssueInstant string `xml:"IssueInstant,attr"
Destination string `xml:"Destination,attr,omitempty"
Issuer string `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"
Signature *sigtypes.Signature `xml:"Signature"
Status Status `xml:"Status"
}
type Status struct {
StatusCode StatusCode `xml:"StatusCode"
}
type StatusCode struct {
Value string `xml:"Value,attr"
}
func main() {
xmlData := `
https://idp.example.com
...
...
`
var response SAMLResponse
err := xml.Unmarshal([]byte(xmlData), &response)
if err != nil {
panic(err)
}
if response.Signature != nil {
fmt.Println("Signature found!")
fmt.Println("Signature Method:", response.Signature.SignedInfo.SignatureMethod.Algorithm)
fmt.Println("Canonicalization:", response.Signature.SignedInfo.CanonicalizationMethod.Algorithm)
}
}
```
--------------------------------
### Implement Custom X509KeyStore in Go
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Shows how to implement the X509KeyStore interface to provide custom key management for signing XML documents. This is useful for integrating with existing key management systems or hardware security modules.
```go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"math/big"
"time"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
type CustomKeyStore struct {
key *rsa.PrivateKey
cert []byte
}
func (ks *CustomKeyStore) GetKeyPair() (*rsa.PrivateKey, []byte, error) {
return ks.key, ks.cert, nil
}
func main() {
privateKey, _ := rsa.GenerateKey(rand.Reader, 2048)
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "My Service"},
NotBefore: time.Now(),
NotAfter: time.Now().Add(365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
}
certDER, _ := x509.CreateCertificate(rand.Reader, template, template, &privateKey.PublicKey, privateKey)
keyStore := &CustomKeyStore{
key: privateKey,
cert: certDER,
}
ctx := dsig.NewDefaultSigningContext(keyStore)
element := etree.NewElement("Message")
element.CreateAttr("ID", "msg1")
signed, _ := ctx.SignEnveloped(element)
doc := etree.NewDocument()
doc.SetRoot(signed)
xmlStr, _ := doc.WriteToString()
println(xmlStr)
}
```
--------------------------------
### Create Default Signing Context in Go
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Demonstrates creating a new signing context with default settings using an X509 key store. The context is pre-configured with SHA256 hashing, 'ID' attribute for identification, 'ds' namespace prefix, and C14N11 canonicalization. It then signs an XML element using an enveloped signature.
```go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"fmt"
"math/big"
"time"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
// Create a key store with your certificate and private key
keyStore := dsig.RandomKeyStoreForTest()
// Create a signing context with default settings:
// - Hash: SHA256
// - IdAttribute: "ID"
// - Prefix: "ds"
// - Canonicalizer: C14N11
ctx := dsig.NewDefaultSigningContext(keyStore)
// Create an XML element to sign
doc := etree.NewDocument()
doc.ReadFromString(`
https://idp.example.com
`)
// Sign the element with an enveloped signature
signedElement, err := ctx.SignEnveloped(doc.Root())
if err != nil {
panic(err)
}
// Output the signed XML
signedDoc := etree.NewDocument()
signedDoc.SetRoot(signedElement)
xmlStr, _ := signedDoc.WriteToString()
fmt.Println(xmlStr)
}
```
--------------------------------
### Sign XML with TLSCertKeyStore
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Demonstrates how to wrap a standard library tls.Certificate into a dsig.TLSCertKeyStore to sign XML elements. This is essential for SAML requests where private key access is required.
```go
package main
import (
"crypto/tls"
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
tlsCert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
panic(err)
}
keyStore := dsig.TLSCertKeyStore(tlsCert)
ctx := dsig.NewDefaultSigningContext(keyStore)
element := etree.NewElement("AuthnRequest")
element.CreateAttr("xmlns", "urn:oasis:names:tc:SAML:2.0:protocol")
element.CreateAttr("ID", "_request123")
signedElement, err := ctx.SignEnveloped(element)
if err != nil {
panic(err)
}
doc := etree.NewDocument()
doc.SetRoot(signedElement)
xmlStr, _ := doc.WriteToString()
fmt.Println(xmlStr)
}
```
--------------------------------
### Validate Signatures with MemoryX509CertificateStore
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Shows how to initialize a MemoryX509CertificateStore with multiple trusted root certificates. This store is used by the validation context to verify incoming XML signatures against known trusted IdPs.
```go
package main
import (
"crypto/x509"
"encoding/pem"
"os"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
certFiles := []string{"idp1.pem", "idp2.pem", "idp3.pem"}
var roots []*x509.Certificate
for _, file := range certFiles {
pemData, err := os.ReadFile(file)
if err != nil {
continue
}
block, _ := pem.Decode(pemData)
if block == nil {
continue
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
continue
}
roots = append(roots, cert)
}
certStore := &dsig.MemoryX509CertificateStore{
Roots: roots,
}
ctx := dsig.NewDefaultValidationContext(certStore)
_ = ctx
}
```
--------------------------------
### Integrate Signature Struct in Go
Source: https://github.com/russellhaering/goxmldsig/blob/main/README.md
Demonstrates how to include the Signature struct within your application's data structures.
```go
import (
sigtypes "github.com/russellhaering/goxmldsig/types"
)
type AppHdr struct {
...
Signature *sigtypes.Signature
}
```
--------------------------------
### Sign XML Elements with goxmldsig
Source: https://github.com/russellhaering/goxmldsig/blob/main/README.md
Shows how to initialize a signing context and sign an etree element. Note that modifying the element after signing will invalidate the signature.
```go
package main
import (
"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig"
)
func main() {
randomKeyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
elementToSign := &etree.Element{
Tag: "ExampleElement",
}
elementToSign.CreateAttr("ID", "id1234")
signedElement, err := ctx.SignEnveloped(elementToSign)
if err != nil {
panic(err)
}
doc := etree.NewDocument()
doc.SetRoot(signedElement)
str, err := doc.WriteToString()
if err != nil {
panic(err)
}
println(str)
}
```
--------------------------------
### Configure Signature Algorithm in goxmldsig
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Demonstrates how to set the signature method for a signing context. It supports various RSA and ECDSA algorithms and retrieves the configured identifiers.
```go
package main
import (
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
keyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(keyStore)
err := ctx.SetSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
if err != nil {
panic(err)
}
sigMethod := ctx.GetSignatureMethodIdentifier()
digestAlgo := ctx.GetDigestAlgorithmIdentifier()
println("Signature Method:", sigMethod)
println("Digest Algorithm:", digestAlgo)
}
```
--------------------------------
### Create Validation Context with Trusted Roots (Go)
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Creates a validation context for XML signature verification by initializing a certificate store with trusted root certificates. It parses a PEM-encoded certificate, adds it to a memory-based certificate store, and then uses this store to create a default validation context. This context is then used to validate a signed XML document. Dependencies include standard Go crypto libraries, PEM decoding, and the goxmldsig and etree libraries for XML parsing and validation.
```Go
package main
import (
"crypto/x509"
"encoding/pem"
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
// Parse your trusted root certificate(s)
certPEM := []byte(`-----BEGIN CERTIFICATE-----
MIIBkTCB+wIJAKHBfpeg...
-----END CERTIFICATE-----`)
block, _ := pem.Decode(certPEM)
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
panic(err)
}
// Create a certificate store with trusted roots
certStore := &dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{cert},
}
// Create validation context
ctx := dsig.NewDefaultValidationContext(certStore)
// Parse the signed XML document
doc := etree.NewDocument()
err = doc.ReadFromFile("signed-assertion.xml")
if err != nil {
panic(err)
}
// Validate returns ONLY the verified content
// Always use the returned element, not the original
validatedElement, err := ctx.Validate(doc.Root())
if err != nil {
fmt.Println("Signature validation failed:", err)
return
}
fmt.Println("Signature is valid!")
// Use validatedElement for further processing
outputDoc := etree.NewDocument()
outputDoc.SetRoot(validatedElement)
xmlStr, _ := outputDoc.WriteToString()
fmt.Println(xmlStr)
}
```
--------------------------------
### Sign Raw String for HTTP-Redirect Binding (Go)
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Signs a raw string, typically a SAML request or response, for use with the HTTP-Redirect binding. It constructs the string to sign by encoding parameters like SAMLRequest, RelayState, and SigAlg, then signs it using a provided signing context and returns the base64-encoded signature. Dependencies include standard Go libraries for encoding, formatting, and URL manipulation, as well as the goxmldsig library.
```Go
package main
import (
"encoding/base64"
"fmt"
"net/url"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
keyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(keyStore)
// Construct the query string to sign (per SAML HTTP-Redirect binding)
// SAMLRequest or SAMLResponse + RelayState + SigAlg
samlRequest := "base64EncodedDeflatedRequest"
relayState := "someState"
sigAlg := ctx.GetSignatureMethodIdentifier()
// Build the string to sign
params := url.Values{}
params.Set("SAMLRequest", samlRequest)
params.Set("RelayState", relayState)
params.Set("SigAlg", sigAlg)
stringToSign := params.Encode()
// Sign the string
signatureBytes, err := ctx.SignString(stringToSign)
if err != nil {
panic(err)
}
// Base64 encode the signature for the URL
signature := base64.StdEncoding.EncodeToString(signatureBytes)
// Add signature to the redirect URL
params.Set("Signature", signature)
redirectURL := "https://sp.example.com/sso?" + params.Encode()
fmt.Println(redirectURL)
}
```
--------------------------------
### Simulate Time for Certificate Validation using NewFakeClockAt
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
This snippet demonstrates how to instantiate a validation context and inject a fake clock. By setting the Clock property, developers can force the validation logic to treat a specific timestamp as the current time, facilitating deterministic testing of certificate validity periods.
```go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"fmt"
"math/big"
"time"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
key, _ := rsa.GenerateKey(rand.Reader, 2048)
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
NotBefore: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
NotAfter: time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC),
KeyUsage: x509.KeyUsageDigitalSignature,
}
certDER, _ := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key)
cert, _ := x509.ParseCertificate(certDER)
ctx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{cert},
})
ctx.Clock = dsig.NewFakeClockAt(time.Date(2024, 6, 15, 12, 0, 0, 0, time.UTC))
productionCtx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{cert},
})
productionCtx.Clock = dsig.NewRealClock()
fmt.Println("Test clock set to:", ctx.Clock.Now())
}
```
--------------------------------
### Validate XML Signatures
Source: https://github.com/russellhaering/goxmldsig/blob/main/README.md
Demonstrates how to validate an XML element against a root certificate using a validation context.
```go
func validate(root *x509.Certificate, el *etree.Element) {
ctx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{root},
})
validated, err := ctx.Validate(el)
if err != nil {
panic(err)
}
doc := etree.NewDocument()
doc.SetRoot(validated)
str, err := doc.WriteToString()
if err != nil {
panic(err)
}
println(str)
}
```
--------------------------------
### Canonicalize XML with C14N11
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Illustrates the use of the C14N11 canonicalizer to normalize XML documents. This ensures consistent output by sorting attributes and handling namespaces, which is critical for signature integrity.
```go
package main
import (
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
canonicalizer := dsig.MakeC14N11Canonicalizer()
fmt.Println("Algorithm:", canonicalizer.Algorithm())
doc := etree.NewDocument()
doc.ReadFromString(`
`)
canonical, err := canonicalizer.Canonicalize(doc.Root())
if err != nil {
panic(err)
}
fmt.Println(string(canonical))
}
```
--------------------------------
### Canonicalize XML with Exclusive C14N 1.0
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Demonstrates the use of Exclusive XML Canonicalization 1.0 with a prefix list. This is a common requirement for SAML assertions to ensure specific namespace prefixes are preserved during canonicalization.
```go
package main
import (
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
canonicalizerWithPrefixes := dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList("xs xsi")
doc := etree.NewDocument()
doc.ReadFromString(`
https://idp.example.com
`)
canonical, err := canonicalizerWithPrefixes.Canonicalize(doc.Root())
if err != nil {
panic(err)
}
fmt.Println(string(canonical))
}
```
--------------------------------
### Create Enveloped XML Signature
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Shows how to sign an XML element using an enveloped signature. The signature is embedded as a child of the signed element, creating a copy of the original data.
```go
package main
import (
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
keyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(keyStore)
assertion := etree.NewElement("saml:Assertion")
assertion.CreateAttr("xmlns:saml", "urn:oasis:names:tc:SAML:2.0:assertion")
assertion.CreateAttr("ID", "_abc123")
signedAssertion, err := ctx.SignEnveloped(assertion)
if err != nil {
panic(err)
}
doc := etree.NewDocument()
doc.SetRoot(signedAssertion)
xmlBytes, _ := doc.WriteToBytes()
fmt.Println(string(xmlBytes))
}
```
--------------------------------
### Validate Enveloped XML Signatures in Go
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Demonstrates how to validate an XML element containing an enveloped signature using a trusted certificate store. It emphasizes using the returned validated element for subsequent processing to ensure security.
```go
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"fmt"
"math/big"
"time"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
key, _ := rsa.GenerateKey(rand.Reader, 2048)
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
NotBefore: time.Now().Add(-1 * time.Hour),
NotAfter: time.Now().Add(24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
}
certDER, _ := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key)
cert, _ := x509.ParseCertificate(certDER)
signingCtx := dsig.NewDefaultSigningContext(dsig.RandomKeyStoreForTest())
element := etree.NewElement("Document")
element.CreateAttr("ID", "doc1")
element.CreateElement("Data").SetText("Test content")
signedElement, _ := signingCtx.SignEnveloped(element)
validationCtx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{cert},
})
validated, err := validationCtx.Validate(signedElement)
if err != nil {
switch err {
case dsig.ErrMissingSignature:
fmt.Println("No signature found referencing the element")
case dsig.ErrInvalidSignature:
fmt.Println("Signature structure is invalid")
default:
fmt.Println("Validation error:", err)
}
return
}
data := validated.FindElement("//Data")
if data != nil {
fmt.Println("Validated data:", data.Text())
}
}
```
--------------------------------
### Construct Detached XML Signature
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Illustrates how to create a detached signature element. This allows for placing the signature outside the signed element, useful for custom XML document structures.
```go
package main
import (
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
keyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(keyStore)
data := etree.NewElement("Data")
data.CreateAttr("ID", "data-001")
signature, err := ctx.ConstructSignature(data, false)
if err != nil {
panic(err)
}
wrapper := etree.NewElement("SignedDocument")
wrapper.AddChild(data.Copy())
wrapper.AddChild(signature)
doc := etree.NewDocument()
doc.SetRoot(wrapper)
xmlStr, _ := doc.WriteToString()
fmt.Println(xmlStr)
}
```
--------------------------------
### SetSignatureMethod
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Configures the signature algorithm for the signing context. Supported algorithms include RSA-SHA1/256/384/512 and ECDSA-SHA1/256/384/512.
```APIDOC
## SetSignatureMethod
### Description
Configures the signature algorithm for the signing context. Supported algorithms include RSA-SHA1/256/384/512 and ECDSA-SHA1/256/384/512.
### Method
This is a method call within the goxmldsig library, not a direct HTTP API endpoint.
### Endpoint
N/A
### Parameters
#### Path Parameters
N/A
#### Query Parameters
N/A
#### Request Body
N/A
### Request Example
```go
package main
import (
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
keyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(keyStore)
// Set RSA-SHA512 signature method
err := ctx.SetSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
if err != nil {
panic(err)
}
sigMethod := ctx.GetSignatureMethodIdentifier()
digestAlgo := ctx.GetDigestAlgorithmIdentifier()
println("Signature Method:", sigMethod)
println("Digest Algorithm:", digestAlgo)
}
```
### Response
#### Success Response (200)
N/A (This is a configuration method, not an API endpoint returning a response)
#### Response Example
N/A
```
--------------------------------
### MakeC14N10RecCanonicalizer
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Initializes a Canonical XML 1.0 (REC) canonicalizer for XML processing.
```APIDOC
## FUNCTION MakeC14N10RecCanonicalizer
### Description
Creates a Canonical XML 1.0 (REC) canonicalizer instance. This is used to normalize XML documents for consistent signature verification.
### Method
Go Function
### Parameters
None
### Request Example
canonicalizer := dsig.MakeC14N10RecCanonicalizer()
### Response
- **canonicalizer** (Canonicalizer) - An object implementing the Canonicalize method.
```
--------------------------------
### types.Signature
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Defines the structure for XML Digital Signature elements for use in Go structs.
```APIDOC
## STRUCT types.Signature
### Description
The Signature struct represents an XML Digital Signature element. It is designed to be embedded in application message structures (like SAML) to facilitate XML marshaling and unmarshaling.
### Method
Go Struct
### Parameters
- **SignedInfo** (struct) - Contains the canonicalization method, signature method, and references.
- **SignatureValue** (string) - The base64 encoded signature value.
### Request Example
type SAMLResponse struct {
Signature *sigtypes.Signature `xml:"Signature"`
}
### Response
- **Signature** (Pointer) - A pointer to the Signature struct populated during XML unmarshaling.
```
--------------------------------
### ConstructSignature
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Creates a detached signature element for an XML element without embedding it. Useful when you need to place the signature in a specific location.
```APIDOC
## ConstructSignature
### Description
Creates a detached signature element for an XML element without embedding it. Useful when you need to place the signature in a specific location.
### Method
This is a method call within the goxmldsig library, not a direct HTTP API endpoint.
### Endpoint
N/A
### Parameters
#### Path Parameters
N/A
#### Query Parameters
N/A
#### Request Body
N/A
### Request Example
```go
package main
import (
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
keyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(keyStore)
// Element to sign
data := etree.NewElement("Data")
data.CreateAttr("ID", "data-001")
data.CreateElement("Value").SetText("Important data")
// Construct a detached signature (enveloped=false)
signature, err := ctx.ConstructSignature(data, false)
if err != nil {
panic(err)
}
// Create a wrapper document with data and signature as siblings
wrapper := etree.NewElement("SignedDocument")
wrapper.AddChild(data.Copy())
wrapper.AddChild(signature)
doc := etree.NewDocument()
doc.SetRoot(wrapper)
xmlStr, _ := doc.WriteToString()
fmt.Println(xmlStr)
}
```
### Response
#### Success Response (200)
- **signature** (*etree.Element) - A detached XMLDSig signature element.
#### Response Example
```xml
Important data
...
...
...
```
```
--------------------------------
### SignEnveloped
Source: https://context7.com/russellhaering/goxmldsig/llms.txt
Signs an XML element using an enveloped signature, embedding the signature as a child of the signed element. The returned element is a copy with the signature attached.
```APIDOC
## SignEnveloped
### Description
Signs an XML element using an enveloped signature, embedding the signature as a child of the signed element. The returned element is a copy with the signature attached.
### Method
This is a method call within the goxmldsig library, not a direct HTTP API endpoint.
### Endpoint
N/A
### Parameters
#### Path Parameters
N/A
#### Query Parameters
N/A
#### Request Body
N/A
### Request Example
```go
package main
import (
"fmt"
"github.com/beevik/etree"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
keyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(keyStore)
// Create a SAML assertion to sign
assertion := etree.NewElement("saml:Assertion")
assertion.CreateAttr("xmlns:saml", "urn:oasis:names:tc:SAML:2.0:assertion")
assertion.CreateAttr("ID", "_abc123")
assertion.CreateAttr("Version", "2.0")
assertion.CreateAttr("IssueInstant", "2024-01-01T00:00:00Z")
issuer := assertion.CreateElement("saml:Issuer")
issuer.SetText("https://idp.example.com")
subject := assertion.CreateElement("saml:Subject")
nameID := subject.CreateElement("saml:NameID")
nameID.SetText("user@example.com")
// Sign the assertion - creates a copy with enveloped signature
signedAssertion, err := ctx.SignEnveloped(assertion)
if err != nil {
panic(err)
}
doc := etree.NewDocument()
doc.SetRoot(signedAssertion)
xmlBytes, err := doc.WriteToBytes()
if err != nil {
panic(err)
}
fmt.Println(string(xmlBytes))
}
```
### Response
#### Success Response (200)
- **signedAssertion** (*etree.Element) - A new XML element representing the original element with an embedded XMLDSig signature.
#### Response Example
```xml
https://idp.example.com
user@example.com
...
...
...
```
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.