GithubHelp home page GithubHelp logo

goxmldsig's People

Contributors

adamdecaf avatar agnivade avatar aidansteele avatar andrewstuart avatar apilloud avatar aporcupine avatar arun251 avatar aykevl avatar calpicow avatar danikarik avatar davidillsley avatar dependabot[bot] avatar elwint avatar fatlotus avatar holgerkoser avatar karlovskiy avatar otto-md avatar paulquerna-okta avatar pboyd04 avatar phoebesimon avatar rowland66 avatar russellhaering avatar russellhaering-okta avatar russjones avatar sagikazarmark avatar santosh653 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

goxmldsig's Issues

proposal: remove clockwork dependency

The current clockwork dependency is used in exactly one place.

type ValidationContext struct {
    CertificateStore X509CertificateStore
    IdAttribute      string
    Clock            *Clock
}

This can easily be replaced with a method for getting the current time.

type ValidationContext struct {
    CertificateStore X509CertificateStore
    IdAttribute      string
    // Now is used to determine the current time. If not provided, time.Now is used.
    Now func() time.Time
}

Basically what tls.Config does https://golang.org/pkg/crypto/tls/#Config

It's a breaking change so I wanted to see how y'all feel about it before sending a PR.

Invalid Body ID/Id parsing

Hey, I noticed something interesting.

xmlsec1 requires this format: <soap:Body Id="xmltosign">

But your package requires this format: <soap:Body ID="xmltosign">

This makes the two incompatible. I was hoping to use your package to talk with an old banking system that uses xmlsec1 with the first format, but I can not do that since you require the second.

Is there a chance you can refactor your parsing to that both ID and Id can be used ?

Crash on nil-pointer dereference with malformed input

See russellhaering/gosaml2#59 for background.

Program which exhibits the issue:

package main

import (
	"crypto/x509"
	"encoding/base64"
	"encoding/xml"
	"fmt"
	"time"

	saml2 "github.com/russellhaering/gosaml2"
	"github.com/russellhaering/gosaml2/types"
	dsig "github.com/russellhaering/goxmldsig"
)

const (
	timeString   = "2019-08-12T12:00:52.718Z"
	oktaMetadata = `<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor entityID="http://www.okta.com/exk133onomIuOW98z357" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"><md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAWxzAwX1MA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU
MBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi05MDUyNTExHDAaBgkqhkiG9w0BCQEW
DWluZm9Ab2t0YS5jb20wHhcNMTkwODA4MjA1MzMzWhcNMjkwODA4MjA1NDMzWjCBkjELMAkGA1UE
BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNV
BAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtOTA1MjUxMRwwGgYJ
KoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
m+ZZF6aEG6ehLLIV6RPA+i1z6ss3HBG2bZD3efwKCDDXYUkp59AE7JsjVHMtpJPHhzHuScuHDMlu
HmkBQTW7j9XpnaRn8SfZXkwlCUHTo+HAC9lwbQxO4d4wnwgnm6FAjm1I/gbfFAobd8BR9pDxHuXE
MQ0DtQu/W3WbDUrz/bhSxPJAoVy2koQn9G0y3unm7eRwYWHeuW6GdPWV2szTtDS0c3qtUXVF5Ugg
iQYlwQu6xkfy4l8iGJL7ETa2BmJzwCFecMIct87SqNhYQwCBH54MBaHcaSsCKyimNvMY9B7RmC+H
4+awePPA1q3R/UQ3Pfom8mx6yDdKIWqlkG3MsQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAiURCZ
P4oJWcf1o5nm4yG15UH01g/S6Y4OUWMi6BFJy9fCrJ0h/2BZKi68SQ0uMAbdK6anxCzq3Rr5MSzW
OWPQ1Zljn3LGPsiTFdFca/GVRen5IYQ7Dr2Mvhtm+QVscEY9TDjtETbTAHEVEjwXmB21wtdIhizv
sQS7wz0A8LV+Atpbev45RiV6COmB6T6vJuFQ7ZsDZMSHZriTYiETTJvHBGd7PtbCxYNc6LRB2JDb
wlekRhVEjR0UhnM+nn2sqqbv7tDEPs63lZSDXCnR1PhscHrEuQ04rHI3OL0gCULVQFvJrj85IAZF
1QQuGUK8ozfOyFpQWAJUW71INnF/SLWv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://dev-905251.okta.com/app/medev905251_test_1/exk133onomIuOW98z357/sso/saml"/><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://dev-905251.okta.com/app/medev905251_test_1/exk133onomIuOW98z357/sso/saml"/></md:IDPSSODescriptor></md:EntityDescriptor>`

	badInput = `<p ID="5"o=""t=""n=""xmlns:saml2p=""s=""><saml2 t=""l=""></l><s s=""><s><s I=""><s><s m=""></m></s><s></e></e></o><s></e><s><s><s></X></X></o></e><saml2p l=""></l><saml2:Assertion ID="id1684056077776386493060641"IssueInstant="2019-08-12T12:00:52.718Z"Version="2.0"xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"xmlns:xs="http://www.w3.org/2001/XMLSchema"><saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"xmlns="">http://www.okta.com/exk133onomIuOW98z357</l><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:Reference URI="#id1684056077776386493060641"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="xs"xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"/></m></s><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>dC1cm0pLLjIWZC6G2Pmf0JogmqHztp9W1euXPd/TUHo=</e></e></o><ds></e><ds><ds><ds></X></X></o></e><saml2:Subject xmlns:=""><saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">[email protected]</l><saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml2:SubjectConfirmationData InResponseTo="_40a419f5-5c1c-43d0-5834-5caf268a5f01"NotOnOrAfter="2019-08-12T12:05:52.718Z"Recipient="https://127.0.0.1/login"/></l></l><saml2:Conditions NotBefore="2019-08-12T11:55:52.718Z"NotOnOrAfter="2019-08-12T12:05:52.718Z"xmlns:=""><saml2:AudienceRestriction><saml2:Audience>37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f.jazznetworks.com</l></l></l><saml2:AuthnStatement AuthnInstant="2019-08-12T12:00:52.718Z"SessionIndex="_40a419f5-5c1c-43d0-5834-5caf268a5f01"xmlns:=""><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</l></l></l><saml2:AttributeStatement xmlns:=""><saml2:Attribute Name="FirstName"NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"><saml2:AttributeValue xmlns:=""xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:type="xs:string">Steven</l></l><saml2:Attribute Name="LastName"NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"><saml2:AttributeValue xmlns:=""xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:type="xs:string">Johnstone</l></l><saml2:Attribute Name="Email"NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"><saml2:AttributeValue xmlns:=""xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:type="xs:string">[email protected]</l></l>`
)

func newServiceProvider() *saml2.SAMLServiceProvider {
	metadata := &types.EntityDescriptor{} // may need to support EntityDescriptors (plural)
	if err := xml.Unmarshal([]byte(oktaMetadata), metadata); err != nil {
		panic(err)
	}

	certStore := dsig.MemoryX509CertificateStore{
		Roots: []*x509.Certificate{},
	}

	for _, kd := range metadata.IDPSSODescriptor.KeyDescriptors {
		for _, xcert := range kd.KeyInfo.X509Data.X509Certificates {
			if xcert.Data == "" {
				panic("nope")
			}
			certData, err := base64.StdEncoding.DecodeString(xcert.Data)
			if err != nil {
				panic(err)
			}

			idpCert, err := x509.ParseCertificate(certData)
			if err != nil {
				panic(err)
			}

			certStore.Roots = append(certStore.Roots, idpCert)
		}
	}

	SSOs := metadata.IDPSSODescriptor.SingleSignOnServices

	tenantURI := "test.example.com"

	fakeTime, err := time.Parse(time.RFC3339, timeString)
	if err != nil {
		panic(err)
	}

	clock := dsig.NewFakeClockAt(fakeTime)

	return &saml2.SAMLServiceProvider{
		Clock:                       clock,
		IdentityProviderSSOURL:      SSOs[0].Location,
		IdentityProviderIssuer:      metadata.EntityID,
		ServiceProviderIssuer:       tenantURI,
		AssertionConsumerServiceURL: "https://127.0.0.1/login",
		SignAuthnRequests:           true,
		AudienceURI:                 tenantURI,
		IDPCertificateStore:         &certStore,
		ValidateEncryptionCert:      true,
	}
}

func main() {
	base64Input := base64.StdEncoding.EncodeToString([]byte(badInput))
	if _, err := newServiceProvider().RetrieveAssertionInfo(base64Input); err != nil {
		fmt.Printf("error %v\n", err)
	}
}

Panic:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x66bca4]

goroutine 1 [running]:
github.com/russellhaering/goxmldsig.(*ValidationContext).validateSignature(0xc000154f88, 0xc00019c240, 0xc00019e4c0, 0xc000126580, 0x0, 0x1, 0x6010105)
	/goroot/go/src/github.com/russellhaering/goxmldsig/validate.go:275 +0x2b4
github.com/russellhaering/goxmldsig.(*ValidationContext).Validate(0xc000154f88, 0xc00017d560, 0xc00017d560, 0x0, 0x0)
	/goroot/go/src/github.com/russellhaering/goxmldsig/validate.go:466 +0xf3
github.com/russellhaering/gosaml2.(*SAMLServiceProvider).validateAssertionSignatures.func1(0xc000191080, 0xc0000ada40, 0x9, 0x1)
	/goroot/go/src/github.com/russellhaering/gosaml2/decode_response.go:178 +0x2fc
github.com/russellhaering/goxmldsig/etreeutils.NSFindIterateCtx.func1(0xc000191080, 0xc0000ada40, 0xc000191080, 0x0)
	/goroot/go/src/github.com/russellhaering/goxmldsig/etreeutils/namespace.go:281 +0x137
github.com/russellhaering/goxmldsig/etreeutils.NSTraverse(0xc000190ba0, 0xc0000ada40, 0xc000190b70, 0x0, 0x0)
	/goroot/go/src/github.com/russellhaering/goxmldsig/etreeutils/namespace.go:148 +0x6e
github.com/russellhaering/goxmldsig/etreeutils.NSTraverse(0xc0000ccc60, 0xc0000ad4a0, 0xc000190b70, 0x30, 0x6ebda0)
	/goroot/go/src/github.com/russellhaering/goxmldsig/etreeutils/namespace.go:155 +0xe5
github.com/russellhaering/goxmldsig/etreeutils.NSFindIterateCtx(0xc0000ccc60, 0xc0000ad4a0, 0x71c4d1, 0x25, 0x712a6e, 0x9, 0xc000190b40, 0x7152c8, 0x12)
	/goroot/go/src/github.com/russellhaering/goxmldsig/etreeutils/namespace.go:268 +0xa4
github.com/russellhaering/goxmldsig/etreeutils.NSFindIterate(...)
	/goroot/go/src/github.com/russellhaering/goxmldsig/etreeutils/namespace.go:257
github.com/russellhaering/gosaml2.(*SAMLServiceProvider).validateAssertionSignatures(0xc000164000, 0xc0000ad4a0, 0x0, 0x0)
	/goroot/go/src/github.com/russellhaering/gosaml2/decode_response.go:200 +0xed
github.com/russellhaering/gosaml2.(*SAMLServiceProvider).ValidateEncodedResponse(0xc000164000, 0xc000143000, 0xe24, 0xc000013510, 0xc00015e000, 0xc0000d8b40)
	/goroot/go/src/github.com/russellhaering/gosaml2/decode_response.go:248 +0x30e
github.com/russellhaering/gosaml2.(*SAMLServiceProvider).RetrieveAssertionInfo(0xc000164000, 0xc000143000, 0xe24, 0xa9b, 0xc000143000, 0xe24)
	/goroot/go/src/github.com/russellhaering/gosaml2/retrieve_assertion.go:40 +0x9b
main.main()
	/goroot/go/src/github.com/russellhaering/gosaml2/crasher/main.go:93 +0xb6
exit status 2

Potential fix:

diff --git a/validate.go b/validate.go
index 55feb39..fe63af4 100644
--- a/validate.go
+++ b/validate.go
@@ -271,6 +271,10 @@ func (ctx *ValidationContext) validateSignature(el *etree.Element, sig *types.Si
                return nil, errors.New("Signature could not be verified")
        }
 
