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 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Runtime.InteropServices;
34 namespace System.Security.Cryptography.Xml {
36 // http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html#sec-Reference
37 public class Reference {
39 private TransformChain chain;
40 private string digestMethod;
41 private byte[] digestValue;
45 private Stream stream;
46 private XmlElement element;
50 chain = new TransformChain ();
51 digestMethod = XmlSignature.NamespaceURI + "sha1";
54 [MonoTODO ("There is no description about how it is used.")]
55 public Reference (Stream stream) : this ()
60 public Reference (string uri) : this ()
66 public string DigestMethod {
67 get { return digestMethod; }
74 public byte[] DigestValue {
75 get { return digestValue; }
90 public TransformChain TransformChain {
93 set { chain = value; }
112 public void AddTransform (Transform transform)
114 chain.Add (transform);
117 public XmlElement GetXml ()
122 if (digestMethod == null)
123 throw new CryptographicException ("DigestMethod");
124 if (digestValue == null)
125 throw new NullReferenceException ("DigestValue");
127 XmlDocument document = new XmlDocument ();
128 XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Reference, XmlSignature.NamespaceURI);
130 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
132 xel.SetAttribute (XmlSignature.AttributeNames.URI, uri);
134 xel.SetAttribute (XmlSignature.AttributeNames.Type, type);
136 if (chain.Count > 0) {
137 XmlElement ts = document.CreateElement (XmlSignature.ElementNames.Transforms, XmlSignature.NamespaceURI);
138 foreach (Transform t in chain) {
139 XmlNode xn = t.GetXml ();
140 XmlNode newNode = document.ImportNode (xn, true);
141 ts.AppendChild (newNode);
143 xel.AppendChild (ts);
146 XmlElement dm = document.CreateElement (XmlSignature.ElementNames.DigestMethod, XmlSignature.NamespaceURI);
147 dm.SetAttribute (XmlSignature.AttributeNames.Algorithm, digestMethod);
148 xel.AppendChild (dm);
150 XmlElement dv = document.CreateElement (XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
151 dv.InnerText = Convert.ToBase64String (digestValue);
152 xel.AppendChild (dv);
157 // note: we do NOT return null -on purpose- if attribute isn't found
158 private string GetAttribute (XmlElement xel, string attribute)
160 XmlAttribute xa = xel.Attributes [attribute];
161 return ((xa != null) ? xa.InnerText : null);
164 public void LoadXml (XmlElement value)
167 throw new ArgumentNullException ("value");
169 if ((value.LocalName != XmlSignature.ElementNames.Reference) || (value.NamespaceURI != XmlSignature.NamespaceURI))
170 throw new CryptographicException ();
172 id = GetAttribute (value, XmlSignature.AttributeNames.Id);
173 uri = GetAttribute (value, XmlSignature.AttributeNames.URI);
174 type = GetAttribute (value, XmlSignature.AttributeNames.Type);
175 // Note: order is important for validations
176 XmlNodeList xnl = value.GetElementsByTagName (XmlSignature.ElementNames.Transform, XmlSignature.NamespaceURI);
177 if ((xnl != null) && (xnl.Count > 0)) {
179 foreach (XmlNode xn in xnl) {
180 string a = GetAttribute ((XmlElement)xn, XmlSignature.AttributeNames.Algorithm);
181 /* This code is useful for debugging in VS.NET because using CryptoConfig
182 (from MS mscorlib) would throw InvalidCastException because it's
183 Transform would come from MS System.Security.dll not Mono's.
185 case "http://www.w3.org/2000/09/xmldsig#base64":
186 t = new XmlDsigBase64Transform ();
188 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
189 t = new XmlDsigC14NTransform ();
191 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
192 t = new XmlDsigC14NWithCommentsTransform ();
194 case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
195 t = new XmlDsigEnvelopedSignatureTransform ();
197 case "http://www.w3.org/TR/1999/REC-xpath-19991116":
198 t = new XmlDsigXPathTransform ();
200 case "http://www.w3.org/TR/1999/REC-xslt-19991116":
201 t = new XmlDsigXsltTransform ();
203 case "http://www.w3.org/2002/07/decrypt#XML":
204 t = new XmlDecryptionTransform ();
207 throw new NotSupportedException ();
210 t = (Transform) CryptoConfig.CreateFromName (a);
212 throw new CryptographicException ("Unknown transform {0}.", a);
214 if (xn.ChildNodes.Count > 0) {
215 t.LoadInnerXml (xn.ChildNodes);
221 DigestMethod = XmlSignature.GetAttributeFromElement (value, XmlSignature.AttributeNames.Algorithm, XmlSignature.ElementNames.DigestMethod);
223 XmlElement dig = XmlSignature.GetChildElement (value, XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
225 DigestValue = Convert.FromBase64String (dig.InnerText);