diff --git a/xmldsig/signature.go b/xmldsig/signature.go
new file mode 100644
index 0000000..f98b8d7
--- /dev/null
+++ b/xmldsig/signature.go
@@ -0,0 +1,51 @@
+package xmldsig
+
+import "encoding/xml"
+
+// Method is part of Signature.
+type Method struct {
+ Algorithm string `xml:",attr"`
+}
+
+// Signature is a model for the Signature object specified by XMLDSIG. This is
+// convenience object when constructing XML that you'd like to sign. For example:
+//
+// type Foo struct {
+// Stuff string
+// Signature Signature
+// }
+//
+// f := Foo{Suff: "hello"}
+// f.Signature = DefaultSignature()
+// buf, _ := xml.Marshal(f)
+// buf, _ = Sign(key, buf)
+//
+type Signature struct {
+ XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# Signature"`
+
+ CanonicalizationMethod Method `xml:"SignedInfo>CanonicalizationMethod"`
+ SignatureMethod Method `xml:"SignedInfo>SignatureMethod"`
+ ReferenceTransforms []Method `xml:"SignedInfo>Reference>Transforms>Transform"`
+ DigestMethod Method `xml:"SignedInfo>Reference>DigestMethod"`
+ DigestValue string `xml:"SignedInfo>Reference>DigestValue"`
+ SignatureValue string `xml:"SignatureValue"`
+ KeyName string `xml:"KeyInfo>KeyName"`
+}
+
+// DefaultSignature populates a default Signature that uses c14n and SHA1.
+func DefaultSignature() Signature {
+ return Signature{
+ CanonicalizationMethod: Method{
+ Algorithm: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
+ },
+ SignatureMethod: Method{
+ Algorithm: "http://www.w3.org/2000/09/xmldsig#rsa-sha1",
+ },
+ ReferenceTransforms: []Method{
+ Method{Algorithm: "http://www.w3.org/2000/09/xmldsig#enveloped-signature"},
+ },
+ DigestMethod: Method{
+ Algorithm: "http://www.w3.org/2000/09/xmldsig#sha1",
+ },
+ }
+}
diff --git a/xmldsig/xmldsig_test.go b/xmldsig/xmldsig_test.go
index bcb4862..71805e0 100644
--- a/xmldsig/xmldsig_test.go
+++ b/xmldsig/xmldsig_test.go
@@ -1,10 +1,16 @@
package xmldsig
import (
+ "encoding/xml"
"strings"
"testing"
)
+type Envelope struct {
+ Data string
+ Signature Signature `xml:"http://www.w3.org/2000/09/xmldsig# Signature"`
+}
+
func TestSign(t *testing.T) {
key := []byte(`-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOK9uFHs/nXrH9Lc
@@ -48,7 +54,7 @@ XML Security Library example: Simple signature template file for sign1 example.
-`
+`)
expectedSignedString := "\n\n\n \n\tHello, World!\n \n \n \n \n \n \n \n \n \n \n 9H/rQr2Axe9hYTV2n/tCp+3UIQQ=\n \n \n 2rM7C8ZzCjxEY4kueUaSevvEZjORQ7hBTWGxUJXStyQScLtX1drFx9dRmUdk/uRr\n0O37B3gsbKzlpQNfdVYPIfWgswjEVLBH7Ncl1dJ6dTofkQrogIF5CQE+PIAG3MPh\nnWsIcBahRQ+rNaRB/TDscuEV3+V3Je4K7E0OEKEuP1I=\n \n\t\n \n \n\n"
@@ -62,6 +68,22 @@ XML Security Library example: Simple signature template file for sign1 example.
t.Errorf("signed: expected %q, got `%q`", expectedSignedString, string(actualSignedString))
return
}
+
+ // Try again but this time construct the message from a struct having a Signature member
+ doc := Envelope{Data: "Hello, World!"}
+ doc.Signature = DefaultSignature()
+ docStr, err = xml.Marshal(doc)
+ if err != nil {
+ t.Errorf("marshal: %s", err)
+ }
+ actualSignedString, err = Sign(key, docStr)
+ if err != nil {
+ t.Errorf("sign: %s", err)
+ return
+ }
+ expectedSignedString = "\nHello, World!09XOMG8zghPZhJYD8kM2uJsr1cc=fqL9oHtcNiFFaTy7AJoQ1hs5Wz0fTqjq0xANLz/mSLBLiFv2OEicuwyo4InyBnyf\njSjmCBaz8QPX9rTW49a2wv1RMkls0WnqP65DUY2ofM4wKHWcjnGt1p1rlYdDv5Sl\njk5Wqwy2EmoqGSXQovRZmn4jidThmoqgum4LNKC2lFI=\n"
+ if string(actualSignedString) != expectedSignedString {
+ t.Errorf("signed: expected %q, got `%q`", expectedSignedString, string(actualSignedString))
return
}