Example #1
0
func ParseAuthnRequestString(src string) (*AuthnRequest, error) {
	p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
	doc, err := p.ParseString(src)
	if err != nil {
		return nil, errors.New("failed to parse xml: " + err.Error())
	}

	return constructAuthnRequest(doc)
}
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)

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

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

	log.Printf("%s", doc.Dump(true))
}
Example #3
0
func (v *SignatureVerify) Verify(buf []byte) error {
	p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
	doc, err := p.Parse(buf)
	if err != nil {
		return err
	}
	defer doc.Free()

	mngr, err := crypto.NewKeyManager()
	if err != nil {
		return err
	}
	defer mngr.Free()

	ctx, err := NewCtx(mngr)
	if err != nil {
		return err
	}
	defer ctx.Free()

	root, err := doc.DocumentElement()
	if err != nil {
		return err
	}
	signode, err := clib.FindSignatureNode(root)
	if err != nil {
		return err
	}

	// Create a key manager, load keys from KeyInfo
	prefix, err := signode.LookupNamespacePrefix(xmlsec.DSigNs)
	if err != nil {
		return err
	}
	if prefix == "" {
		prefix = xmlsec.Prefix
	}

	xpc, err := xpath.NewContext(signode)
	if err != nil {
		return err
	}

	xpc.RegisterNS(prefix, xmlsec.Prefix)

	iter := xpath.NodeIter(xpc.Find("//" + prefix + ":KeyInfo"))
	for iter.Next() {
		n := iter.Node()
		if err := mngr.GetKey(n); err != nil {
			return err
		}
	}

	if key := v.key; key != nil {
		cpy, err := key.Copy()
		if err != nil {
			return err
		}

		if err := ctx.SetKey(cpy); err != nil {
			return err
		}
	}

	return ctx.Verify(doc)
}
Example #4
0
func TestXmlSecDSigCtx(t *testing.T) {
	xmlsec.Init()
	defer xmlsec.Shutdown()

	privkey, err := rsa.GenerateKey(rand.Reader, 2048)
	if !assert.NoError(t, err, "Generating private key should succeed") {
		return
	}

	privfile, err := writePrivateKey(privkey)
	if !assert.NoError(t, err, "Writing private key should succeed") {
		return
	}
	defer os.Remove(privfile)

	pubfile, err := writePublicKey(&privkey.PublicKey)
	if !assert.NoError(t, err, "Writing public key should succeed") {
		return
	}
	defer os.Remove(pubfile)

	src := `<?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>`

	p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
	doc, err := p.ParseString(src)

	if !assert.NoError(t, err, "Parsing template should succeed") {
		return
	}
	defer doc.Free()

	{
		ctx, err := dsig.NewCtx(nil)
		if !assert.NoError(t, err, "dsig.NewCtx should succeed") {
			return
		}
		defer ctx.Free()

		key, err := crypto.LoadKeyFromFile(privfile, crypto.KeyDataFormatPem)
		if !assert.NoError(t, err, "Loading private key '%s' should succeed", privfile) {
			return
		}
		ctx.SetKey(key)

		if !assert.NoError(t, ctx.Sign(doc), "Sign should succeed") {
			return
		}
	}

	signed := doc.String()
	t.Logf("%s", signed)

	{
		ctx, err := dsig.NewCtx(nil)
		if !assert.NoError(t, err, "dsig.NewCtx should succeed") {
			return
		}
		defer ctx.Free()

		key, err := crypto.LoadKeyFromFile(pubfile, crypto.KeyDataFormatPem)
		if !assert.NoError(t, err, "Loading public key '%s' should succeed", pubfile) {
			return
		}
		ctx.SetKey(key)

		if !assert.NoError(t, ctx.Verify(doc), "Verify should succeed") {
			return
		}
	}

	{
		verify, err := dsig.NewSignatureVerify()
		if !assert.NoError(t, err, "NewSignatureVerify succeeds") {
			return
		}

		if !assert.NoError(t, verify.LoadKeyFromFile(pubfile, crypto.KeyDataFormatPem), "LoadKeyFromFile succeeds") {
			return
		}

		if !assert.NoError(t, verify.VerifyString(signed), "VerifyString succeeds") {
			return
		}
		if !assert.NoError(t, verify.Verify([]byte(signed)), "Verify succeeds") {
			return
		}
	}
}
Example #5
0
func encode(s serializer, key *crypto.Key, compress bool) ([]byte, error) {
	xmlstr, err := s.Serialize()
	if err != nil {
		return nil, err
	}
	if pdebug.Enabled {
		pdebug.Printf("Generated %d bytes of XML", len(xmlstr))
	}

	if key != nil {
		p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
		doc, err := p.ParseString(xmlstr)
		if err != nil {
			return nil, err
		}

		root, err := doc.DocumentElement()
		if err != nil {
			return nil, err
		}

		// Create a new signature section.
		sig, err := dsig.NewSignature(root, dsig.ExclC14N, dsig.RsaSha1, "")
		if err := sig.AddReference(dsig.Sha1, "", "", ""); err != nil {
			return nil, err
		}

		if err := sig.AddTransform(dsig.Enveloped); err != nil {
			return nil, err
		}

		if key.HasRsaKey() == nil || key.HasDsaKey() == nil || key.HasEcdsaKey() == nil {
			if err := sig.AddKeyValue(); err != nil {
				return nil, err
			}
		}

		// If the key is setup using X509, add that node
		if key.HasX509() == nil {
			if err := sig.AddX509Data(); err != nil {
				return nil, err
			}
		}

		if pdebug.Enabled {
			pdebug.Printf("Signing using key %p", key)
		}
		if err := sig.Sign(key); err != nil {
			return nil, err
		}

		xmlstr = doc.Dump(false)
		if err != nil {
			return nil, err
		}
	}

	if !compress {
		return []byte(xmlstr), nil
	}

	buf := bytes.Buffer{}

	w := getFlateWriter()
	defer releaseFlateWriter(w)

	w.Reset(&buf)
	if _, err := io.WriteString(w, xmlstr); err != nil {
		return nil, err
	}

	if err := w.Close(); err != nil {
		return nil, err
	}
	if pdebug.Enabled {
		pdebug.Printf("Compressed to %d bytes", buf.Len())
	}

	ret := make([]byte, b64enc.EncodedLen(buf.Len()))
	b64enc.Encode(ret, buf.Bytes())
	if pdebug.Enabled {
		pdebug.Printf("Encoded into %d bytes of base64", len(ret))
	}

	return ret, nil
}
func ExampleDSigCtx_Sign() {
	xmlsec.Init()
	defer xmlsec.Shutdown()

	ctx, err := dsig.NewCtx(nil)
	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))
}
Example #7
0
func TestAuthnRequest(t *testing.T) {
	xmlsec.Init()
	defer xmlsec.Shutdown()

	ar := NewAuthnRequest()
	ar.ID = "809707f0030a5d00620c9d9df97f627afe9dcc24"
	ar.Version = "2.0"
	ar.IssueInstant = time.Now()
	ar.Issuer = "http://sp.example.com/metadata"
	ar.Destination = "http://idp.example.com/sso"
	ar.ProviderName = "FooProvider"
	ar.ProtocolBinding = binding.HTTPPost
	ar.AssertionConsumerServiceURL = "http://sp.example.com/acs"
	ar.NameIDPolicy = NewNameIDPolicy(nameid.EmailAddress, true)
	ar.RequestedAuthnContext = NewRequestedAuthnContext(
		"exact",
		"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
	)

	xmlstr, err := ar.Serialize()
	if !assert.NoError(t, err, "Serialize() succeeds") {
		return
	}

	p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
	c14ndoc, err := p.ParseString(xmlstr)
	if !assert.NoError(t, err, "Parse C14N XML doc succeeds") {
		return
	}
	defer c14ndoc.Free()

	root, err := c14ndoc.DocumentElement()
	if !assert.NoError(t, err, "DocumentElement succeeds") {
		return
	}

	privkey, err := rsa.GenerateKey(rand.Reader, 2048)
	if !assert.NoError(t, err, "GenerateKey succeeds") {
		return
	}

	signer, err := dsig.NewSignature(root, dsig.ExclC14N, dsig.RsaSha1, "urn:oasis:names:tc:SAML:2.0:protocol:AuthnRequest")
	if !assert.NoError(t, err, "dsig.NewSignature succeeds") {
		return
	}

	if !assert.NoError(t, signer.AddReference(dsig.Sha1, "", "", ""), "AddReference succeeds") {
		return
	}

	if !assert.NoError(t, signer.AddTransform(dsig.Enveloped), "AddTransform succeeds") {
		return
	}

	if !assert.NoError(t, signer.AddKeyValue(), "AddKeyValue succeeds") {
		return
	}

	key, err := crypto.LoadKeyFromRSAPrivateKey(privkey)
	if !assert.NoError(t, err, "Load key from RSA private key succeeds") {
		return
	}

	if !assert.NoError(t, signer.Sign(key), "Sign succeeds") {
		return
	}

	t.Logf("%s", c14ndoc.Dump(true))
}
Example #8
0
func TestAssertion_XML(t *testing.T) {
	a := Assertion{
		Conditions: Conditions{
			NotBefore:    time.Now(),
			NotOnOrAfter: time.Now(),
		},
		Version:      "2.0",
		ID:           "b07b804c-7c29-ea16-7300-4f3d6f7928ac",
		IssueInstant: time.Now(),
		Issuer:       "https://idp.example.org/SAML2",
		Subject: Subject{
			NameID: NameID{
				Format: nameid.Transient,
				Value:  "3f7b3dcf-1674-4ecd-92c8-1544f346baf8",
			},
			SubjectConfirmation: SubjectConfirmation{
				InResponseTo: "aaf23196-1773-2113-474a-fe114412ab72",
				Recipient:    "https://sp.example.com/SAML2/SSO/POST",
				NotOnOrAfter: time.Now(),
			},
		},
		AuthnStatement: AuthnStatement{
			AuthnInstant: time.Now(),
			SessionIndex: "b07b804c-7c29-ea16-7300-4f3d6f7928ac",
			AuthnContext: AuthnContext{
				AuthnContextClassRef: PasswordProtectedTransport,
			},
		},
	}
	a.Conditions.AddAudience("https://sp.example.com/SAML2")
	a.AddAttribute(Attribute{
		Attrs: map[string]string{
			"xmlns:" + ns.X500.Prefix:     ns.X500.URI,
			ns.X500.AddPrefix("Encoding"): "LDAP",
			"NameFormat":                  ns.NameFormatURI,
		},
		Name:         "urn:oid:1.3.6.1.4.1.5923.1.1.1.1",
		FriendlyName: "eduPersonAffiliation",
		Values: []AttributeValue{
			AttributeValue{
				Type:  ns.XMLSchema.AddPrefix("string"),
				Value: "member",
			},
			AttributeValue{
				Type:  ns.XMLSchema.AddPrefix("string"),
				Value: "staff",
			},
		},
	})

	xmlstr, err := a.Serialize()
	if !assert.NoError(t, err, "Serialize() succeeds") {
		return
	}

	p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
	c14ndoc, err := p.ParseString(xmlstr)
	if !assert.NoError(t, err, "Parse C14N XML doc succeeds") {
		return
	}
	defer c14ndoc.Free()
}
Example #9
0
func TestResponse(t *testing.T) {
	xmlsec.Init()
	defer xmlsec.Shutdown()
	res := NewResponse()
	res.Issuer = "http://idp.example.com/metadata"
	res.Destination = "http://sp.example.com/sso"

	// Run serialize once so we can check for empty assertion
	xmlstr, err := res.Serialize()
	if !assert.NoError(t, err, "Serialize() succeeds") {
		return
	}
	if !assert.NotContains(t, xmlstr, "<Assertion", "Should not contain assertion") {
		return
	}

	res.Assertion = NewAssertion()

	res.Assertion.Conditions.AddAudience("sp.example.com/sso")

	xmlstr, err = res.Serialize()
	if !assert.NoError(t, err, "Serialize() succeeds") {
		return
	}

	if !assert.Contains(t, xmlstr, "<saml:Audience>sp.example.com/sso", "<saml:Audience> exists") {
		return
	}

	p := parser.New(parser.XMLParseDTDLoad | parser.XMLParseDTDAttr | parser.XMLParseNoEnt)
	doc, err := p.ParseString(xmlstr)
	if !assert.NoError(t, err, "Parse XML doc succeeds") {
		return
	}
	defer doc.Free()

	c14nxml, err := dom.C14NSerialize{Mode: dom.C14NExclusive1_0}.Serialize(doc)
	if !assert.NoError(t, err, "C14NSerialize.Serialize succeeds") {
		return
	}

	c14ndoc, err := p.ParseString(c14nxml)
	if !assert.NoError(t, err, "Parse C14N doc succeeds") {
		return
	}
	defer c14ndoc.Free()

	root, err := c14ndoc.DocumentElement()
	if !assert.NoError(t, err, "DocumentElement succeeds") {
		return
	}

	privkey, err := rsa.GenerateKey(rand.Reader, 2048)
	if !assert.NoError(t, err, "GenerateKey succeeds") {
		return
	}

	signer, err := dsig.NewSignature(root, dsig.ExclC14N, dsig.RsaSha1, "urn:oasis:names:tc:SAML:2.0:protocol:Response")
	if !assert.NoError(t, err, "dsig.NewSignature succeeds") {
		return
	}

	if !assert.NoError(t, signer.AddReference(dsig.Sha1, "", "", ""), "AddReference succeeds") {
		return
	}

	if !assert.NoError(t, signer.AddTransform(dsig.Enveloped), "AddTransform succeeds") {
		return
	}

	if !assert.NoError(t, signer.AddKeyValue(), "AddKeyValue succeeds") {
		return
	}

	key, err := crypto.LoadKeyFromRSAPrivateKey(privkey)
	if !assert.NoError(t, err, "Load key from RSA private key succeeds") {
		return
	}

	if !assert.NoError(t, signer.Sign(key), "Sign succeeds") {
		t.Logf("%s", c14ndoc.Dump(true))
		return
	}

	t.Logf("%s", c14ndoc.Dump(true))
}