README ¶
goxmldsig
XML Digital Signatures implemented in pure Go.
Installation
Install goxmldsig
into your $GOPATH
using go get
:
$ go get github.com/russellhaering/goxmldsig
Usage
Signing
package main
import (
"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig"
)
func main() {
// Generate a key and self-signed certificate for signing
randomKeyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
elementToSign := &etree.Element{
Tag: "ExampleElement",
}
elementToSign.CreateAttr("ID", "id1234")
// Sign the element
signedElement, err := ctx.SignEnveloped(elementToSign)
if err != nil {
panic(err)
}
// Serialize the signed element. It is important not to modify the element
// after it has been signed - even pretty-printing the XML will invalidate
// the signature.
doc := etree.NewDocument()
doc.SetRoot(signedElement)
str, err := doc.WriteToString()
if err != nil {
panic(err)
}
println(str)
}
Signature Validation
// Validate an element against a root certificate
func validate(root *x509.Certificate, el *etree.Element) {
// Construct a signing context with one or more roots of trust.
ctx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{root},
})
// It is important to only use the returned validated element.
// See: https://www.w3.org/TR/xmldsig-bestpractices/#check-what-is-signed
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)
}
Limitations
This library was created in order to implement SAML 2.0 without needing to execute a command line tool to create and validate signatures. It currently only implements the subset of relevant standards needed to support that implementation, but I hope to make it more complete over time. Contributions are welcome.
Documentation ¶
Index ¶
- Constants
- Variables
- type AlgorithmID
- type Canonicalizer
- type Clock
- type MemoryX509CertificateStore
- type MemoryX509KeyStore
- type SigningContext
- func (ctx *SigningContext) ConstructSignature(el *etree.Element, enveloped bool) (*etree.Element, error)
- func (ctx *SigningContext) GetDigestAlgorithmIdentifier() string
- func (ctx *SigningContext) GetSignatureMethodIdentifier() string
- func (ctx *SigningContext) SetSignatureMethod(algorithmID string) error
- func (ctx *SigningContext) SignEnveloped(el *etree.Element) (*etree.Element, error)
- func (ctx *SigningContext) SignString(content string) ([]byte, error)
- type TLSCertKeyStore
- type ValidationContext
- type X509CertificateStore
- type X509ChainStore
- type X509KeyStore
Constants ¶
const ( // DefaultPrefix for generating signs DefaultPrefix = "ds" // EmptyPrefix for generating empty prefixes, especially for KYC. EmptyPrefix = "" // Namespace of signature. Namespace = "http://www.w3.org/2000/09/xmldsig#" )
const ( SignatureTag = "Signature" SignedInfoTag = "SignedInfo" CanonicalizationMethodTag = "CanonicalizationMethod" SignatureMethodTag = "SignatureMethod" ReferenceTag = "Reference" TransformsTag = "Transforms" TransformTag = "Transform" DigestMethodTag = "DigestMethod" DigestValueTag = "DigestValue" SignatureValueTag = "SignatureValue" KeyInfoTag = "KeyInfo" X509DataTag = "X509Data" X509SubjectNameTag = "X509SubjectName" X509CertificateTag = "X509Certificate" InclusiveNamespacesTag = "InclusiveNamespaces" )
Tags
const ( // AlgorithmAttr is AlgorithmAttribute. AlgorithmAttr = "Algorithm" // URIAttr is URIAttribute. URIAttr = "URI" // PrefixListAttr is PrefixListAttribute. PrefixListAttr = "PrefixList" )
const ( // RSASHA1SignatureMethod is a signature method. RSASHA1SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" // RSASHA256SignatureMethod is a signature method RSASHA256SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" // RSASHA512SignatureMethod is a signature method RSASHA512SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" )
Variables ¶
var ( ErrNonRSAKey = fmt.Errorf("Private key was not RSA") ErrMissingCertificates = fmt.Errorf("No public certificates provided") )
Well-known errors
var ( // ErrMissingSignature indicates that no enveloped signature was found referencing // the top level element passed for signature verification. ErrMissingSignature = errors.New("Missing signature referencing the top-level element") )
Functions ¶
This section is empty.
Types ¶
type AlgorithmID ¶
type AlgorithmID string
AlgorithmID as custom type out of string.
const ( // Supported canonicalization algorithms. CanonicalXML10ExclusiveAlgorithmID AlgorithmID = "http://www.w3.org/2001/10/xml-exc-c14n#" CanonicalXML11AlgorithmID AlgorithmID = "http://www.w3.org/2006/12/xml-c14n11" CanonicalXML10RecAlgorithmID AlgorithmID = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" CanonicalXML10CommentAlgorithmID AlgorithmID = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" EnvelopedSignatureAltorithmID AlgorithmID = "http://www.w3.org/2000/09/xmldsig#enveloped-signature" )
Well-known signature algorithms
func (AlgorithmID) String ¶
func (id AlgorithmID) String() string
type Canonicalizer ¶
type Canonicalizer interface { Canonicalize(el *etree.Element) ([]byte, error) Algorithm() AlgorithmID }
Canonicalizer is an implementation of a canonicalization algorithm.
func MakeC14N10CommentCanonicalizer ¶
func MakeC14N10CommentCanonicalizer() Canonicalizer
MakeC14N10CommentCanonicalizer constructs an inclusive canonicalizer.
func MakeC14N10ExclusiveCanonicalizerWithPrefixList ¶
func MakeC14N10ExclusiveCanonicalizerWithPrefixList(prefixList string) Canonicalizer
MakeC14N10ExclusiveCanonicalizerWithPrefixList constructs an exclusive Canonicalizer from a PrefixList in NMTOKENS format (a white space separated list).
func MakeC14N10RecCanonicalizer ¶
func MakeC14N10RecCanonicalizer() Canonicalizer
MakeC14N10RecCanonicalizer constructs an inclusive canonicalizer.
func MakeC14N11Canonicalizer ¶
func MakeC14N11Canonicalizer() Canonicalizer
MakeC14N11Canonicalizer constructs an inclusive canonicalizer.
type Clock ¶
type Clock struct {
// contains filtered or unexported fields
}
Clock wraps a clockwork.Clock (which could be real or fake) in order to default to a real clock when a nil *Clock is used. In other words, if you attempt to use a nil *Clock it will defer to the real system clock. This allows Clock to be easily added to structs with methods that currently reference the time package, without requiring every instantiation of that struct to be updated.
func NewFakeClock ¶
NewFakeClock for testing purpose.
func NewFakeClockAt ¶
NewFakeClockAt for testing for picking a particular time point.
type MemoryX509CertificateStore ¶
type MemoryX509CertificateStore struct {
Roots []*x509.Certificate
}
MemoryX509CertificateStore interface.
func (*MemoryX509CertificateStore) Certificates ¶
func (mX509cs *MemoryX509CertificateStore) Certificates() ([]*x509.Certificate, error)
Certificates retruns list of certificates.
type MemoryX509KeyStore ¶
type MemoryX509KeyStore struct {
// contains filtered or unexported fields
}
MemoryX509KeyStore used for testing and all.
func (*MemoryX509KeyStore) GetKeyPair ¶
func (ks *MemoryX509KeyStore) GetKeyPair() (*rsa.PrivateKey, *x509.Certificate, error)
GetKeyPair implimenting X509KeyStore interface.
type SigningContext ¶
type SigningContext struct { Hash crypto.Hash KeyStore X509KeyStore Prefix string Canonicalizer Canonicalizer }
SigningContext is a base structure for signing.
func NewDefaultSigningContext ¶
func NewDefaultSigningContext(ks X509KeyStore) *SigningContext
NewDefaultSigningContext is for creating a default signing context.
func NewKYCSigningContext ¶
func NewKYCSigningContext(ks X509KeyStore) *SigningContext
NewKYCSigningContext creates a new context for KYC signging
func (*SigningContext) ConstructSignature ¶
func (ctx *SigningContext) ConstructSignature(el *etree.Element, enveloped bool) (*etree.Element, error)
ConstructSignature will construct etree nodes for signature.
func (*SigningContext) GetDigestAlgorithmIdentifier ¶
func (ctx *SigningContext) GetDigestAlgorithmIdentifier() string
GetDigestAlgorithmIdentifier returns digest identifier.
func (*SigningContext) GetSignatureMethodIdentifier ¶
func (ctx *SigningContext) GetSignatureMethodIdentifier() string
GetSignatureMethodIdentifier returns identifier string.
func (*SigningContext) SetSignatureMethod ¶
func (ctx *SigningContext) SetSignatureMethod(algorithmID string) error
SetSignatureMethod to set signature method.
func (*SigningContext) SignEnveloped ¶
SignEnveloped creates etree element for envelope.
func (*SigningContext) SignString ¶
func (ctx *SigningContext) SignString(content string) ([]byte, error)
SignString is useful for signing query string (including DEFLATED AuthnRequest) when using HTTP-Redirect to make a signed request. See 3.4.4.1 DEFLATE Encoding of https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
type TLSCertKeyStore ¶
type TLSCertKeyStore tls.Certificate
TLSCertKeyStore wraps the stdlib tls.Certificate to return its contained key and certs.
func (TLSCertKeyStore) GetChain ¶
func (d TLSCertKeyStore) GetChain() ([]*x509.Certificate, error)
GetChain impliments X509ChainStore using the underlying tls.Certificate
func (TLSCertKeyStore) GetKeyPair ¶
func (d TLSCertKeyStore) GetKeyPair() (*rsa.PrivateKey, *x509.Certificate, error)
GetKeyPair implements X509KeyStore using the underlying tls.Certificate
type ValidationContext ¶
type ValidationContext struct { CertificateStore X509CertificateStore Clock *Clock }
ValidationContext is a base structure for validation.
func NewDefaultValidationContext ¶
func NewDefaultValidationContext(certificateStore X509CertificateStore) *ValidationContext
NewDefaultValidationContext will create a new context for validation.
func NewKYCValidationContext ¶
func NewKYCValidationContext(certificateStore X509CertificateStore) *ValidationContext
NewKYCValidationContext is for validating KYC docs
type X509CertificateStore ¶
type X509CertificateStore interface {
Certificates() (roots []*x509.Certificate, err error)
}
X509CertificateStore interface.
type X509ChainStore ¶
type X509ChainStore interface {
GetChain() (certs []*x509.Certificate, err error)
}
X509ChainStore interface.
type X509KeyStore ¶
type X509KeyStore interface {
GetKeyPair() (privateKey *rsa.PrivateKey, cert *x509.Certificate, err error)
}
X509KeyStore is elemetary type. This package can be leveraged by implimenting GetKeyPair method.
func RandomKeyStoreForTest ¶
func RandomKeyStoreForTest() X509KeyStore
RandomKeyStoreForTest is for generating test key.