Skip to content

pure go library for processing signed XML documents

License

Notifications You must be signed in to change notification settings

daugminas/signedxml

 
 

Repository files navigation

daugminas/signedxml

GoDoc Build Status Coverage Status Go Report Card Repo Size MIT  License Slack Channel Twitter

The signedxml package transforms and validates signed xml documents. The main use case is to support Single Sign On protocols like SAML and WS-Federation.

Other packages that provide similar functionality rely on C libraries, which makes them difficult to run across platforms without significant configuration. signedxml is written in pure go, and can be easily used on any platform. This package was originally created by Matt Smith and is in use at Moov Financial.

Install

go get github.com/daugminas/signedxml

Included Algorithms

Examples

Simple signing of a document with a private key

Three steps:

  1. Insert the to-be-signed document into an XML signature template (this uses an enveloped version)

  2. Prepare private key for signing (DER format)

  3. Sign the templated document with the private key

Full code:

  // 0. load inputs
	templateBytes, e := os.ReadFile("template.xml")
	if e != nil {
		panic(e)
	}
	targetBytes, e := os.ReadFile("signing_target.xml")
	if e != nil {
		panic(e)
	}
  keyBytes, e = os.ReadFile("private_key.pem")
	if e != nil {
		return
	}

	// 1. Insert target into the template
	finalXMLtoBeSigned, e := signedxml.InsertXMLintoSignatureTemplate(string(templateBytes), string(targetBytes), true)
	if e != nil {
		panic(e)
	}

  // 2. Prep the key
  key, e := signedxml.PrepPKCS8PrivateKey(keyBytes)
  if e != nil {
		panic(e)
	}

  // 3. Sign the document
	var signer *signedxml.Signer
	signer, e = signedxml.NewSigner(targetXML)
	if e != nil {
		return
	}

	signedXML, e = signer.Sign(key)
   if e != nil {
		panic(e)
	}

Validating signed XML

If your signed xml contains the signature and certificate, then you can just pass in the xml and call ValidateReferences().

validator, err := signedxml.NewValidator(`<YourXMLString></YourXMLString>`)
xml, err = validator.ValidateReferences()

ValidateReferences() verifies the DigestValue and SignatureValue in the xml document, and returns the signed payload(s). If the error value is nil, then the signed xml is valid.

The x509.Certificate that was successfully used to validate the xml will be available by calling:

validator.SigningCert()

You can then verify that you trust the certificate. You can optionally supply your trusted certificates ahead of time by assigning them to the Certificates property of the Validator object, which is an x509.Certificate array.

Using an external Signature

If you need to specify an external Signature, you can use the SetSignature() function to assign it:

validator.SetSignature(<`Signature></Signature>`)

Generating signed XML

It is expected that your XML contains the Signature element with all the parameters set (except DigestValue and SignatureValue).

signer, err := signedxml.NewSigner(`<YourXMLString></YourXMLString`)
signedXML, err := signer.Sign(`*rsa.PrivateKey object`)

Sign() will generate the DigestValue and SignatureValue, populate it in the XML, and return the signed XML string.

Implementing custom transforms

Additional Transform algorithms can be included by adding to the CanonicalizationAlgorithms map. This interface will need to be implemented:

type CanonicalizationAlgorithm interface {
	Process(inputXML string, transformXML string) (outputXML string, err error)
}

Simple Example:

type NoChangeCanonicalization struct{}

func (n NoChangeCanonicalization) Process(inputXML string,
	transformXML string) (outputXML string, err error) {
	return inputXML, nil
}

signedxml.CanonicalizationAlgorithms["http://myTranform"] = NoChangeCanonicalization{}

See envelopedsignature.go and exclusivecanonicalization.go for examples of actual implementations.

Using a custom reference ID attribute

It is possible to set a custom reference ID attribute for both the signer and the validator. The default value is "ID"

Signer example:

signer.SetReferenceIDAttribute("customId")

Validator example:

validator.SetReferenceIDAttribute("customId")

Getting help

channel info
Twitter @moov You can follow Moov.io's Twitter feed to get updates on our project(s). You can also tweet us questions or just share blogs or stories.
GitHub Issue If you are able to reproduce a problem please open a GitHub Issue under the specific project that caused the error.
moov-io slack Join our slack channel to have an interactive discussion about the development of the project.

Contributions

Contributions are welcome. Just fork the repo and send a pull request.

Releated Projects

  • Moov RTP20022 implements ISO20022 messages in Go for Real Time Payments (RTP)

Additional Information

About xml-sig:(https://www.xml.com/pub/a/2001/08/08/xmldsig.html#xml-sig) XML-DSIG how-to: https://www.di-mgt.com.au/xmldsig.html

About

pure go library for processing signed XML documents

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 99.1%
  • Makefile 0.9%