2 // Reference.cs - Reference implementation for XML Signature
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // (C) 2004 Novell (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 namespace System.Security.Cryptography.Xml {
37 // http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html#sec-Reference
38 public class Reference {
40 private TransformChain chain;
41 private string digestMethod;
42 private byte[] digestValue;
46 private Stream stream;
47 private XmlElement element;
51 chain = new TransformChain ();
52 digestMethod = XmlSignature.NamespaceURI + "sha1";
55 [MonoTODO ("There is no description about how it is used.")]
56 public Reference (Stream stream) : this ()
61 public Reference (string uri) : this ()
67 public string DigestMethod {
68 get { return digestMethod; }
75 public byte[] DigestValue {
76 get { return digestValue; }
91 public TransformChain TransformChain {
111 public void AddTransform (Transform transform)
113 chain.Add (transform);
116 public XmlElement GetXml ()
121 if (digestMethod == null)
122 throw new CryptographicException ("DigestMethod");
123 if (digestValue == null)
124 throw new NullReferenceException ("DigestValue");
126 XmlDocument document = new XmlDocument ();
127 XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Reference, XmlSignature.NamespaceURI);
129 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
131 xel.SetAttribute (XmlSignature.AttributeNames.URI, uri);
133 xel.SetAttribute (XmlSignature.AttributeNames.Type, type);
135 if (chain.Count > 0) {
136 XmlElement ts = document.CreateElement (XmlSignature.ElementNames.Transforms, XmlSignature.NamespaceURI);
137 foreach (Transform t in chain) {
138 XmlNode xn = t.GetXml ();
139 XmlNode newNode = document.ImportNode (xn, true);
140 ts.AppendChild (newNode);
142 xel.AppendChild (ts);
145 XmlElement dm = document.CreateElement (XmlSignature.ElementNames.DigestMethod, XmlSignature.NamespaceURI);
146 dm.SetAttribute (XmlSignature.AttributeNames.Algorithm, digestMethod);
147 xel.AppendChild (dm);
149 XmlElement dv = document.CreateElement (XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
150 dv.InnerText = Convert.ToBase64String (digestValue);
151 xel.AppendChild (dv);
156 // note: we do NOT return null -on purpose- if attribute isn't found
157 private string GetAttribute (XmlElement xel, string attribute)
159 XmlAttribute xa = xel.Attributes [attribute];
160 return ((xa != null) ? xa.InnerText : null);
163 public void LoadXml (XmlElement value)
166 throw new ArgumentNullException ("value");
168 if ((value.LocalName != XmlSignature.ElementNames.Reference) || (value.NamespaceURI != XmlSignature.NamespaceURI))
169 throw new CryptographicException ();
171 id = GetAttribute (value, XmlSignature.AttributeNames.Id);
172 uri = GetAttribute (value, XmlSignature.AttributeNames.URI);
173 type = GetAttribute (value, XmlSignature.AttributeNames.Type);
174 // Note: order is important for validations
175 XmlNodeList xnl = value.GetElementsByTagName (XmlSignature.ElementNames.Transform, XmlSignature.NamespaceURI);
176 if ((xnl != null) && (xnl.Count > 0)) {
178 foreach (XmlNode xn in xnl) {
179 string a = GetAttribute ((XmlElement)xn, XmlSignature.AttributeNames.Algorithm);
180 /* This code is useful for debugging in VS.NET because using CryptoConfig
181 (from MS mscorlib) would throw InvalidCastException because it's
182 Transform would come from MS System.Security.dll not Mono's.
184 case "http://www.w3.org/2000/09/xmldsig#base64":
185 t = new XmlDsigBase64Transform ();
187 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
188 t = new XmlDsigC14NTransform ();
190 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
191 t = new XmlDsigC14NWithCommentsTransform ();
193 case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
194 t = new XmlDsigEnvelopedSignatureTransform ();
196 case "http://www.w3.org/TR/1999/REC-xpath-19991116":
197 t = new XmlDsigXPathTransform ();
199 case "http://www.w3.org/TR/1999/REC-xslt-19991116":
200 t = new XmlDsigXsltTransform ();
203 throw new NotSupportedException ();
206 t = (Transform) CryptoConfig.CreateFromName (a);
208 throw new CryptographicException ("Unknown transform {0}.", a);
210 if (xn.ChildNodes.Count > 0) {
211 t.LoadInnerXml (xn.ChildNodes);
217 DigestMethod = XmlSignature.GetAttributeFromElement (value, XmlSignature.AttributeNames.Algorithm, XmlSignature.ElementNames.DigestMethod);
219 XmlElement dig = XmlSignature.GetChildElement (value, XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
221 DigestValue = Convert.FromBase64String (dig.InnerText);