+       if sig.SignatureValue == nil {
+               return nil, errors.New("nil signature value")
+       }
+
        // Decode the 'SignatureValue' so we can compare against it
        decodedSignature, err := base64.StdEncoding.DecodeString(sig.SignatureValue.Data)
        if err != nil {

Possible regressions in signature verification

Running tests in dex with the latest commit (ff1b2e1)

Ref: dexidp/dex#870

=== RUN   TestVerifySignedMessageAndUnsignedAssertion
--- FAIL: TestVerifySignedMessageAndUnsignedAssertion (0.00s)
	saml_test.go:56: crypto/rsa: verification error
=== RUN   TestVerifyUnsignedMessageAndSignedAssertion
--- FAIL: TestVerifyUnsignedMessageAndSignedAssertion (0.00s)
	saml_test.go:56: crypto/rsa: verification error
=== RUN   TestVerifySignedMessageAndSignedAssertion
--- FAIL: TestVerifySignedMessageAndSignedAssertion (0.00s)
	saml_test.go:56: crypto/rsa: verification error

NSSelectOne returns nil pointer w/o error

It seems NSSelectOne returns a nil pointer w/o an error for found if the element is not present.

I found this while chasing a production panic that's using this repo as a dependency:

dexidp/dex#1823

I'm not sure if it would make sense to just do a found == nil check in NSSelectOne and return an error.

C14N10 REC Canonicalizer does not follow

Taking Example 3.3 from the REC-xml-c14n-20010315 specification does not properly canonicalize the document.

--- FAIL: TestC14N10RecCanonicalizer (0.00s)
    canonicalize_test.go:31: 
        	Error Trace:	canonicalize_test.go:31
        	            				canonicalize_test.go:118
        	Error:      	Not equal: 
        	            	expected: "<doc>\n   <e1></e1>\n   <e2></e2>\n   <e3 id=\"elem3\" name=\"elem3\"></e3>\n   <e4 id=\"elem4\" name=\"elem4\"></e4>\n   <e5 xmlns=\"http://example.org\" xmlns:a=\"http://www.w3.org\" xmlns:b=\"http://www.ietf.org\" attr=\"I'm\" attr2=\"all\" b:attr=\"sorted\" a:attr=\"out\"></e5>\n   <e6 xmlns:a=\"http://www.w3.org\">\n      <e7 xmlns=\"http://www.ietf.org\">\n         <e8 xmlns=\"\">\n            <e9 xmlns:a=\"http://www.ietf.org\" attr=\"default\"></e9>\n         </e8>\n      </e7>\n   </e6>\n</doc>"
        	            	actual  : "<doc>\n   <e1></e1>\n   <e2></e2>\n   <e3 id=\"elem3\" name=\"elem3\"></e3>\n   <e4 id=\"elem4\" name=\"elem4\"></e4>\n   <e5 xmlns=\"http://example.org\" xmlns:a=\"http://www.w3.org\" xmlns:b=\"http://www.ietf.org\" attr=\"I'm\" attr2=\"all\" b:attr=\"sorted\" a:attr=\"out\"></e5>\n   <e6 xmlns=\"\" xmlns:a=\"http://www.w3.org\">\n      <e7 xmlns=\"http://www.ietf.org\">\n         <e8 xmlns=\"\">\n            <e9 xmlns=\"\"></e9>\n         </e8>\n      </e7>\n   </e6>\n</doc>"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -6,6 +6,6 @@
        	            	    <e5 xmlns="http://example.org" xmlns:a="http://www.w3.org" xmlns:b="http://www.ietf.org" attr="I'm" attr2="all" b:attr="sorted" a:attr="out"></e5>
        	            	-   <e6 xmlns:a="http://www.w3.org">
        	            	+   <e6 xmlns="" xmlns:a="http://www.w3.org">
        	            	       <e7 xmlns="http://www.ietf.org">
        	            	          <e8 xmlns="">
        	            	-            <e9 xmlns:a="http://www.ietf.org" attr="default"></e9>
        	            	+            <e9 xmlns=""></e9>
        	            	          </e8>
        	Test:       	TestC14N10RecCanonicalizer
FAIL
FAIL	github.com/russellhaering/goxmldsig	1.175s

It appears we are injecting empty xmlns attributes into the response.

Missing copyright

Hi,

Please provide a copyright so your rights are properly represented and companies can use your code the proper legal way.
E.g.
Copyright

Thank you!
Have a nice day!

Fuzz Testing

Use go-fuzz to compare compare our canonicalization's to those generated by another implementation.

Could you please add a new tag for the latest commit?

Hi,

First of all, thanks for the hard work and for sharing this lib with the community.

I am trying to use your library in my app using go mod with the latest fixes but as you forgot to create a new tag I am getting a old version that contains a bug already fixed at sign.go - constructSignedInfo.

So, could you please just create a new tag with this small revision?

Thanks in advance.

PS.: I know we could run go get github.com/russellhaering/goxmldsig@master but this small adjust will avoid this inconvenience

Support xml-c14n 1.0

So as I've been working on russellhaering/gosaml2#3, I've hit a minor snag with signed AuthN request. It seems that Shibboleth wants signatures that use the original xml-c14n algorithm.

I'd like to try to tackle the issue, but I'm curious as to whether you have any advice/experience on the differences and how I would go about prepping the etree.Document differently. No worries if not, but it might save me some reading of the spec. :-)

Gap in the readme, how do I sign an object with the Signature property?

The Usages says

Include the types.Signature struct from this package in your application messages

proceeds to create the AppHdr struct which is never used or referenced again, LOL.

I need to sign Response and Assertion objects from for post binding, I got an starting base by copying them from gosaml2 and adding the Signature property.

How do I get from embedding the Signature struct to actually signing the objects?

Optionally allow expired signing certificates?

When validating a signature, the function verifyCertificate verifies that the certificate hasn't expired. Since we've already verified that the certificate is one we trust, it would be nice if we could as an option skip the check of the certificate's notBefore/notAfter.

I can get around it by setting a fake clock to the cert's notBefore in the validation context (and calling Validate multiple times if there are multiple certificates). But it would be nice if you could set a flag in ValidationContext instead.

For context, see also crewjam/saml#234

Would you consider such a feature? I can provide a PR if you wish.

Many regressions with saml.oktadev.com

After bumping to the latest master revs in gosaml2 and goxmldsig, I see several regressions when testing my app against http://saml.oktadev.com/.

Here's a subset:

  • Created SAMLResponse that removes NotOnOrAfter from saml:Conditions
<?xml version="1.0" ?>
<samlp:Response Destination="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0" ID="_0bb6e7bd0c86a18e04e8" IssueInstant="2017-03-24T21:58:36Z" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
	<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">idp.oktadev.com</saml:Issuer>
	<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
		<ds:SignedInfo>
			<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
			<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
			<ds:Reference URI="">
				<ds:Transforms>
					<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
					<ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
				<ds:DigestValue>PoDJiuV7l8rwQiSUJz13y6OdaJkbd9ZlV/bIRdQM4cc=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>CogrL+tKzDDd2G8l0D+spvGoBM1Z3EejIumWwds+ttAydrQWuFPnRa0i/7vGNU4bQk3g2JUbo+/60rt88uaH8kzxE+Lz62YYSxQn//bGPhXkHGLMbsIbAAJk19KmSRhDBRY/mM+LySu4+HKVS4wIDpoTdGOkGNJgrGI0DzMqyo9EI3orh8Pe/nf4AkWCY+qLbSKHQF28+00dvdCn3xekbQQ7aY8Df24x4sxTf3YBcMXo6sCglS8G4xBnexzI6NDYy/EUGf2CsyG3qtYMDc2y515XiG0VDHAn9LI0/QlvZkwJIrI9Jur7nM0wUWVBnAiHT7KW8xbl3atxWW3wBWRgNA==</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate>MIIDPDCCAiQCCQDydJgOlszqbzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEQMA4GA1UEChMHSmFua3lDbzESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE0MDMxMjE5NDYzM1oXDTI3MTExOTE5NDYzM1owYDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEDAOBgNVBAoTB0phbmt5Q28xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGvJpRTTasRUSPqcbqCG+ZnTAurnu0vVpIG9lzExnh11o/BGmzu7lB+yLHcEdwrKBBmpepDBPCYxpVajvuEhZdKFx/Fdy6j5mH3rrW0Bh/zd36CoUNjbbhHyTjeM7FN2yF3u9lcyubuvOzr3B3gX66IwJlU46+wzcQVhSOlMk2tXR+fIKQExFrOuK9tbX3JIBUqItpI+HnAow509CnM134svw8PTFLkR6/CcMqnDfDK1m993PyoC1Y+N4X9XkhSmEQoAlAHPI5LHrvuujM13nvtoVYvKYoj7ScgumkpWNEvX652LfXOnKYlkB8ZybuxmFfIkzedQrbJsyOhfL03cMECAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAeHwzqwnzGEkxjzSD47imXaTqtYyETZow7XwBc0ZaFS50qRFJUgKTAmKS1xQBP/qHpStsROT35DUxJAE6NY1Kbq3ZbCuhGoSlY0L7VzVT5tpu4EY8+Dq/u2EjRmmhoL7UkskvIZ2n1DdERtd+YUMTeqYl9co43csZwDno/IKomeN5qaPc39IZjikJ+nUC6kPFKeu/3j9rgHNlRtocI6S1FdtFz9OZMQlpr0JbUt2T3xS/YoQJn6coDmJL5GTiiKM6cOe+Ur1VwzS1JEDbSS2TWWhzq8ojLdrotYLGd9JOsoQhElmz+tMfCFQUFLExinPAyy7YHlSiVX13QH2XTu/iQQ==</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>
	<samlp:Status>
		<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
	</samlp:Status>
	<saml:Assertion ID="_zMpSsMVcfYO2oWQvTJw4KjlQKssPBsPu" IssueInstant="2017-03-24T21:58:36.487Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
		<saml:Issuer>idp.oktadev.com</saml:Issuer>
		<saml:Subject>
			<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">[email protected]</saml:NameID>
			<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml:SubjectConfirmationData NotOnOrAfter="2017-03-24T22:58:36.487Z" Recipient="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0"/>
			</saml:SubjectConfirmation>
		</saml:Subject>
		<saml:Conditions NotBefore="2017-03-24T21:58:36.487Z">
			<saml:AudienceRestriction>
				<saml:Audience>app.launchdarkly.com</saml:Audience>
			</saml:AudienceRestriction>
		</saml:Conditions>
		<saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
			<saml:Attribute Name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="Email">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="FirstName">
				<saml:AttributeValue xsi:type="xs:anyType">Jane</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="LastName">
				<saml:AttributeValue xsi:type="xs:anyType">Doe</saml:AttributeValue>
			</saml:Attribute>
		</saml:AttributeStatement>
		<saml:AuthnStatement AuthnInstant="2017-03-24T21:58:36.487Z">
			<saml:AuthnContext>
				<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
			</saml:AuthnContext>
		</saml:AuthnStatement>
	</saml:Assertion>
</samlp:Response>
  • Created SAMLResponse that removes NotBefore and NotOnOrAfter from saml:Conditions
