Skip to content

lestrrat-go/xmlsec

Repository files navigation

xmlsec

xmlsec is a Go binding for XML Security Library (https://www.aleksey.com/xmlsec/index.html)

Build Status

GoDoc

Status

  • API still unstable.
  • There's enough code to generate signatures for a libxml2 Document, and to verify it, but not much else.
  • PRs, suggestions for more coverage welcome.

Example

import (
  "crypto/rand"
  "crypto/rsa"
  "crypto/x509"
  "encoding/pem"
  "io/ioutil"
  "log"
  "os"

  "github.com/lestrrat-go/libxml2/parser"
  "github.com/lestrrat-go/xmlsec"
  "github.com/lestrrat-go/xmlsec/crypto"
  "github.com/lestrrat-go/xmlsec/dsig"
)

func ExampleSignature_Sign() {
  xmlsec.Init()
  defer xmlsec.Shutdown()

  p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
  doc, err := p.ParseString(`<?xml version="1.0" encoding="UTF-8"?>
<Message><Data>Hello, World!</Data></Message>`)

  n, err := doc.DocumentElement()
  if err != nil {
    log.Printf("DocumentElement failed: %s", err)
    return
  }

  // n is the node where you want your signature to be
  // generated under
  sig, err := dsig.NewSignature(n, dsig.ExclC14N, dsig.RsaSha1, "")
  if err != nil {
    log.Printf("failed to create signature: %s", err)
    return
  }

  sig.AddReference(dsig.Sha1, "", "", "")
  sig.AddTransform(dsig.Enveloped)

  key, err := rsa.GenerateKey(rand.Reader, 2048)
  if err != nil {
    log.Printf("failed to generate key: %s", err)
    return
  }

  if err := sig.Sign(key); err != nil {
    log.Printf("failed to sign: %s", err)
    return
  }

  log.Printf("%s", doc.Dump(true))
}


func ExampleDSigCtx_Sign() {
  xmlsec.Init()
  defer xmlsec.Shutdown()

  ctx, err := dsig.NewCtx()
  if err != nil {
    log.Printf("Failed to create signature context: %s", err)
    return
  }
  defer ctx.Free()

  // This stuff isn't necessary if you already have a key file
  privkey, err := rsa.GenerateKey(rand.Reader, 2048)
  if err != nil {
    log.Printf("Failed to generate private key: %s", err)
    return
  }
  var pemkey = &pem.Block{
    Type:  "RSA PRIVATE KEY",
    Bytes: x509.MarshalPKCS1PrivateKey(privkey),
  }

  pemfile, err := ioutil.TempFile("", "xmlsec-test-")
  if err != nil {
    log.Printf("Failed to create temporary pemfile")
    return
  }
  defer os.Remove(pemfile.Name())
  defer pemfile.Close()

  if err := pem.Encode(pemfile, pemkey); err != nil {
    log.Printf("Failed to write to pemfile: %s", err)
    return
  }

  if err := pemfile.Sync(); err != nil {
    log.Printf("Failed to sync pemfile: %s", err)
    return
  }

  key, err := crypto.LoadKeyFromFile(pemfile.Name(), crypto.KeyDataFormatPem)
  if err != nil {
    log.Printf("Faild to load key: %s", err)
    return
  }
  ctx.SetKey(key)

  p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
  doc, err := p.ParseString(`<?xml version="1.0" encoding="UTF-8"?>
<!-- XML Security Library example: Simple signature template file for sign1 example.  -->
<Envelope xmlns="urn:envelope">
  <Data>
  Hello, World!
  </Data>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue></DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue/>
    <KeyInfo>
      <KeyName/>
    </KeyInfo>
  </Signature>
</Envelope>`)

  if err != nil {
    log.Printf("Failed to parse source XML: %s", err)
    return
  }
  defer doc.Free()

  if err := ctx.Sign(doc); err != nil {
    log.Printf("Failed to sign document: %s", err)
    return
  }

  log.Printf("%s", doc.Dump(true))
}

Caveats

cgo and pkg-config sometimes have problems with quoting. For example, on my local machine (OS X 10.10.5 + go 1.5.1), I get this:

shoebill% go test .
# github.com/lestrrat-go/xmlsec
In file included from <built-in>:326:
<command line>:1:24: warning: missing terminating '"' character [-Winvalid-pp-token]

If it annoys you, explicitly specifying #cgo CFLAGS: and #cgo LDFLAGS: may help, but we don't do that in this library because it makes it unportable.

See Also

Credits

About

xmlsec1 binding for golang

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages