dsig

package module
v0.0.0-...-37be254 Latest Latest
Warning

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

Go to latest
Published: May 7, 2020 License: Apache-2.0 Imports: 19 Imported by: 0

README

goxmldsig

Build Status GoDoc

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

View Source
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#"
)
View Source
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

View Source
const (
	// AlgorithmAttr is AlgorithmAttribute.
	AlgorithmAttr = "Algorithm"
	// URIAttr is URIAttribute.
	URIAttr = "URI"
	// PrefixListAttr is PrefixListAttribute.
	PrefixListAttr = "PrefixList"
)
View Source
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

View Source
var (
	ErrNonRSAKey           = fmt.Errorf("Private key was not RSA")
	ErrMissingCertificates = fmt.Errorf("No public certificates provided")
)

Well-known errors

View Source
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

func NewFakeClock(wrapped clockwork.Clock) *Clock

NewFakeClock for testing purpose.

func NewFakeClockAt

func NewFakeClockAt(t time.Time) *Clock

NewFakeClockAt for testing for picking a particular time point.

func NewRealClock

func NewRealClock() *Clock

NewRealClock will create new clock object.s

func (*Clock) After

func (c *Clock) After(d time.Duration) <-chan time.Time

After method to chain execution chain.

func (*Clock) Now

func (c *Clock) Now() time.Time

Now returns momentary time object.

func (*Clock) Sleep

func (c *Clock) Sleep(d time.Duration)

Sleep for duration 'd'.

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

func (ctx *SigningContext) SignEnveloped(el *etree.Element) (*etree.Element, error)

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

func (*ValidationContext) Validate

func (ctx *ValidationContext) Validate(el *etree.Element) (*etree.Element, error)

Validate verifies that the passed element contains a valid enveloped signature matching a currently-valid certificate in the context's CertificateStore.

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.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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