<?xml version="1.0" ?>
<samlp:Response Destination="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0" ID="_e285f2ec1c708548071f" IssueInstant="2017-03-24T21:58:37Z" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
	<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">idp.oktadev.com</saml:Issuer>
	<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
		<ds:SignedInfo>
			<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
			<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
			<ds:Reference URI="">
				<ds:Transforms>
					<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
					<ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
				<ds:DigestValue>NhdPcbTm85iOEiqPM+r51L4ARVsmSgjNYIJHTGxAdhA=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>nvTpT24dpnfxBv4xFwgP/Q3TJ3vKTmR3eXc67hnDXhRpOmoRruVIBUgm/+aLm0uFaZDzay9yOPaBwI1yFeikoM4/iCMWpUhrTyA1orIJC/GZ4YOG+owbawvXcamLlfavxgsAE1f4dWsu4qOCkIjpejC57M+wTgDHV4C74GWABuFCTDWQfTvspK0GAKlwvbccgXR+eRO8nrQkh4xb/wCfu5gTAp1gzB4Z31KXjPf+72hDU0xZ/gDAXUYUFuMJPeYzSMPTN2qUUF/oA/QaM/QOO2BCqTIjtTZa6W7KHgncx8feYo/LzzOGUDWzqeECFM1zvcR1Bbo55TTxEsoOIf5J8w==</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate>MIIDPDCCAiQCCQDydJgOlszqbzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEQMA4GA1UEChMHSmFua3lDbzESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE0MDMxMjE5NDYzM1oXDTI3MTExOTE5NDYzM1owYDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEDAOBgNVBAoTB0phbmt5Q28xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGvJpRTTasRUSPqcbqCG+ZnTAurnu0vVpIG9lzExnh11o/BGmzu7lB+yLHcEdwrKBBmpepDBPCYxpVajvuEhZdKFx/Fdy6j5mH3rrW0Bh/zd36CoUNjbbhHyTjeM7FN2yF3u9lcyubuvOzr3B3gX66IwJlU46+wzcQVhSOlMk2tXR+fIKQExFrOuK9tbX3JIBUqItpI+HnAow509CnM134svw8PTFLkR6/CcMqnDfDK1m993PyoC1Y+N4X9XkhSmEQoAlAHPI5LHrvuujM13nvtoVYvKYoj7ScgumkpWNEvX652LfXOnKYlkB8ZybuxmFfIkzedQrbJsyOhfL03cMECAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAeHwzqwnzGEkxjzSD47imXaTqtYyETZow7XwBc0ZaFS50qRFJUgKTAmKS1xQBP/qHpStsROT35DUxJAE6NY1Kbq3ZbCuhGoSlY0L7VzVT5tpu4EY8+Dq/u2EjRmmhoL7UkskvIZ2n1DdERtd+YUMTeqYl9co43csZwDno/IKomeN5qaPc39IZjikJ+nUC6kPFKeu/3j9rgHNlRtocI6S1FdtFz9OZMQlpr0JbUt2T3xS/YoQJn6coDmJL5GTiiKM6cOe+Ur1VwzS1JEDbSS2TWWhzq8ojLdrotYLGd9JOsoQhElmz+tMfCFQUFLExinPAyy7YHlSiVX13QH2XTu/iQQ==</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>
	<samlp:Status>
		<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
	</samlp:Status>
	<saml:Assertion ID="_OGBYRimn0dCxa8EIS0MGw12Fo7usJBgH" IssueInstant="2017-03-24T21:58:37.182Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
		<saml:Issuer>idp.oktadev.com</saml:Issuer>
		<saml:Subject>
			<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">[email protected]</saml:NameID>
			<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml:SubjectConfirmationData NotOnOrAfter="2017-03-24T22:58:37.182Z" Recipient="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0"/>
			</saml:SubjectConfirmation>
		</saml:Subject>
		<saml:Conditions>
			<saml:AudienceRestriction>
				<saml:Audience>app.launchdarkly.com</saml:Audience>
			</saml:AudienceRestriction>
		</saml:Conditions>
		<saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
			<saml:Attribute Name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="Email">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="FirstName">
				<saml:AttributeValue xsi:type="xs:anyType">Jane</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="LastName">
				<saml:AttributeValue xsi:type="xs:anyType">Doe</saml:AttributeValue>
			</saml:Attribute>
		</saml:AttributeStatement>
		<saml:AuthnStatement AuthnInstant="2017-03-24T21:58:37.182Z">
			<saml:AuthnContext>
				<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
			</saml:AuthnContext>
		</saml:AuthnStatement>
	</saml:Assertion>
</samlp:Response>
  • Created SAMLResponse that set NotBefore and NotOnOrAfter to old dates
<?xml version="1.0" ?>
<samlp:Response Destination="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0" ID="_a06edb0384760275e261" IssueInstant="2017-03-24T21:58:38Z" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
	<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">idp.oktadev.com</saml:Issuer>
	<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
		<ds:SignedInfo>
			<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
			<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
			<ds:Reference URI="">
				<ds:Transforms>
					<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
					<ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
				<ds:DigestValue>MiGu+cAsT81eZ1/bb6ck35gMMj777pkx/1Wg37p7lHc=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>SA7a7rVq6Dx9RrEwkVL4LCfUFBfcfm815NZh9vrVX1G8Y6PJmpdk5B6Eos+8cuYhEDDheud5ts4U6Qur5rKTIDzPpN28r0/mTu+NfMmz9QYqlxvv3mDFA2bqtbQg6o6mTJnMeYiUNFjixzqNokFUDn6JOsHB68ysLMqGJYoIDEKo83rNGnc4VDXbO/txoWkyYJR6veXkftrUPvPvO91KhLFEIQTI3QEoMqUdjtBLJ40rcewYtJjdJBhuuLp5Gswf/tA40nlx/hBvYC8PvtaMd72KR26RvIG6ybAQGd0mcpLoRQnDI5pHhUXn4KVMUcL1UPahrRTihkXg3lmNWlHQzQ==</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate>MIIDPDCCAiQCCQDydJgOlszqbzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEQMA4GA1UEChMHSmFua3lDbzESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE0MDMxMjE5NDYzM1oXDTI3MTExOTE5NDYzM1owYDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEDAOBgNVBAoTB0phbmt5Q28xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGvJpRTTasRUSPqcbqCG+ZnTAurnu0vVpIG9lzExnh11o/BGmzu7lB+yLHcEdwrKBBmpepDBPCYxpVajvuEhZdKFx/Fdy6j5mH3rrW0Bh/zd36CoUNjbbhHyTjeM7FN2yF3u9lcyubuvOzr3B3gX66IwJlU46+wzcQVhSOlMk2tXR+fIKQExFrOuK9tbX3JIBUqItpI+HnAow509CnM134svw8PTFLkR6/CcMqnDfDK1m993PyoC1Y+N4X9XkhSmEQoAlAHPI5LHrvuujM13nvtoVYvKYoj7ScgumkpWNEvX652LfXOnKYlkB8ZybuxmFfIkzedQrbJsyOhfL03cMECAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAeHwzqwnzGEkxjzSD47imXaTqtYyETZow7XwBc0ZaFS50qRFJUgKTAmKS1xQBP/qHpStsROT35DUxJAE6NY1Kbq3ZbCuhGoSlY0L7VzVT5tpu4EY8+Dq/u2EjRmmhoL7UkskvIZ2n1DdERtd+YUMTeqYl9co43csZwDno/IKomeN5qaPc39IZjikJ+nUC6kPFKeu/3j9rgHNlRtocI6S1FdtFz9OZMQlpr0JbUt2T3xS/YoQJn6coDmJL5GTiiKM6cOe+Ur1VwzS1JEDbSS2TWWhzq8ojLdrotYLGd9JOsoQhElmz+tMfCFQUFLExinPAyy7YHlSiVX13QH2XTu/iQQ==</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>
	<samlp:Status>
		<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
	</samlp:Status>
	<saml:Assertion ID="_tUUdPl0s8js1VgSLz2dwcnRVGZXhzwNj" IssueInstant="2017-03-24T21:58:38.347Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
		<saml:Issuer>idp.oktadev.com</saml:Issuer>
		<saml:Subject>
			<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">[email protected]</saml:NameID>
			<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml:SubjectConfirmationData NotOnOrAfter="2017-03-24T22:58:38.347Z" Recipient="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0"/>
			</saml:SubjectConfirmation>
		</saml:Subject>
		<saml:Conditions NotBefore="1997-09-29T06:14:00.000Z" NotOnOrAfter="2004-07-25T22:18:00.000Z">
			<saml:AudienceRestriction>
				<saml:Audience>app.launchdarkly.com</saml:Audience>
			</saml:AudienceRestriction>
		</saml:Conditions>
		<saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
			<saml:Attribute Name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="Email">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="FirstName">
				<saml:AttributeValue xsi:type="xs:anyType">Jane</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="LastName">
				<saml:AttributeValue xsi:type="xs:anyType">Doe</saml:AttributeValue>
			</saml:Attribute>
		</saml:AttributeStatement>
		<saml:AuthnStatement AuthnInstant="2017-03-24T21:58:38.347Z">
			<saml:AuthnContext>
				<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
			</saml:AuthnContext>
		</saml:AuthnStatement>
	</saml:Assertion>
</samlp:Response>
  • Created SAMLResponse that changes the contents of samlp:StatusCode to 'Failure'
<?xml version="1.0" ?>
<samlp:Response Destination="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0" ID="_16223f44fcc4370680fb" IssueInstant="2017-03-24T21:58:41Z" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
	<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">idp.oktadev.com</saml:Issuer>
	<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
		<ds:SignedInfo>
			<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
			<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
			<ds:Reference URI="">
				<ds:Transforms>
					<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
					<ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
				<ds:DigestValue>o7uuTeqwDts5SjXd5Q9b+uxD42lLJQaj5nBBkwLHNx4=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>r2wnckxyJAw28htJ9MJVH136Cx67NziCWB84A0OrRCZHjJylzkOe/tLQ5gGlFUe3PTXgW+aCO7b3mrN92Y50Q04Eho9+z+o4kDOjQaZaD2hw6HiSjnvapMVKNPYvYlVmhHqedekShBaz55XeOTQaDjmRA0c92iDtCpWqFjeaDRM3nL5lm6JPKR52AXKM0j/KK/uuGrVVN9AZ0rE33K8PcHX35nnHc4lzqCFgCqqoNvcJUW7VWT0fnvfWO7g22/ixzulCuXbA49HJakuZkrcEbLid7RKqxRD9LBJTOsWZ91rm50OwMCpnarJ4k7T7jmzv3TD61Mm/LgnttCiWIumzkA==</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate>MIIDPDCCAiQCCQDydJgOlszqbzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEQMA4GA1UEChMHSmFua3lDbzESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE0MDMxMjE5NDYzM1oXDTI3MTExOTE5NDYzM1owYDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEDAOBgNVBAoTB0phbmt5Q28xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGvJpRTTasRUSPqcbqCG+ZnTAurnu0vVpIG9lzExnh11o/BGmzu7lB+yLHcEdwrKBBmpepDBPCYxpVajvuEhZdKFx/Fdy6j5mH3rrW0Bh/zd36CoUNjbbhHyTjeM7FN2yF3u9lcyubuvOzr3B3gX66IwJlU46+wzcQVhSOlMk2tXR+fIKQExFrOuK9tbX3JIBUqItpI+HnAow509CnM134svw8PTFLkR6/CcMqnDfDK1m993PyoC1Y+N4X9XkhSmEQoAlAHPI5LHrvuujM13nvtoVYvKYoj7ScgumkpWNEvX652LfXOnKYlkB8ZybuxmFfIkzedQrbJsyOhfL03cMECAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAeHwzqwnzGEkxjzSD47imXaTqtYyETZow7XwBc0ZaFS50qRFJUgKTAmKS1xQBP/qHpStsROT35DUxJAE6NY1Kbq3ZbCuhGoSlY0L7VzVT5tpu4EY8+Dq/u2EjRmmhoL7UkskvIZ2n1DdERtd+YUMTeqYl9co43csZwDno/IKomeN5qaPc39IZjikJ+nUC6kPFKeu/3j9rgHNlRtocI6S1FdtFz9OZMQlpr0JbUt2T3xS/YoQJn6coDmJL5GTiiKM6cOe+Ur1VwzS1JEDbSS2TWWhzq8ojLdrotYLGd9JOsoQhElmz+tMfCFQUFLExinPAyy7YHlSiVX13QH2XTu/iQQ==</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>
	<samlp:Status>
		<samlp:StatusCode Value="Failure"/>
	</samlp:Status>
	<saml:Assertion ID="_v1MQkIzG5Y4vDlBVo4CA86CEuod36QF6" IssueInstant="2017-03-24T21:58:40.992Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
		<saml:Issuer>idp.oktadev.com</saml:Issuer>
		<saml:Subject>
			<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">[email protected]</saml:NameID>
			<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml:SubjectConfirmationData NotOnOrAfter="2017-03-24T22:58:40.992Z" Recipient="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0"/>
			</saml:SubjectConfirmation>
		</saml:Subject>
		<saml:Conditions NotBefore="2017-03-24T21:58:40.992Z" NotOnOrAfter="2017-03-24T22:58:40.992Z">
			<saml:AudienceRestriction>
				<saml:Audience>app.launchdarkly.com</saml:Audience>
			</saml:AudienceRestriction>
		</saml:Conditions>
		<saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
			<saml:Attribute Name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="Email">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="FirstName">
				<saml:AttributeValue xsi:type="xs:anyType">Jane</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="LastName">
				<saml:AttributeValue xsi:type="xs:anyType">Doe</saml:AttributeValue>
			</saml:Attribute>
		</saml:AttributeStatement>
		<saml:AuthnStatement AuthnInstant="2017-03-24T21:58:40.992Z">
			<saml:AuthnContext>
				<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
			</saml:AuthnContext>
		</saml:AuthnStatement>
	</saml:Assertion>
</samlp:Response>
  • Created SAMLResponse that changes the conents of samlp:StatusCode to 'urn:oasis:names:tc:SAML:2.0:status:Requester'
