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)
14 namespace System.Security.Cryptography.Xml {
16 // http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html#sec-Reference
17 public class Reference {
19 private TransformChain chain;
20 private string digestMethod;
21 private byte[] digestValue;
25 private Stream stream;
26 private XmlElement element;
30 chain = new TransformChain ();
31 digestMethod = XmlSignature.NamespaceURI + "sha1";
34 [MonoTODO ("There is no description about how it is used.")]
35 public Reference (Stream stream) : this ()
40 public Reference (string uri) : this ()
46 public string DigestMethod {
47 get { return digestMethod; }
54 public byte[] DigestValue {
55 get { return digestValue; }
70 public TransformChain TransformChain {
90 public void AddTransform (Transform transform)
92 chain.Add (transform);
95 public XmlElement GetXml ()
100 if (digestMethod == null)
101 throw new CryptographicException ("DigestMethod");
102 if (digestValue == null)
103 throw new NullReferenceException ("DigestValue");
105 XmlDocument document = new XmlDocument ();
106 XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Reference, XmlSignature.NamespaceURI);
108 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
110 xel.SetAttribute (XmlSignature.AttributeNames.URI, uri);
112 xel.SetAttribute (XmlSignature.AttributeNames.Type, type);
114 if (chain.Count > 0) {
115 XmlElement ts = document.CreateElement (XmlSignature.ElementNames.Transforms, XmlSignature.NamespaceURI);
116 foreach (Transform t in chain) {
117 XmlNode xn = t.GetXml ();
118 XmlNode newNode = document.ImportNode (xn, true);
119 ts.AppendChild (newNode);
121 xel.AppendChild (ts);
124 XmlElement dm = document.CreateElement (XmlSignature.ElementNames.DigestMethod, XmlSignature.NamespaceURI);
125 dm.SetAttribute (XmlSignature.AttributeNames.Algorithm, digestMethod);
126 xel.AppendChild (dm);
128 XmlElement dv = document.CreateElement (XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
129 dv.InnerText = Convert.ToBase64String (digestValue);
130 xel.AppendChild (dv);
135 // note: we do NOT return null -on purpose- if attribute isn't found
136 private string GetAttribute (XmlElement xel, string attribute)
138 XmlAttribute xa = xel.Attributes [attribute];
139 return ((xa != null) ? xa.InnerText : null);
142 public void LoadXml (XmlElement value)
145 throw new ArgumentNullException ("value");
147 if ((value.LocalName != XmlSignature.ElementNames.Reference) || (value.NamespaceURI != XmlSignature.NamespaceURI))
148 throw new CryptographicException ();
150 id = GetAttribute (value, XmlSignature.AttributeNames.Id);
151 uri = GetAttribute (value, XmlSignature.AttributeNames.URI);
152 type = GetAttribute (value, XmlSignature.AttributeNames.Type);
153 // Note: order is important for validations
154 XmlNodeList xnl = value.GetElementsByTagName (XmlSignature.ElementNames.Transform, XmlSignature.NamespaceURI);
155 if ((xnl != null) && (xnl.Count > 0)) {
157 foreach (XmlNode xn in xnl) {
158 string a = GetAttribute ((XmlElement)xn, XmlSignature.AttributeNames.Algorithm);
159 /* This code is useful for debugging in VS.NET because using CryptoConfig
160 (from MS mscorlib) would throw InvalidCastException because it's
161 Transform would come from MS System.Security.dll not Mono's.
163 case "http://www.w3.org/2000/09/xmldsig#base64":
164 t = new XmlDsigBase64Transform ();
166 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
167 t = new XmlDsigC14NTransform ();
169 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
170 t = new XmlDsigC14NWithCommentsTransform ();
172 case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
173 t = new XmlDsigEnvelopedSignatureTransform ();
175 case "http://www.w3.org/TR/1999/REC-xpath-19991116":
176 t = new XmlDsigXPathTransform ();
178 case "http://www.w3.org/TR/1999/REC-xslt-19991116":
179 t = new XmlDsigXsltTransform ();
182 throw new NotSupportedException ();
185 t = (Transform) CryptoConfig.CreateFromName (a);
187 throw new CryptographicException ("Unknown transform {0}.", a);
189 if (xn.ChildNodes.Count > 0) {
190 t.LoadInnerXml (xn.ChildNodes);
196 DigestMethod = XmlSignature.GetAttributeFromElement (value, XmlSignature.AttributeNames.Algorithm, XmlSignature.ElementNames.DigestMethod);
198 XmlElement dig = XmlSignature.GetChildElement (value, XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
200 DigestValue = Convert.FromBase64String (dig.InnerText);