2004-03-09 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Security / System.Security.Cryptography.Xml / Reference.cs
1 //
2 // Reference.cs - Reference implementation for XML Signature
3 //
4 // Author:
5 //      Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // (C) 2004 Novell (http://www.novell.com)
9 //
10
11 using System.IO;
12 using System.Xml;
13
14 namespace System.Security.Cryptography.Xml { 
15
16         // http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html#sec-Reference
17         public class Reference {
18
19                 private TransformChain chain;
20                 private string digestMethod;
21                 private byte[] digestValue;
22                 private string id;
23                 private string uri;
24                 private string type;
25
26                 public Reference () 
27                 {
28                         chain = new TransformChain ();
29                         digestMethod = XmlSignature.NamespaceURI + "sha1";
30                 }
31
32                 [MonoTODO()]
33                 public Reference (Stream stream) : this () 
34                 {
35                 }
36
37                 public Reference (string uri) : this ()
38                 {
39                         this.uri = uri;
40                 }
41
42                 // default to SHA1
43                 public string DigestMethod {
44                         get { return digestMethod; }
45                         set { digestMethod = value; }
46                 }
47
48                 public byte[] DigestValue {
49                         get { return digestValue; }
50                         set { digestValue = value; }
51                 }
52
53                 public string Id {
54                         get { return id; }
55                         set { id = value; }
56                 }
57
58                 public TransformChain TransformChain {
59                         get { return chain; }
60                 }
61
62                 public string Type {
63                         get { return type; }
64                         set { type = value; }
65                 }
66
67                 public string Uri {
68                         get { return uri; }
69                         set { uri = value; }
70                 }
71
72                 public void AddTransform (Transform transform) 
73                 {
74                         chain.Add (transform);
75                 }
76
77                 public XmlElement GetXml () 
78                 {
79                         if (digestMethod == null)
80                                 throw new CryptographicException ("DigestMethod");
81                         if (digestValue == null)
82                                 throw new NullReferenceException ("DigestValue");
83
84                         XmlDocument document = new XmlDocument ();
85                         XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Reference, XmlSignature.NamespaceURI);
86                         if (id != null)
87                                 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
88                         if (uri != null)
89                                 xel.SetAttribute (XmlSignature.AttributeNames.URI, uri);
90                         if (type != null)
91                                 xel.SetAttribute (XmlSignature.AttributeNames.Type, type);
92
93                         if (chain.Count > 0) {
94                                 XmlElement ts = document.CreateElement (XmlSignature.ElementNames.Transforms, XmlSignature.NamespaceURI);
95                                 foreach (Transform t in chain) {
96                                         XmlNode xn = t.GetXml ();
97                                         XmlNode newNode = document.ImportNode (xn, true);
98                                         ts.AppendChild (newNode);
99                                 }
100                                 xel.AppendChild (ts);
101                         }
102
103                         XmlElement dm = document.CreateElement (XmlSignature.ElementNames.DigestMethod, XmlSignature.NamespaceURI);
104                         dm.SetAttribute (XmlSignature.AttributeNames.Algorithm, digestMethod);
105                         xel.AppendChild (dm);
106
107                         XmlElement dv = document.CreateElement (XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
108                         dv.InnerText = Convert.ToBase64String (digestValue);
109                         xel.AppendChild (dv);
110
111                         return xel;
112                 }
113
114                 // note: we do NOT return null -on purpose- if attribute isn't found
115                 private string GetAttribute (XmlElement xel, string attribute) 
116                 {
117                         XmlAttribute xa = xel.Attributes [attribute];
118                         return ((xa != null) ? xa.InnerText : null);
119                 }
120
121                 public void LoadXml (XmlElement value) 
122                 {
123                         if (value == null)
124                                 throw new ArgumentNullException ("value");
125
126                         if ((value.LocalName != XmlSignature.ElementNames.Reference) || (value.NamespaceURI != XmlSignature.NamespaceURI))
127                                 throw new CryptographicException ();
128
129                         id = GetAttribute (value, XmlSignature.AttributeNames.Id);
130                         uri = GetAttribute (value, XmlSignature.AttributeNames.URI);
131                         type = GetAttribute (value, XmlSignature.AttributeNames.Type);
132                         // Note: order is important for validations
133                         XmlNodeList xnl = value.GetElementsByTagName (XmlSignature.ElementNames.Transform, XmlSignature.NamespaceURI);
134                         if ((xnl != null) && (xnl.Count > 0)) {
135                                 Transform t = null;
136                                 foreach (XmlNode xn in xnl) {
137                                         string a = GetAttribute ((XmlElement)xn, XmlSignature.AttributeNames.Algorithm);
138                                         switch (a) {
139                                                 case "http://www.w3.org/2000/09/xmldsig#base64":
140                                                         t = new XmlDsigBase64Transform ();
141                                                         break;
142                                                 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
143                                                         t = new XmlDsigC14NTransform ();
144                                                         break;
145                                                 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
146                                                         t = new XmlDsigC14NWithCommentsTransform ();
147                                                         break;
148                                                 case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
149                                                         t = new XmlDsigEnvelopedSignatureTransform ();
150                                                         break;
151                                                 case "http://www.w3.org/TR/1999/REC-xpath-19991116":
152                                                         t = new XmlDsigXPathTransform ();
153                                                         break;
154                                                 case "http://www.w3.org/TR/1999/REC-xslt-19991116":
155                                                         t = new XmlDsigXsltTransform ();
156                                                         break;
157                                                 default:
158                                                         throw new NotSupportedException ();
159                                         }
160                                         if (xn.ChildNodes.Count > 0) {
161                                                 t.LoadInnerXml (xn.ChildNodes);
162                                         }
163                                         AddTransform (t);
164                                 }
165                         }
166                         // get DigestMethod
167                         DigestMethod = XmlSignature.GetAttributeFromElement (value, XmlSignature.AttributeNames.Algorithm, XmlSignature.ElementNames.DigestMethod);
168                         // get DigestValue
169                         XmlElement dig = XmlSignature.GetChildElement (value, XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
170                         if (dig != null)
171                                 DigestValue = Convert.FromBase64String (dig.InnerText);
172                 }
173         }
174 }