<?xml version="1.0" ?>
<samlp:Response Destination="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0" ID="_24582fac1560df7ea0d2" IssueInstant="2017-03-24T21:58:41Z" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
	<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">idp.oktadev.com</saml:Issuer>
	<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
		<ds:SignedInfo>
			<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
			<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
			<ds:Reference URI="">
				<ds:Transforms>
					<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
					<ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
				</ds:Transforms>
				<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
				<ds:DigestValue>hDuyacRyffzisWMz0QW3uIB7+ZYnqVFonU7ckjbh/34=</ds:DigestValue>
			</ds:Reference>
		</ds:SignedInfo>
		<ds:SignatureValue>mXHkgcPnJBxGeA2RlZkwzFAaNNUejP+ZEOO58ObW2U2qYItEZvzeH11WYuNrFJs4dN9b1eqH5U7rW26BegL24a0RfDGMxsRnPl+/CZaekGYdLScldap26KdFPMLC2YTIYoyA0HhV+vQm0/Wu2t574gnp4JtxfxFtyPmWUAg15nwt9SQKBhp96tiAt6jsFuMfjmTchknGWcIXcwocPUfngpY8gs6lMms5/3NP8g+8OMhTGm0EXg2Y0vq7yhvioLk8y6AFBwy2qiZlxK0ypSiHjwB6T42yPL7FzuEOicLFhoC8NT5AeQ4J7m9iO/JkmeQ4wa4fyLKVHwdFMA6hfZK0xA==</ds:SignatureValue>
		<ds:KeyInfo>
			<ds:X509Data>
				<ds:X509Certificate>MIIDPDCCAiQCCQDydJgOlszqbzANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEQMA4GA1UEChMHSmFua3lDbzESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTE0MDMxMjE5NDYzM1oXDTI3MTExOTE5NDYzM1owYDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEDAOBgNVBAoTB0phbmt5Q28xEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGvJpRTTasRUSPqcbqCG+ZnTAurnu0vVpIG9lzExnh11o/BGmzu7lB+yLHcEdwrKBBmpepDBPCYxpVajvuEhZdKFx/Fdy6j5mH3rrW0Bh/zd36CoUNjbbhHyTjeM7FN2yF3u9lcyubuvOzr3B3gX66IwJlU46+wzcQVhSOlMk2tXR+fIKQExFrOuK9tbX3JIBUqItpI+HnAow509CnM134svw8PTFLkR6/CcMqnDfDK1m993PyoC1Y+N4X9XkhSmEQoAlAHPI5LHrvuujM13nvtoVYvKYoj7ScgumkpWNEvX652LfXOnKYlkB8ZybuxmFfIkzedQrbJsyOhfL03cMECAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAeHwzqwnzGEkxjzSD47imXaTqtYyETZow7XwBc0ZaFS50qRFJUgKTAmKS1xQBP/qHpStsROT35DUxJAE6NY1Kbq3ZbCuhGoSlY0L7VzVT5tpu4EY8+Dq/u2EjRmmhoL7UkskvIZ2n1DdERtd+YUMTeqYl9co43csZwDno/IKomeN5qaPc39IZjikJ+nUC6kPFKeu/3j9rgHNlRtocI6S1FdtFz9OZMQlpr0JbUt2T3xS/YoQJn6coDmJL5GTiiKM6cOe+Ur1VwzS1JEDbSS2TWWhzq8ojLdrotYLGd9JOsoQhElmz+tMfCFQUFLExinPAyy7YHlSiVX13QH2XTu/iQQ==</ds:X509Certificate>
			</ds:X509Data>
		</ds:KeyInfo>
	</ds:Signature>
	<samlp:Status>
		<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester"/>
	</samlp:Status>
	<saml:Assertion ID="_dINDjicytb7BCCZGjo6JHXqfDTjlMnKm" IssueInstant="2017-03-24T21:58:41.740Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
		<saml:Issuer>idp.oktadev.com</saml:Issuer>
		<saml:Subject>
			<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">[email protected]</saml:NameID>
			<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
				<saml:SubjectConfirmationData NotOnOrAfter="2017-03-24T22:58:41.740Z" Recipient="https://4ee49844.ngrok.io/api/sso/saml2/acs/58d4b05673d4f375b8e70fa0"/>
			</saml:SubjectConfirmation>
		</saml:Subject>
		<saml:Conditions NotBefore="2017-03-24T21:58:41.740Z" NotOnOrAfter="2017-03-24T22:58:41.740Z">
			<saml:AudienceRestriction>
				<saml:Audience>app.launchdarkly.com</saml:Audience>
			</saml:AudienceRestriction>
		</saml:Conditions>
		<saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
			<saml:Attribute Name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="Email">
				<saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="FirstName">
				<saml:AttributeValue xsi:type="xs:anyType">Jane</saml:AttributeValue>
			</saml:Attribute>
			<saml:Attribute Name="LastName">
				<saml:AttributeValue xsi:type="xs:anyType">Doe</saml:AttributeValue>
			</saml:Attribute>
		</saml:AttributeStatement>
		<saml:AuthnStatement AuthnInstant="2017-03-24T21:58:41.740Z">
			<saml:AuthnContext>
				<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
			</saml:AuthnContext>
		</saml:AuthnStatement>
	</saml:Assertion>
</samlp:Response>

Invalid Signature

The lib is generating wrong digest value and siganture when the Id is in subelement of the XML, if we put the ID in root of the document it works.

XML sample

<test><subelement Id="123"></subelement></test>

DigestValue generated is <DigestValue>NW8608eQ8/D7oW+DkK4APEcoSmQ=</DigestValue>

correct digest value is <DigestValue>Yyr4tGjKVRhghWuw38f3gwZwt3g=</DigestValue>, I'm comparing with a Lib I use for Python, I'd like to implement it in Go.

so, if I use the xml below it works

<test  Id="123"><subelement></subelement></test>

I tried to undesrtand and modify something here https://github.com/russellhaering/goxmldsig/blob/master/canonicalize.go#L135 and here https://github.com/russellhaering/goxmldsig/blob/master/canonicalize.go#L167 with no luck, I coudn't undesrtand the reason it's changing digest value if ID is not on the root of the document

This would be the correct signature

<?xml version="1.0" encoding="UTF-8"?>
<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="#123">
         <Transforms>
            <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
            <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
         </Transforms>
         <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
         <DigestValue>Yyr4tGjKVRhghWuw38f3gwZwt3g=</DigestValue>
      </Reference>
   </SignedInfo>
   <SignatureValue>FYHaTric4WHTcULweGeTNmXByHAxbfA2YMThFbWsnymQSuM/2sh0IUq8MGw3h/o37FumeMdHnSJ/hC9VpmZaCFq2lyVoGhAa72Sbz7euxtqN5zbvBN1O6EfL+CMjHhl06n1esMn86OTI0/XZ0oUtThd6x+VKxzRggwZ8d2T6+VMhzxGugtalKni21u+2HeoEwt+Oi72rkSD52Tm82L/2cuf/IyV16bhLhBifIkCBDtoHTTftDK1Znpu1AW5c4FnQnjh0D6GgQK6HMaf0UqJcyVRns3t3wkJmLUqlKehHrgyA85w/DA3SHtzVXsj+MnDYbZ3h1w7Psev+UnWk66tfAg==</SignatureValue>
   <KeyInfo>
      <X509Data>
         <X509Certificate>MIIIGjCCBgKgAwIBAgIIY7m57qeJkQMwDQYJKoZIhvcNAQELBQAwezELMAkGA1UE
BhMCQlIxEzARBgNVBAoTCklDUC1CcmFzaWwxNjA0BgNVBAsTLVNlY3JldGFyaWEg
ZGEgUmVjZWl0YSBGZWRlcmFsIGRvIEJyYXNpbCAtIFJGQjEfMB0GA1UEAxMWQUMg
Q09OU1VMVEkgQlJBU0lMIFJGQjAeFw0xOTExMjExMzM3MzVaFw0yMDExMjExMzM3
MzVaMIHzMQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDELMAkGA1UE
CBMCUk4xEDAOBgNVBAcTB01PU1NPUj8xNjA0BgNVBAsTLVNlY3JldGFyaWEgZGEg
UmVjZWl0YSBGZWRlcmFsIGRvIEJyYXNpbCAtIFJGQjEWMBQGA1UECxMNUkZCIGUt
Q05QSiBBMTEXMBUGA1UECxMOMTIwNzM3NDMwMDAxNzAxRzBFBgNVBAMTPkNBU0Eg
RE8gQ09OU1RSVVRPUiBNQVRFUklBSVMgREUgQ09OU1RSVUNBTyBMVERBOjE5ODQz
NjU3MDAwMTQ5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuq6a8xin
3KPto4rhLoT10Nkd8gqMrZMWN/G7p4mw9pDcxWPvugIGjKIPgAqr1spvh4Nosvuk
ugXuj8vObI5ZAmk6aGJnLcz9sqYKwBgI1cxr2Ac7ufZ9ia0ScFDPTfJEVerZLxyD
6B51AGruyxjvwDGSC/i3m51v/xFvkK1VNhnici5QBCiU18/3rtyw2p52lT9tlnmc
fiiMAM2onNq3Wc91suKOvEMj9MW/QEsZdngMEQ1MiUlxtJ90Inw2M8WPgmCtVEqd
IofxVrvhb6UXGUnzEmCurZXR/ZwGgyioeqU4dglRn2zrHGMqzYExLuS6n3BeAq05
EjWJTGOpFJV2qQIDAQABo4IDJzCCAyMwHwYDVR0jBBgwFoAUrvGhcHYTavvnlHec
MixXyxQ4Wd8wDgYDVR0PAQH/BAQDAgXgMIGABgNVHSAEeTB3MHUGBmBMAQIBQTBr
MGkGCCsGAQUFBwIBFl1odHRwOi8vcmVwb3NpdG9yaW8uYWNjb25zdWx0aWJyYXNp
bC5jb20uYnIvYWMtYWNjb25zdWx0aWJyYXNpbHJmYi9kcGMtYWNjb25zdWx0aWJy
YXNpbHJmYi5wZGYwgeAGA1UdHwSB2DCB1TBooGagZIZiaHR0cDovL3JlcG9zaXRv
cmlvLmFjY29uc3VsdGlicmFzaWwuY29tLmJyL2FjLWFjY29uc3VsdGlicmFzaWxy
ZmIvbGNyLWFjLWFjY29uc3VsdGlicmFzaWxyZmJ2NC5jcmwwaaBnoGWGY2h0dHA6
Ly9yZXBvc2l0b3JpbzIuYWNjb25zdWx0aWJyYXNpbC5jb20uYnIvYWMtYWNjb25z
dWx0aWJyYXNpbHJmYi9sY3ItYWMtYWNjb25zdWx0aWJyYXNpbHJmYnY0LmNybDCB
rQYIKwYBBQUHAQEEgaAwgZ0wagYIKwYBBQUHMAKGXmh0dHA6Ly9yZXBvc2l0b3Jp
by5hY2NvbnN1bHRpYnJhc2lsLmNvbS5ici9hYy1hY2NvbnN1bHRpYnJhc2lscmZi
L2FjLWFjY29uc3VsdGlicmFzaWxyZmJ2NC5wN2IwLwYIKwYBBQUHMAGGI2h0dHA6
Ly9vY3NwLmFjY29uc3VsdGlicmFzaWwuY29tLmJyMIG6BgNVHREEgbIwga+BFlRJ
VElDTzE5NTNASE9UTUFJTC5DT02gJwYFYEwBAwKgHhMcTUFSSUEgREUgRkFUSU1B
IEJFWkVSUkEgTElNQaAZBgVgTAEDA6AQEw4xOTg0MzY1NzAwMDE0OaA4BgVgTAED
BKAvEy0yOTA5MTk1MzEzMTAxOTQzNDM0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
MDCgFwYFYEwBAwegDhMMMDAwMDAwMDAwMDAwMB0GA1UdJQQWMBQGCCsGAQUFBwMC
BggrBgEFBQcDBDANBgkqhkiG9w0BAQsFAAOCAgEAccSve2usWDae/iWS/olz5HvE
tb7Li89dj27nv4vOHSDE5flGFZOdWbDUvCSP5slaDBhdwRSo+ZVd85nq6VBcbUnm
VyqU+biF2YP4RCnHOCMpCUx0uG/AW1eIZ8F32u2BdoeqQG5moYznfCk6ImAwtOPG
u6DHhP4DXKg0Xk3Lbn5VHD4/0ShATBBN+1gDn3DHGNmEcOgW15NwIm2otI6dUE50
l+Qhwiy7jqHXlazrbVdUmIR/y3DIEqBtcjPPEiUxZEDo/ijNyqOrn/AAM8WguAti
oexNu8tJhUIFJLM6J/+ojaoQKwPOggw4m8I58nTsvq3PnsAWb1t69OUfltn3YXbO
/BfF3fvVcbMGpq4kISGNn1BssgcNia8+FSL3Uijzt6rL+63PmlCzPNd8zcbBSdAY
qEhJpOReQxEf+uVxEWtxFX2cC3yPxfW4axvCpsF2m7QI3w3+FkHIsMLtE6bKyMBW
R9LUF5iJ/IDZK3JId0ijsk0p7W5xnWCMFpnej5F5G6q75SLcxuEPdRjON6kzXr8P
RIFaeyzPHzm25MkdRPzEOBV+bNHZkhGCY8UfiS03qElNcjsKBFjdPoGuNM+/0NR/
9MnkzJ1jx8K+WEaMR/3WKRicXY7Yzs1wFFzg3lWpImTIbgBABBlIRJtbVlAnfMUG
GkZpOXJM/XrVtzLssL8=</X509Certificate>
      </X509Data>
   </KeyInfo>
