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)) }
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) }
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 } } }
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)) }
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)) }
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() }
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)) }