diff --git a/xmldsig/golang/ExampleElement.crt b/xmldsig/golang/ExampleElement.crt new file mode 100644 index 00000000..1ac51c99 --- /dev/null +++ b/xmldsig/golang/ExampleElement.crt @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIBlTCB/6ADAgECAgEAMA0GCSqGSIb3DQEBCwUAMAAwHhcNMjEwNDA4MDMyNDA0WhcNMjIwNDA4MDMyOTA0WjAAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx+Fzc+wzEMSt1+/f1BkIwLR6MUPlTM7kAoAjwvS3nIcHKZ/hM/5s9VDbYUQTThZxXHiGYSTHh4ahg5iSdV4L0Tjxv0aDmryLIpjrXU2b2VDTBNV07TA7ZaX37qa2S9biSe9Q6oI1tlS/ze6YTNeF8kaKWPrUlWePKNAfLD0E1/QIDAQABoyAwHjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOBgQBSZwrrQuzihJFUVZ4tx/8XUN79xk/Nq3EjpJNpt5do9rOLlOgNNhbU0aH3ErmO4TGAhHn/40C3IbFxdWOSKoZLOs7/PNWoOuUmtJ/zbplCA/avniY3nq1zdUUK+cc7G+TwfJ1pYZgFFTYz1tWi9lmLES0O3J2SDuZL4wrk9Y8+HQ== +-----END CERTIFICATE----- diff --git a/xmldsig/golang/ExampleElement.xml b/xmldsig/golang/ExampleElement.xml new file mode 100644 index 00000000..c37260df --- /dev/null +++ b/xmldsig/golang/ExampleElement.xml @@ -0,0 +1 @@ +iMfmOOPBujUYLEbhg97cVxdcyx3WNgw5OrLsVf1+I6E=U0py5MnWOTSicSGPPY2LOA44fIy8A9E6GznXcljRWzjFGljqcrWd4L84mm45TUIi1r+X+6p9/iZRpESTIJ495LokX4abaoam7CuxYirDPKfpz18mBnejAZhpgOGTNLIPCn2PNLMQZc+WABJC6aszPJKrNol760rk0MwdQESQOYM=MIIBlTCB/6ADAgECAgEAMA0GCSqGSIb3DQEBCwUAMAAwHhcNMjEwNDA4MDMyNDA0WhcNMjIwNDA4MDMyOTA0WjAAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCx+Fzc+wzEMSt1+/f1BkIwLR6MUPlTM7kAoAjwvS3nIcHKZ/hM/5s9VDbYUQTThZxXHiGYSTHh4ahg5iSdV4L0Tjxv0aDmryLIpjrXU2b2VDTBNV07TA7ZaX37qa2S9biSe9Q6oI1tlS/ze6YTNeF8kaKWPrUlWePKNAfLD0E1/QIDAQABoyAwHjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOBgQBSZwrrQuzihJFUVZ4tx/8XUN79xk/Nq3EjpJNpt5do9rOLlOgNNhbU0aH3ErmO4TGAhHn/40C3IbFxdWOSKoZLOs7/PNWoOuUmtJ/zbplCA/avniY3nq1zdUUK+cc7G+TwfJ1pYZgFFTYz1tWi9lmLES0O3J2SDuZL4wrk9Y8+HQ== diff --git a/xmldsig/golang/README.md b/xmldsig/golang/README.md new file mode 100644 index 00000000..db7a91c2 --- /dev/null +++ b/xmldsig/golang/README.md @@ -0,0 +1,13 @@ + +# Go + +First, install the dependency. You can use `go get` + + $ go get github.com/russellhaering/goxmldsig + $ go run golang/xmldsignverify.go + +Or, on Ubuntu, `apt-get` + + $ sudo apt-get install golang-go golang-github-russellhaering-goxmldsig-dev + $ GOPATH=/usr/share/gocode/ go run golang/xmldsignverify.go + diff --git a/xmldsig/golang/go.mod b/xmldsig/golang/go.mod new file mode 100644 index 00000000..f264d71e --- /dev/null +++ b/xmldsig/golang/go.mod @@ -0,0 +1,8 @@ +module github.com/alphawallet/xmldsig + +go 1.15 + +require ( + github.com/beevik/etree v1.1.0 // indirect + github.com/russellhaering/goxmldsig v1.1.1-0.20201210191726-3541f5e554ee +) diff --git a/xmldsig/golang/xmldsignverify.go b/xmldsig/golang/xmldsignverify.go new file mode 100644 index 00000000..c96f04a5 --- /dev/null +++ b/xmldsig/golang/xmldsignverify.go @@ -0,0 +1,100 @@ +package main + +import ( + "crypto/x509" + "encoding/pem" + "fmt" + "io/ioutil" + "os" + + "github.com/beevik/etree" + dsig "github.com/russellhaering/goxmldsig" +) + +func main() { + // Generate a key and self-signed certificate for signing + randomKeyStore := dsig.RandomKeyStoreForTest() + ctx := dsig.NewDefaultSigningContext(randomKeyStore) + elementToSign := &etree.Element{ + Tag: "ExampleElement", + } + elementToSign.CreateAttr("ID", "id1234") + + // Sign the element + signedElement, err := ctx.SignEnveloped(elementToSign) + if err != nil { + panic(err) + } + + // Serialize the signed element. It is important not to modify the element + // after it has been signed - even pretty-printing the XML will invalidate + // the signature. + doc := etree.NewDocument() + doc.SetRoot(signedElement) + str, err := doc.WriteToString() + if err != nil { + panic(err) + } + + println(str) + + // Replace ExampleElement.crt with the X509Certificate in your tsml accordingly. + cf, e := ioutil.ReadFile("ExampleElement.crt") + if e != nil { + fmt.Println("cfload:", e.Error()) + os.Exit(1) + } + //fmt.Println(string(cf)) + cpb, cr := pem.Decode(cf) + fmt.Println(string(cr)) + fmt.Println(string(cpb.Type)) + cert, err := x509.ParseCertificate(cpb.Bytes) + if err != nil { + fmt.Println("x509.ParseCertificate:", e.Error()) + os.Exit(1) + } + fmt.Println(cert.PublicKeyAlgorithm) + + for i := 1; i < len(os.Args); i++ { + doc2 := etree.NewDocument() + errdoc := doc2.ReadFromFile(os.Args[i]) + if errdoc != nil { + panic(errdoc) + } + root := doc2.SelectElements("ts:token") + fmt.Println(root[0].Tag) + defer func() { + if p := recover(); p != nil { + fmt.Printf("panic: %s\n", p) + } + }() + validate(cert, root[0]) + } +} + +// Validate an element against a root certificate +func validate(root *x509.Certificate, el *etree.Element) { + // Construct a signing context with one or more roots of trust. + ctx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{ + Roots: []*x509.Certificate{root}, + }) + + // 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 { + panic(err) + } + + if validated == nil { + return + } + doc := etree.NewDocument() + doc.SetRoot(validated) + str, err := doc.WriteToString() + if err != nil { + panic(err) + } + + println(str) +}