</Signature>

this is my code used to generated the signature

ctx := dsig.NewDefaultSigningContext(keyStore)
	ctx.Canonicalizer = dsig.MakeC14N10RecCanonicalizer()
	ctx.Hash = crypto.SHA1
	ctx.IdAttribute = "Id"
	ctx.ElementContainId = "subelement"
	ctx.Prefix = ""

	doc := etree.NewDocument()
	err = doc.ReadFromString(xml)
	failOnError(err, "Lendo string xml")

	element := doc.FindElements("//")[0]
	signedElement, err := ctx.SignEnveloped(element)
	signatureElement := signedElement.FindElements("//Signature")[0]
	doc.SetRoot(signatureElement)
	//nfeElement := doc.FindElements("//NFe")[0]
	//nfeElement.Child = append(nfeElement.Child, signatureElement)
	signedXml, err := doc.WriteToString()
	return signedXml

I changed line 95 for it get the id based on the ElementContainId field I added

dataId := el.FindElement("//"+ctx.ElementContainId).SelectAttrValue(ctx.IdAttribute, "")

Facing issue in validating the signature of the xml file.

I use below code to verify the signature of the xml file. But, it gives me error:- Could not verify certificate against trusted certs


func ValidateXMLSignature(xmlData []byte, publicKey string) (bool, error) {
	doc := etree.NewDocument()
	err := doc.ReadFromBytes(xmlData)
	if err != nil {
		return false, err
	}
        block, _ := pem.Decode([]byte(aadhaarLatestPublicKey))
	pub, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return false, err
	}
	ctx := goxmldsig.NewDefaultValidationContext(&goxmldsig.MemoryX509CertificateStore{
		Roots: []*x509.Certificate{pub},
	})
	if el := doc.FindElement("OfflinePaperlessKyc"); el != nil {
		_, err = ctx.Validate(el)
		if err != nil {
			helpers.Logger.Errorf("error in validating xml signature:%s", err.Error())
			return false, nil
		}
		return true, nil
	}
	return false, nil
}
const aadhaarLatestPublicKey = `-----BEGIN CERTIFICATE-----
MIIG7jCCBdagAwIBAgIEAv5vUzANBgkqhkiG9w0BAQsFADCB4jELMAkGA1UEBhMCSU4xLTArBgNVBAoTJENhcHJpY29ybiBJZGVudGl0eSBTZXJ2aWNlcyBQdnQgTHRkLjEdMBsGA1UECxMUQ2VydGlmeWluZyBBdXRob3JpdHkxDzANBgNVBBETBjExMDA5MjEOMAwGA1UECBMFREVMSEkxJzAlBgNVBAkTHjE4LExBWE1JIE5BR0FSIERJU1RSSUNUIENFTlRFUjEfMB0GA1UEMxMWRzUsVklLQVMgREVFUCBCVUlMRElORzEaMBgGA1UEAxMRQ2Fwcmljb3JuIENBIDIwMTQwHhcNMjAwNTI3MDUwMzA1WhcNMjMwNTI3MDUwMzA1WjCCARAxCzAJBgNVBAYTAklOMQ4wDAYDVQQKEwVVSURBSTEaMBgGA1UECxMRVGVjaG5vbG9neSBDZW50cmUxDzANBgNVBBETBjU2MDA5MjESMBAGA1UECBMJS2FybmF0YWthMRIwEAYDVQQJEwliYW5nYWxvcmUxOzA5BgNVBDMTMlVJREFJIFRlY2ggQ2VudHJlLCBBYWRoYXIgQ29tcGxleCwgTlRJIExheW91dCwgVGF0MUkwRwYDVQQFE0BiMTlhODdmYWU3YWU5ZWY1NWZmMTY2YjVjYzYyNTcwMGUyOGQ4MmRhNzZiZDUzZjA5ODM2ZWVhZWFiM2ZlMzg1MRQwEgYDVQQDEwtEUyBVSURBSSAwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANSINogOm/Y3pyz0xqILE4C8eJ79af1dk9Kt0QWuICQyq2beNWzBFml5BVBLjeUvjbWbz2zv4yY9lotTb0kKlWEwP+yctIVVDliaWHr+/zxcwAFDoJKLULJokvIYaUeSDrLDvtSq2K3eypIvmS5Df/T6miBJKyYbxDj+8LTZxeSXh12xBUs9X6RxkWSM2cqIJkPPb2mPYFwchtTCczapaUYaGoQB6mbbwW1PQR6qXxUBVefFe373sGh3Pyty0bOOw/NBYHLES1p+3jUXSp2ovqMxsEEIq0c/oCjjhbJYUKa0190EhZDyTYojGuNsD4VCb7jJk1xN67szEKyYQ2Ld/40CAwEAAaOCAnkwggJ1MEAGA1UdJQQ5MDcGCisGAQQBgjcUAgIGCCsGAQUFBwMEBggrBgEFBQcDAgYKKwYBBAGCNwoDDAYJKoZIhvcvAQEFMBMGA1UdIwQMMAqACEOABKAHteDPMIGIBggrBgEFBQcBAQR8MHowLAYIKwYBBQUHMAGGIGh0dHA6Ly9vY3ZzLmNlcnRpZmljYXRlLmRpZ2l0YWwvMEoGCCsGAQUFBzAChj5odHRwczovL3d3dy5jZXJ0aWZpY2F0ZS5kaWdpdGFsL3JlcG9zaXRvcnkvQ2Fwcmljb3JuQ0EyMDE0LmNlcjCB+AYDVR0gBIHwMIHtMFYGBmCCZGQCAzBMMEoGCCsGAQUFBwICMD4aPENsYXNzIDMgQ2VydGlmaWNhdGUgaXNzdWVkIGJ5IENhcHJpY29ybiBDZXJ0aWZ5aW5nIEF1dGhvcml0eTBEBgZggmRkCgEwOjA4BggrBgEFBQcCAjAsGipPcmdhbml6YXRpb25hbCBEb2N1bWVudCBTaWduZXIgQ2VydGlmaWNhdGUwTQYHYIJkZAEKAjBCMEAGCCsGAQUFBwIBFjRodHRwczovL3d3dy5jZXJ0aWZpY2F0ZS5kaWdpdGFsL3JlcG9zaXRvcnkvY3BzdjEucGRmMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHBzOi8vd3d3LmNlcnRpZmljYXRlLmRpZ2l0YWwvY3JsL0NhcHJpY29ybkNBLmNybDARBgNVHQ4ECgQITfksz0HaUFUwDgYDVR0PAQH/BAQDAgbAMCIGA1UdEQQbMBmBF2FudXAua3VtYXJAdWlkYWkubmV0LmluMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggEBACED9DwfU+qImzRkqc4FLN1ED4wgKXsvqwszJrvKKjwiQSxILTcapKPaTuW51HTlKOYUDmQH8MXGWLYjnyJDp/gpj6thcuwiXRFL87UarUMDd5A+dBn4UPkUSuThn+CjrhGQcStaKSz5QfzdOO/2fZeZgDB0xo7IyDtVfC2ZvW1xrxWngKNVkp8XkPNmPW/jHk7395/1obaHsjKNcAaAxNztXGG6azwsURx83Fy6irF4pHFTfZV3Y93iBZovXeetYc1bgIAvLSFd2Yvuy6yGyL8nb8vUMbWYIasZ47E4q+kMDmB49xedQg97L5CRfN0gIrk7foxnTexvSlLtEVo2M/A=
-----END CERTIFICATE-----`

Format of the xml file:-

<OfflinePaperlessKyc referenceId="">
<UidData>
<Poi dob="" gender="" name="" e="" m=""/>
<Poa careof="" country="" dist="" house="" loc="" pc="" po="" state="" street="" subdist="" vtc="" />
<Pht></Pht>
</UidData>
<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/2001/04/xmlenc#sha256" />
<DigestValue></DigestValue>
</Reference>
</SignedInfo>
<SignatureValue></SignatureValue>
<KeyInfo>
</KeyInfo>
</Signature>

</OfflinePaperlessKyc>```

XML namespace invalidating signature

I have attempted to sign a entities descriptor element, but I have not been able to use xmlsectool to validate the result:

xmlsectool.sh --verifySignature --certificate saml.crt --inFile example.xml
INFO  XMLSecTool - Reading XML document from file 'example.xml'
INFO  XMLSecTool - XML document parsed and is well-formed.
WARN  Reference - Verification failed for URI "#id1234"
WARN  Reference - Expected Digest: D+SEh34cA7/atdQ8ojV9rzUcJcJSAslFZ0aOIwplGfI=
WARN  Reference - Actual Digest: EYun0wngsN35ci20wRziCXs0Io7J4bZN+NYRnnTR5QM=
ERROR XMLSecTool - XML document signature verification failed

Could you provide any pointers as to where I am going wrong?

package main

import (
	"crypto/tls"
	"io/ioutil"
	"log"

	"github.com/beevik/etree"
	"github.com/russellhaering/goxmldsig"
)

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
	}
}

func main() {
	certBytes := []byte(`-----BEGIN CERTIFICATE-----
MIID3TCCAsWgAwIBAgIJAKMxnSbqmztEMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYD
VQQGEwJHQjETMBEGA1UECAwKQmlybWluZ2hhbTETMBEGA1UEBwwKQmlybWluZ2hh
bTEOMAwGA1UECgwFVGFsaXMxDjAMBgNVBAsMBVRhbGlzMQ4wDAYDVQQDDAVUYWxp
czEbMBkGCSqGSIb3DQEJARYMbXdAdGFsaXMuY29tMB4XDTE3MDgwODIxNTA0NFoX
DTI3MDgwNjIxNTA0NFowgYQxCzAJBgNVBAYTAkdCMRMwEQYDVQQIDApCaXJtaW5n
aGFtMRMwEQYDVQQHDApCaXJtaW5naGFtMQ4wDAYDVQQKDAVUYWxpczEOMAwGA1UE
CwwFVGFsaXMxDjAMBgNVBAMMBVRhbGlzMRswGQYJKoZIhvcNAQkBFgxtd0B0YWxp
cy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCfyQiwTxAbc6HJ
6aB6NrmDYoVUBqWZ4njZyQqnhf0ZvpqGh8ppMiXjiuJjn72pJYHnOqRQNgJDNhAZ
X5KtJ/YI4XbOruJU3TWX/KnGn7l8TJ5FFmnJWHohJ0f9/+uVv0hivRkSVUwh+q2e
TpKNypNu2Kf8iiGW3dMOY1CYWxWnksM1xoaWKV3mWgMqRqcj4kyLT1t8UctOhKhg
m04HPNTeFCkcmH3IuIiVAi3uVU+zDKec8+cxSHHmnm0iphm8jpT0OjNSGWt7F7+N
NhIa2FOI+Lz6t+VU0WToWnB16qJIhMGcIGPZR7fp/di/0h9Huc+GJBNfbgdVEYiv
7DuF28zzAgMBAAGjUDBOMB0GA1UdDgQWBBRjnMEGZsZR+cSX5/UJcwAZULsKijAf
BgNVHSMEGDAWgBRjnMEGZsZR+cSX5/UJcwAZULsKijAMBgNVHRMEBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQBNrPOgLt1bZPO8283HddeASfzoVK40qqBP0HgLihja
VvABPRkE2046lka6MSDXJTpbg9rMT/JDplWea4gCroD+UX79W/r2WBEHgJ63piq+
wVFoxB4S8IgbQi2N5CEM/yLexWq9O2YDl7gemRc1EES01x64YBlBgHGpMvc6NyjD
ecMdTmUAXgNTTGKlpistVRtArQHaqw3FJE3LfoyEx9fP0joA7Q5U7Z6pvveYXEHl
fSoCeI4UUPOlAGBOR5VWnDYuS+FwB9RIcegycxB12Sd+RLxojpFg6VSk2SSiG9/4
u02uKxgXiZ7/41lHjoTHS9BOoPOT0ZD8C7Goeg8OAMgs
-----END CERTIFICATE-----`)

	keyBytes := []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAn8kIsE8QG3Ohyemgeja5g2KFVAalmeJ42ckKp4X9Gb6ahofK
aTIl44riY5+9qSWB5zqkUDYCQzYQGV+SrSf2COF2zq7iVN01l/ypxp+5fEyeRRZp
yVh6ISdH/f/rlb9IYr0ZElVMIfqtnk6SjcqTbtin/Iohlt3TDmNQmFsVp5LDNcaG
lild5loDKkanI+JMi09bfFHLToSoYJtOBzzU3hQpHJh9yLiIlQIt7lVPswynnPPn
MUhx5p5tIqYZvI6U9DozUhlrexe/jTYSGthTiPi8+rflVNFk6FpwdeqiSITBnCBj
2Ue36f3Yv9IfR7nPhiQTX24HVRGIr+w7hdvM8wIDAQABAoIBADrEjdWKvrnaBZ9l
tgg9KG4SRkdpSm8WxKwVLT4AId7eI6dnOiMGtrjB1BIgJnmXufd5sgVuV9awg6tR
Y3kcQXlys2fBGq1rztJfs3HCPU5iP7PZUn8jc4fOEsRw5AznlY/7TMVZae71a/XV
oEFWSHN0bBSOGVyLqZyZGoNuvMAsvZ7ObmfAddLQerPV0nOvv9X332wgo2a+8rnb
NHqcZOLdmGjJRkBbAd0IHFciynb1YlhHIEObmZzD8LVFV0UxhhPDHbRwmrj1T2+j
u9U3rBduJKG+mQxelLOLUB6CNbvcyNtj3wAnyq6IVA9qb/CLXJbEhTgnvNTLnYA3
FJxZysECgYEAzw67MVhQY1VZnN49NiXhhl6ypVIlp3fKOUMMZVgiUeSDPSs4Un9q
ABoFBHT9x/Rs6repl/Yr6V3o8uWz/7V7yArom9/yhErunW8bORfiGVUqibYIKi51
qNJMpamQGI/Uw2AbKCjKhpnCcRjt0YTfuTWXxAxOPYNJZqXEvUaUoNUCgYEAxY3P
H07aR2zTDfjvddG2eieaMLoaTWSuGTUH1P7KplQHEsoE135PyLayzYy5I2HX+JDn
fUDDWXWeI4+NdGdUnRrXOedr/Rewu8RZFxxqBV0TJhmTJzGpoun08YXkj7CBCs60
faohJS5iSpi39XNf2k5/RJHGm2FePfPYQR7sWqcCgYEAx6LYcZdIyr18DXdpZU/Y
xgmADU3K6FDjNZqj1QLI9FRzBQMq5r/aoAZ2V/nExomwig5TAiVj6TmWZLt8dUux
8QozhDbESTFGJ5z8jmusn+gxf113OdRZtVAufnuiZ0wmQ8nh5TKPMoAFra3vfley
rYwyq9+BgGWY29NwgV4P55ECgYB5ThRqkw6xYP9PyxWu8PDtnTeux/eyoinNTKTc
gv+Ilnwpa2cBs4vmIVk1oj1knoXxGXkrjgLmAbTy/QjM+04Xkg2qfpHuvQdGpNBX
wpjPZlGFyZp0LKiPYr2HOMIaATWbn0VxDHCB1jOAvrnmu8uVzzGStziO3IDz5bFa
e1SCbQKBgGNUKKppH7BYDMrb+dqRsB6YI5mFlHZoDhVWkPgDba8klp/NvhTI8ACu
URVaPLlgTRdiG2Q5NVDYPpTrhsCbKwE6HeshNKqhL/VsrK77/oSpSQHeLf88oBV2
rDFpN/In31Wp6c+C4crPQNSWZ9jMohHQkCFOUAyBc6UzcqCa4vqd
-----END RSA PRIVATE KEY-----`)

	xmlBytes := []byte(`<EntitiesDescriptor Name="https://your-federation.org/metadata/federation-name.xml" xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><EntityDescriptor entityID="https://idp.example.org/idp/shibboleth"><IDPSSODescriptor protocolSupportEnumeration="urn:mace:shibboleth:1.0 urn:oasis:names:tc:SAML:2.0:protocol"><Extensions><shibmd:Scope regexp="false">example.org</shibmd:Scope></Extensions><KeyDescriptor><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIEKjCCAxKgAwIBAgIJAIgUuHL4QvkYMA0GCSqGSIb3DQEBBQUAMGsxCzAJBgNVq1og9SGCUU2yRL1tC+Y=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></KeyDescriptor><NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat><NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat><SingleSignOnService Binding="urn:mace:shibboleth:1.0:profiles:AuthnRequest" Location="https://idp.example.org/idp/profile/Shibboleth/SSO" /><SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idp.example.org/idp/profile/SAML2/POST/SSO" /><SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://idp.example.org/idp/profile/SAML2/Redirect/SSO" /></IDPSSODescriptor><AttributeAuthorityDescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol"><KeyDescriptor><ds:KeyInfo><ds:X509Data><ds:X509Certificate> MIIEKjCCAxKgAwIBAgIJAIgUuHL4QvkYMA0GCSqGSIb3DQEBBQUAMGsxCzAJBgNVq1og9SGCUU2yRL1tC+Y= </ds:X509Certificate></ds:X509Data></ds:KeyInfo></KeyDescriptor><AttributeService Binding="urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding" Location="https://idp.example.org:8443/idp/profile/SAML1/SOAP/AttributeQuery" /><AttributeService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://idp.example.org:8443/idp/profile/SAML2/SOAP/AttributeQuery" /><NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat><NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat></AttributeAuthorityDescriptor><Organization><OrganizationName xml:lang="en">Your Identities</OrganizationName><OrganizationDisplayName xml:lang="en"> Your Identities</OrganizationDisplayName><OrganizationURL xml:lang="en">http://www.example.org/</OrganizationURL></Organization><ContactPerson contactType="technical"><GivenName>Your</GivenName><SurName>Contact</SurName><EmailAddress>[email protected]</EmailAddress></ContactPerson></EntityDescriptor><EntityDescriptor entityID="https://sp.example.org/shibboleth-sp"><SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol"><Extensions><idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" index="1" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="http://sp.example.org/Shibboleth.sso/DS"/><idpdisc:DiscoveryResponse xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" index="2" Binding="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" Location="https://sp.example.org/Shibboleth.sso/DS"/></Extensions><KeyDescriptor><ds:KeyInfo><ds:X509Data><ds:X509Certificate> MIIEPjCCAyagAwIBAgIBADANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJVUzEVInh+vYSYngQB2sx9LGkR9KHaMKNIGCDehk93Xla4pWJx1w== </ds:X509Certificate></ds:X509Data></ds:KeyInfo></KeyDescriptor><NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat><NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat><AssertionConsumerService index="1" isDefault="true" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sp.example.org/Shibboleth.sso/SAML2/POST"/><AssertionConsumerService index="2" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="https://sp.example.org/Shibboleth.sso/SAML2/POST-SimpleSign"/><AssertionConsumerService index="3" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://sp.example.org/Shibboleth.sso/SAML2/Artifact"/><AssertionConsumerService index="4" Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="https://sp.example.org/Shibboleth.sso/SAML/POST"/><AssertionConsumerService index="5" Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="https://sp.example.org/Shibboleth.sso/SAML/Artifact"/></SPSSODescriptor><Organization><OrganizationName xml:lang="en">Your Service</OrganizationName><OrganizationDisplayName xml:lang="en">Your Service</OrganizationDisplayName><OrganizationURL xml:lang="en">http://sp.example.org/</OrganizationURL></Organization><ContactPerson contactType="technical"><GivenName>Your</GivenName><SurName>Admin</SurName><EmailAddress>[email protected]</EmailAddress></ContactPerson></EntityDescriptor></EntitiesDescriptor>`)
	keyPair, err := tls.X509KeyPair(certBytes, keyBytes)
	failOnError(err, "invalided to load keypair")

	keyStore := dsig.TLSCertKeyStore(keyPair)

	signingContext := dsig.NewDefaultSigningContext(keyStore)
	signingContext.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList("")
	err = signingContext.SetSignatureMethod(dsig.RSASHA256SignatureMethod)
	failOnError(err, "failed to set signature method")

	readXMLDoc := etree.NewDocument()
	err = readXMLDoc.ReadFromBytes(xmlBytes)
	failOnError(err, "cannot parse xml")

	elementToSign := readXMLDoc.Root()
	elementToSign.CreateAttr("ID", "id1234")

	signedElement, err := signingContext.SignEnveloped(elementToSign)
	failOnError(err, "failed to sign envelop")

	var signedAssertionBuf []byte
	{
		readXMLDoc.SetRoot(signedElement)
		signedAssertionBuf, err = readXMLDoc.WriteToBytes()
		failOnError(err, "failed to convert doc to bytes")
	}

	ioutil.WriteFile("/tmp/test/example.xml", signedAssertionBuf, 0775)
}

X509Data element is missing fields

I am trying to sign some ISO 20022 messages and the X509Data type is missing some fields such as X509SubjectName, X509IssuerSerial, X509IssuerName, and X509SerialNumber (among others).

RFC 3075 provides details on the fields and there are references in other projects as well.

Would a PR be accepted with these additional fields?

References Empty URI

For my use case, I wanted empty reference uri = "", but it seems from the code it isn't possible. I would have to assign an id attribute always. Could you provide a fix please ?

Support signing with hardware security modules (HSMs)

We'd like to use HSMs with goxmldsig (and ultimately SAML) for signing, but right now the API requires an RSA private key. I'm not sure if there were any plans to add it, so I've made a pull request #44 that uses the golang crypto.Signer interface to accomplish this. There's also a few minor changes to enable ECDSA signing and verification. I've made the changes to preserve backwards compatibility so existing code won't break.

Please let me know if you have any questions about the use cases or would like a different approach.

How to use for SOAP? (Could not sign: undeclared namespace prefix: 'SOAP-ENV')

I sadly have to build a Soap client that also supports WSSE signing for messages for interaction with some legacy system. I'm looking into this library to see if I can use it to generate the required signature before sending the message off.

The first problem I ran into is that, for signing SOAP messages, only the body element should be signed. But if I try to do that, the signature generator complains that the namespace is not defined. Which is true; the namespace is defined on the envelope, not deeper down.

Test code;

package main

import (
	"crypto/tls"
	"fmt"
	"log"

	"github.com/beevik/etree"
	"github.com/russellhaering/goxmldsig"
)

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
	}
}

func main() {
	certBytes := []byte(`-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
`)

	keyBytes := []byte(`-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
`)

	xmlBytes := []byte(`<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://sys.svc.tennet.nl/MMCHub/v1" xmlns:ns2="http://sys.svc.tennet.nl/MMCHub/Header/v1">
   <SOAP-ENV:Header>
      <ns2:MessageAddressing>
         <ns2:technicalMessageId>0849df0a-1912-11eb-8b2d-6c5d3a074dc2</ns2:technicalMessageId>
         <ns2:senderId>8720299053908</ns2:senderId>
         <ns2:receiverId>8716867999983</ns2:receiverId>
         <ns2:carrierId>8719333014463</ns2:carrierId>
         <ns2:contentType>ACK_ACTIVATED_FCR</ns2:contentType>
      </ns2:MessageAddressing>
   </SOAP-ENV:Header>
   <SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <ns1:getMessageRequest>
         <ns1:technicalMessageId>3c72e741-190e-11eb-86d0-c0b6f97cb937</ns1:technicalMessageId>
      </ns1:getMessageRequest>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>`)

	keyPair, err := tls.X509KeyPair(certBytes, keyBytes)
	failOnError(err, "Invalid keypair")

	keyStore := dsig.TLSCertKeyStore(keyPair)
	ctx := dsig.NewDefaultSigningContext(keyStore)
	ctx.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList("")
	err = ctx.SetSignatureMethod(dsig.RSASHA256SignatureMethod)
	failOnError(err, "Failed to set signature mode")

	readXMLDoc := etree.NewDocument()
	err = readXMLDoc.ReadFromBytes(xmlBytes)
	failOnError(err, "Cannot parse XML doc")

	elementToSign := readXMLDoc.Root().FindElement("Body")
	elementToSign.CreateAttr("ID", "id1234")

	signedElement, err := ctx.SignEnveloped(elementToSign)
	failOnError(err, "Could not sign")

	var signedBuf []byte
	readXMLDoc.SetRoot(signedElement)
	signedBuf, err = readXMLDoc.WriteToBytes()
	failOnError(err, "Failed to write to bytes")

	fmt.Println(string(signedBuf))
}

Errors out with; Could not sign: undeclared namespace prefix: 'SOAP-ENV'

Is there any way to get this to work, or am I trying to do something incredibly unholy here?

Full disclaimer; I know very little about SOAP and only a moderate amount about xml signatures, so perhaps this is a really obvious question. I previously tried to write this client in Python, but an issue in the way it handles signatures makes it not viable. I also built a test implementation in PHP, which works, but I'm extremely reluctant to use that for a production deployment.

Hope someone can help me out a bit here :)

Feedback: More strongly typed errors as means to provide better diagnostics

Not always the error message coming from this package makes sense in a broader context.
That's where our application sometimes struggles to offer a better diagnostic for users.

One example is the error that occurs when the signing certificate differs from the one in the XML document:
Could not verify certificate against trusted certs

The message seems sufficient in this context but we'd love to offer more insights for a quicker resolution, for example stating that signing certificate may need to be updated.

There's always room for improvement in error messages but we have no expectation that this package be responsible for provide such high level diagnostic in all cases. However, providing means for applications to handle errors selectively seems something within the reach of the package.

Currently to achieve this goal, we would have to watch for a particular error message with a logic based on string matching, which tends to be fragile. Instead, we'd rather match a particular error type.

In the last few years, the Go community has been moving in that direction:
https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully
https://golang.org/doc/go1.13#error_wrapping
https://github.com/golang/go/wiki/ErrorValueFAQ

We're looking forward to see strongly typed errors over time.

OAM signature verification

A few issues with OAM (Oracle Access Manager) generated assertions:

  1. Signature does not always reference the top-level element
  2. x509 certificate will not always be contained in the response
  3. xmlns defined at the top level causes canonicalization problems

Signed payload and certificate:
https://gist.github.com/Calpicow/fd1d03ded8dc9da1570155bc14aa689a
https://gist.github.com/Calpicow/ef34701804053d042739137b2efd708a

Expected canonicalization: https://gist.github.com/Calpicow/22062f1cf9283621226c5dee2cb9bb0d
Current canonicalization: https://gist.github.com/Calpicow/405b039350d4efff2537ce2f204b6964

invalid CanonicalizationMethod

I'm trying to validate signed xml, but getting error: invalid CanonicalizationMethod on Signature: w3.org/TR/2001/REC-xml-c14n-20010315. Code below:

package main

import (
	"crypto/x509"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/beevik/etree"
	dsig "github.com/russellhaering/goxmldsig"
)

const (
	rootCertURL = "http://root.gov.kz/root_cer/root_rsa.crt"
	pkiCertURL  = "http://root.gov.kz/root_cer/pki_rsa.crt"
)

func main() {
	roots := getTrustedCerts()
	doc := etree.NewDocument()
	if err := doc.ReadFromString(testXML); err != nil {
		log.Fatalln(err)
	}
	if err := validate(roots, doc.Root()); err != nil {
		log.Fatalln(err)
	}
	log.Println("success")
}

func getTrustedCerts() []*x509.Certificate {
	store := []*x509.Certificate{}
	rootCert, err := downloadCert(rootCertURL)
	if err != nil {
		log.Println(err)
	} else {
		store = append(store, rootCert)
	}
	pkiCert, err := downloadCert(pkiCertURL)
	if err != nil {
		log.Println(err)
	} else {
		store = append(store, pkiCert)
	}
	return store
}

func downloadCert(url string) (*x509.Certificate, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	cert, err := x509.ParseCertificate(body)
	if err != nil {
		return nil, err
	}
	return cert, nil
}

// Validate an element against a root certificate
func validate(roots []*x509.Certificate, el *etree.Element) error {
	// Construct a signing context with one or more roots of trust.
	ctx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
		Roots: roots,
	})
	// 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 {
		return err
	}

	doc := etree.NewDocument()
	doc.SetRoot(validated)
	str, err := doc.WriteToString()
	if err != nil {
		return err
	}

	log.Println(str)
	return nil
}

Signed XML:

<?xml version="1.0" encoding="utf-8" standalone="no"?><root ID="rootID">
                    <name>Ivan</name>
                    <iin>123456789012</iin>
                <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>6b9amiF3pI3EjKBHADPH0xgoqYtewg5+oeovWEaBmzA=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
ost70Ykv++A9Ls4G4T8622d+atoQyA388Ttf7Kc8JocwBBns4ytdlnaYhPfGNLIdQDD+3k6tbEOw
gBEzuW/SEyR/bXkTTFZCdpLdEmfBYa+PY6S+ZtV9TUkces7IQ9OxwiE+3hwo0FmMiBp7DMeJmjC7
XjvaBKJUO4MGRyIAyxn/S0e6rI5GPYRWAAH3dnIyIF+rQOi8I/B8H9+rQ9FZKgtPH4RzxMsj+YQ7
Hp8JgdGuQnzn2mzJuAVGEgFYlN0NxR40vlOrsu1FSfVlR/3OBCxwen+zHwysLeixpXHNIzQ6D1xW
+KRV7iDWK3bLLgJ15F07x7wptO5+0gGOOVr06A==
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIG9DCCBNygAwIBAgIUTFVCYjrFFRdWjgJW0G8fUs6LLk4wDQYJKoZIhvcNAQELBQAwgc4xCzAJ
BgNVBAYTAktaMRUwEwYDVQQHDAzQkNCh0KLQkNCd0JAxFTATBgNVBAgMDNCQ0KHQotCQ0J3QkDFM
MEoGA1UECgxD0KDQnNCaIMKr0JzQldCc0JvQldCa0JXQotCi0IbQmiDQotCV0KXQndCY0JrQkNCb
0KvSmiDSmtCr0JfQnNCV0KLCuzFDMEEGA1UEAww60rDQm9Ci0KLQq9KaINCa0KPTmNCb0JDQndCU
0KvQoNCj0KjQqyDQntCg0KLQkNCb0KvSmiAoUlNBKTAeFw0xNzA3MjcwMzU1MDZaFw0xODA3Mjcw
MzU1MDZaMIHJMSwwKgYDVQQDDCPQkdCQ0JnQotCj0KDQodCr0J3QntCSINCU0JDQndCY0K/QoDEf
MB0GA1UEBAwW0JHQkNCZ0KLQo9Cg0KHQq9Cd0J7QkjEYMBYGA1UEBRMPSUlOOTIwNzI3MzAwMDQ0
MQswCQYDVQQGEwJLWjEVMBMGA1UEBwwM0JDQm9Cc0JDQotCrMRUwEwYDVQQIDAzQkNCb0JzQkNCi
0KsxIzAhBgNVBCoMGtCh0JXQmdCi0JrQkNCh0KvQnNCe0JLQmNCnMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAvW0Lyoex/kkhq5Xb5uCOtEpp4zjc34M5UGftcgmY6FXvlCaPm4415cmk
Kyaz6M+vmsK3T/wH3S2Up5cLKo022BgpBTYg6+lPUQgigYM7PPc20aLySrMg+Gu4HitokrdWgA/H
hjr14HAOFNiEZm7UpeLAhBfuAz/S9TeCct0C/dp75X8K7zOdXX1n/npnMZKMStPVJ94Cbdpprz/O
lNWzk+MGUB5+2yy4k4zBUamyEk8QzsJZID4Hva8ZIwqSXe4gyCe46iPxPZ8EKiwR4Pn6BXj0k7G1
a8A1jYEqc91QMX+L4CCS5M+BeUvbrcdMjNEoy71YG6m9qgNsBGl7WueMawIDAQABo4IByzCCAccw
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggqgw4DAwQBATAPBgNVHSMECDAG
gARVtbTiMB0GA1UdDgQWBBQKnKaePX9Y74pplb7yI5ql8zxiJDBeBgNVHSAEVzBVMFMGByqDDgMD
AgQwSDAhBggrBgEFBQcCARYVaHR0cDovL3BraS5nb3Yua3ovY3BzMCMGCCsGAQUFBwICMBcMFWh0
dHA6Ly9wa2kuZ292Lmt6L2NwczBOBgNVHR8ERzBFMEOgQaA/hh1odHRwOi8vY3JsLnBraS5nb3Yu
a3ovcnNhLmNybIYeaHR0cDovL2NybDEucGtpLmdvdi5rei9yc2EuY3JsMFIGA1UdLgRLMEkwR6BF
oEOGH2h0dHA6Ly9jcmwucGtpLmdvdi5rei9kX3JzYS5jcmyGIGh0dHA6Ly9jcmwxLnBraS5nb3Yu
a3ovZF9yc2EuY3JsMGIGCCsGAQUFBwEBBFYwVDAuBggrBgEFBQcwAoYiaHR0cDovL3BraS5nb3Yu
a3ovY2VydC9wa2lfcnNhLmNlcjAiBggrBgEFBQcwAYYWaHR0cDovL29jc3AucGtpLmdvdi5rejAN
BgkqhkiG9w0BAQsFAAOCAgEAColZth/p4wVdcPU1AHTMhNeyLtSJI4K5A7/NoOsqYsH5qpE89gPI
mxB4NAvtmHD49f/lHLvzeIBh+snO+lfJZYXaWcYwU1+dJRyB/bE+W6vcEa5N79eihSyl9fsQTYcz
jBsXzUx0Sv2vAiZH+RIowSsg/m9+UZDt5eNcL7eqkr/JDs0I5VVYXFKwNP1rPam4jfuJKB9w/bEg
6G6RM0/DGaXxLAimVB6gLQzT1hdQzgG8YOERJxjlTeRUICUiEqFz5mZzlJ6zb2+N7lUCzRu385o1
DeWjRJZaTxFKM9JJv8a6zPjcuFA+PIsDy9GSLby1OfZaJJo/7w4iLtJiYDuyMTXisnOknmVr5LC6
fft4AXOq7zOTn7t5r3T9lb5VmorfnqdqSXrep6c/dlkSlyP2mYhUE3JOSQTraJQH/jjcWH5hfewb
/9kPWqDlTpBnok9pcciRSYOgzqkpe0CJ3ZNyj+YNuL58O+TkV9MOwe8wWrWe8rVYV61E597WJZJ/
m6qKBPYUy+zoRVK/XdYYAMsBC2zHrz8n7Z8k6s9FQo4YLgprMQh6Hcq42PgnCZZGxxJ4wU44STUj
HCtohHNYjhz+sZfKg6KEFPzGJN1O7rYd8q0Gl9vQtKMjIsETZ7BRYbXxuzMVA2CMhxiXJS929qH2
ce48JWaAdMkyzyjcF8t3tVY=
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature></root>

Invalid handling of xml namespace

It would seem as if the xml namespace is not being handled correctly. If I create a signature for the following XML example the signature cannot be validated:

<Organization xmlns="http://www.w3.org/2000/xmlns" ID="id1234">
      <OrganizationName xml:lang="en">Your Identities</OrganizationName>
      <OrganizationDisplayName xml:lang="en">Your Identities</OrganizationDisplayName>
      <OrganizationURL xml:lang="en">http://www.example.org/</OrganizationURL>
</Organization>
~/workspace/xmlsectool/xmlsectool-2.0.0/xmlsectool.sh --verifySignature --certificate saml.crt --inFile test.xml
INFO  XMLSecTool - Reading XML document from file 'test.xml'
INFO  XMLSecTool - XML document parsed and is well-formed.
WARN  Reference - Verification failed for URI "#id1234"
WARN  Reference - Expected Digest: 7G4WNjtqxoFobBdFzQtblVRj6oAFVVA/9Jac8HOioAI=
WARN  Reference - Actual Digest: nisb5vb0nPW3Ajd6bkypeJ0QZIEC5VZ2cALuW4lUqYg=
ERROR XMLSecTool - XML document signature verification failed

Whereas the following XML can be verified:

<Organization xmlns="http://www.w3.org/2000/xmlns" ID="id1234">
      <OrganizationName>Your Identities</OrganizationName>
      <OrganizationDisplayName>Your Identities</OrganizationDisplayName>
      <OrganizationURL>http://www.example.org/</OrganizationURL>
</Organization>
~/workspace/xmlsectool/xmlsectool-2.0.0/xmlsectool.sh --verifySignature --certificate saml.crt --inFile test.xml
INFO  XMLSecTool - Reading XML document from file 'test.xml'
INFO  XMLSecTool - XML document parsed and is well-formed.
INFO  XMLSecTool - XML document signature verified.

Below is the minimum amount of code to demonstrate the issue:

package main

import (
	"crypto/tls"
	"fmt"
	"log"

	"github.com/beevik/etree"
	"github.com/russellhaering/goxmldsig"
)

func failOnError(err error, msg string) {
	if err != nil {
		log.Fatalf("%s: %s", msg, err)
	}
}

func main() {
	certBytes := []byte(`-----BEGIN CERTIFICATE-----
MIID3TCCAsWgAwIBAgIJAKMxnSbqmztEMA0GCSqGSIb3DQEBCwUAMIGEMQswCQYD
VQQGEwJHQjETMBEGA1UECAwKQmlybWluZ2hhbTETMBEGA1UEBwwKQmlybWluZ2hh
bTEOMAwGA1UECgwFVGFsaXMxDjAMBgNVBAsMBVRhbGlzMQ4wDAYDVQQDDAVUYWxp
czEbMBkGCSqGSIb3DQEJARYMbXdAdGFsaXMuY29tMB4XDTE3MDgwODIxNTA0NFoX
DTI3MDgwNjIxNTA0NFowgYQxCzAJBgNVBAYTAkdCMRMwEQYDVQQIDApCaXJtaW5n
aGFtMRMwEQYDVQQHDApCaXJtaW5naGFtMQ4wDAYDVQQKDAVUYWxpczEOMAwGA1UE
CwwFVGFsaXMxDjAMBgNVBAMMBVRhbGlzMRswGQYJKoZIhvcNAQkBFgxtd0B0YWxp
cy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCfyQiwTxAbc6HJ
6aB6NrmDYoVUBqWZ4njZyQqnhf0ZvpqGh8ppMiXjiuJjn72pJYHnOqRQNgJDNhAZ
X5KtJ/YI4XbOruJU3TWX/KnGn7l8TJ5FFmnJWHohJ0f9/+uVv0hivRkSVUwh+q2e
TpKNypNu2Kf8iiGW3dMOY1CYWxWnksM1xoaWKV3mWgMqRqcj4kyLT1t8UctOhKhg
m04HPNTeFCkcmH3IuIiVAi3uVU+zDKec8+cxSHHmnm0iphm8jpT0OjNSGWt7F7+N
NhIa2FOI+Lz6t+VU0WToWnB16qJIhMGcIGPZR7fp/di/0h9Huc+GJBNfbgdVEYiv
7DuF28zzAgMBAAGjUDBOMB0GA1UdDgQWBBRjnMEGZsZR+cSX5/UJcwAZULsKijAf
BgNVHSMEGDAWgBRjnMEGZsZR+cSX5/UJcwAZULsKijAMBgNVHRMEBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQBNrPOgLt1bZPO8283HddeASfzoVK40qqBP0HgLihja
VvABPRkE2046lka6MSDXJTpbg9rMT/JDplWea4gCroD+UX79W/r2WBEHgJ63piq+
wVFoxB4S8IgbQi2N5CEM/yLexWq9O2YDl7gemRc1EES01x64YBlBgHGpMvc6NyjD
ecMdTmUAXgNTTGKlpistVRtArQHaqw3FJE3LfoyEx9fP0joA7Q5U7Z6pvveYXEHl
fSoCeI4UUPOlAGBOR5VWnDYuS+FwB9RIcegycxB12Sd+RLxojpFg6VSk2SSiG9/4
u02uKxgXiZ7/41lHjoTHS9BOoPOT0ZD8C7Goeg8OAMgs
-----END CERTIFICATE-----`)

	keyBytes := []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAn8kIsE8QG3Ohyemgeja5g2KFVAalmeJ42ckKp4X9Gb6ahofK
aTIl44riY5+9qSWB5zqkUDYCQzYQGV+SrSf2COF2zq7iVN01l/ypxp+5fEyeRRZp
yVh6ISdH/f/rlb9IYr0ZElVMIfqtnk6SjcqTbtin/Iohlt3TDmNQmFsVp5LDNcaG
lild5loDKkanI+JMi09bfFHLToSoYJtOBzzU3hQpHJh9yLiIlQIt7lVPswynnPPn
MUhx5p5tIqYZvI6U9DozUhlrexe/jTYSGthTiPi8+rflVNFk6FpwdeqiSITBnCBj
2Ue36f3Yv9IfR7nPhiQTX24HVRGIr+w7hdvM8wIDAQABAoIBADrEjdWKvrnaBZ9l
tgg9KG4SRkdpSm8WxKwVLT4AId7eI6dnOiMGtrjB1BIgJnmXufd5sgVuV9awg6tR
Y3kcQXlys2fBGq1rztJfs3HCPU5iP7PZUn8jc4fOEsRw5AznlY/7TMVZae71a/XV
oEFWSHN0bBSOGVyLqZyZGoNuvMAsvZ7ObmfAddLQerPV0nOvv9X332wgo2a+8rnb
NHqcZOLdmGjJRkBbAd0IHFciynb1YlhHIEObmZzD8LVFV0UxhhPDHbRwmrj1T2+j
u9U3rBduJKG+mQxelLOLUB6CNbvcyNtj3wAnyq6IVA9qb/CLXJbEhTgnvNTLnYA3
FJxZysECgYEAzw67MVhQY1VZnN49NiXhhl6ypVIlp3fKOUMMZVgiUeSDPSs4Un9q
ABoFBHT9x/Rs6repl/Yr6V3o8uWz/7V7yArom9/yhErunW8bORfiGVUqibYIKi51
qNJMpamQGI/Uw2AbKCjKhpnCcRjt0YTfuTWXxAxOPYNJZqXEvUaUoNUCgYEAxY3P
H07aR2zTDfjvddG2eieaMLoaTWSuGTUH1P7KplQHEsoE135PyLayzYy5I2HX+JDn
fUDDWXWeI4+NdGdUnRrXOedr/Rewu8RZFxxqBV0TJhmTJzGpoun08YXkj7CBCs60
faohJS5iSpi39XNf2k5/RJHGm2FePfPYQR7sWqcCgYEAx6LYcZdIyr18DXdpZU/Y
xgmADU3K6FDjNZqj1QLI9FRzBQMq5r/aoAZ2V/nExomwig5TAiVj6TmWZLt8dUux
8QozhDbESTFGJ5z8jmusn+gxf113OdRZtVAufnuiZ0wmQ8nh5TKPMoAFra3vfley
rYwyq9+BgGWY29NwgV4P55ECgYB5ThRqkw6xYP9PyxWu8PDtnTeux/eyoinNTKTc
gv+Ilnwpa2cBs4vmIVk1oj1knoXxGXkrjgLmAbTy/QjM+04Xkg2qfpHuvQdGpNBX
wpjPZlGFyZp0LKiPYr2HOMIaATWbn0VxDHCB1jOAvrnmu8uVzzGStziO3IDz5bFa
e1SCbQKBgGNUKKppH7BYDMrb+dqRsB6YI5mFlHZoDhVWkPgDba8klp/NvhTI8ACu
URVaPLlgTRdiG2Q5NVDYPpTrhsCbKwE6HeshNKqhL/VsrK77/oSpSQHeLf88oBV2
rDFpN/In31Wp6c+C4crPQNSWZ9jMohHQkCFOUAyBc6UzcqCa4vqd
-----END RSA PRIVATE KEY-----`)

	xmlBytes := []byte(`<Organization xmlns="http://www.w3.org/2000/xmlns">
	<OrganizationName xml:lang="en">Your Identities</OrganizationName>
	<OrganizationDisplayName xml:lang="en">Your Identities</OrganizationDisplayName>
	<OrganizationURL xml:lang="en">http://www.example.org/</OrganizationURL>
	</Organization>`)

	// xmlBytes := []byte(`<Organization xmlns="http://www.w3.org/2000/xmlns">
	// <OrganizationName>Your Identities</OrganizationName>
	// <OrganizationDisplayName>Your Identities</OrganizationDisplayName>
	// <OrganizationURL>http://www.example.org/</OrganizationURL>
	// </Organization>`)

	keyPair, err := tls.X509KeyPair(certBytes, keyBytes)
	failOnError(err, "invalided to load keypair")

	keyStore := dsig.TLSCertKeyStore(keyPair)

	signingContext := dsig.NewDefaultSigningContext(keyStore)
	signingContext.Canonicalizer = dsig.MakeC14N10ExclusiveCanonicalizerWithPrefixList("")
	err = signingContext.SetSignatureMethod(dsig.RSASHA256SignatureMethod)
	failOnError(err, "failed to set signature method")

	readXMLDoc := etree.NewDocument()
	err = readXMLDoc.ReadFromBytes(xmlBytes)
	failOnError(err, "cannot parse xml")

	elementToSign := readXMLDoc.Root()
	elementToSign.CreateAttr("ID", "id1234")

	signedElement, err := signingContext.SignEnveloped(elementToSign)
	failOnError(err, "failed to sign envelop")

	var signedAssertionBuf []byte
	readXMLDoc.SetRoot(signedElement)
	signedAssertionBuf, err = readXMLDoc.WriteToBytes()
	failOnError(err, "failed to convert doc to bytes")

	fmt.Println(string(signedAssertionBuf))
}

CanonicalizationMethod not being used.

Hello there, reading this function:
func (ctx *ValidationContext) transform(
el *etree.Element,
sig *types.Signature,
ref *types.Reference) (*etree.Element, Canonicalizer, error) {

I can see that selects the canonicalizer based on the list of Transforms


But ommits the CanonicalizationMethod tag:

So then, digestValue calculations are wrong.

transform issue

I'm hitting the Expected Enveloped and C14N transforms error when validating signatures. The relevant <Transforms> element has only a single child:

<SignedInfo>
    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
    <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
    <Reference URI="#id">
        <Transforms>
            <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
    </Reference>
</SignedInfo>

The signature verifies if I hardcode pretty much any canonicalizer in the case where one isn't specified, but my reading of the spec doesn't seem to support this fallback canonicalizer. Any ideas?

Totally willing to spend some cycles investigating and bringing Reference transforms more inline with the spec if this is indeed some invalid behavior in goxmldsig.

feature request: Manifest

Would be great to receive a notification through this issue when the author wants to add Manifest support. Thanks.

v2 with minor breaking changes?

I have done some work see diff:

main...lafriks:go-xmldsig:main

  • Refactor to minimize dependencies
  • Fix XML C14N sorting (by namespace value instead of prefix)
  • Add support for ECDSA key signing/verification
  • Add support for SHA2-384 hashes
  • Add support for signing and verification of partial document signatures (signing only one or multiple elements of XML document) - this is required to allow to use this for SOAP WS-Security extensions

Would you be interested in working together on merging this? (of course except my changes about package rename and CI stuff)

Empty default ID attribute fails builds

Just copy pasting the exact Signing code from README, produces the following error. And so does in complex code whenever I try it.

panic: Missing ID attribute

When I look closely into the source code, the default ID attribute that is being set has an empty value. And I can't even find any option to set the ID attr, since in my XML the attribute is actually referenceId and not ID.

Incorrect location of ds:Signature after signature, causes validation to fail

I am using github.com/russellhaering/goxmldsig v1.2.0

I have the following Go structs that represent a document being signed, however the signature is nested inside of the header (AppHdr) struct.

type Request struct {
	XMLName xml.Name   `xml:"Message"`
	Attrs   []xml.Attr `xml:",attr"`

	Header headreq.AppHdr `xml:"AppHdr"`
	Body   document.Iso20022Message
}

type AppHdr struct {
	XMLName xml.Name   `xml:"AppHdr"`
	Attrs   []xml.Attr `xml:",attr"`

	...
	Sgntr     *Sgntr    `xml:"head:Sgntr,omitempty"`
}

type Sgntr struct {
	Attrs     []xml.Attr `xml:",attr"`
	Signature *sigtypes.Signature
}

We have the following code to sign the document.

	edoc := etree.NewDocument()
	err := edoc.ReadFromBytes(data)

	ctx := dsig.NewDefaultSigningContext(mh.keyStore)
	signed, err := ctx.SignEnveloped(notSigned)
	// ... 
	signedDoc := etree.NewDocument()
	signedDoc.SetRoot(notSigned)
	out, err := signedDoc.WriteToBytes()
	// ... 
	return out, nil

This generates the following xml:

<Message xmlns="urn:tch" xmlns:p3="http://www.w3.org/2001/XMLSchema-instance">
  <AppHdr xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
  ... (No head:Sgntr element)
  </AppHdr>
  <CreditTransfer>
  ...
  </CreditTransfer>
  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11" />
      <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
      <ds:Reference URI="">
        <ds:Transforms>
          <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11" />
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
        <ds:DigestValue></ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue></ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate></ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>
  </ds:Signature>
</Message>

This is unexpected because I would expect *sigtypes.Signature to stand-in for the Signature when nested inside the object. It should look like the following (which matches the spec I'm following).

<Message xmlns="urn:tch" xmlns:p3="http://www.w3.org/2001/XMLSchema-instance">
  <AppHdr xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
    ...
    <head:Sgntr>
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11" />
          <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
          <ds:Reference URI="">
            <ds:Transforms>
              <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
              <ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>...</ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>...</ds:SignatureValue>
        <ds:KeyInfo>
          <ds:X509Data>
            <ds:X509Certificate>...</ds:X509Certificate>
          </ds:X509Data>
        </ds:KeyInfo>
      </ds:Signature>
    </head:Sgntr>
  </AppHdr>
  <CreditTransfer>
  ...
  </CreditTransfer>
</Message>

FWIW I've tried to hack in support for moving ds:Signature after signing, but that seems to fail with my validator (3rd party). I understand that manipulating the XML would invalidate the signature, but was hoping it would work. The goxmlsig library will validate the document with ds:Signature appended on the end, but that fails the spec I'm following.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.