2 // Reference.cs - Reference implementation for XML Signature
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2002 Motus Technologies Inc. (http://www.motus.com)
10 using System.Collections;
15 namespace System.Security.Cryptography.Xml {
17 // http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html#sec-Reference
18 public class Reference {
20 private TransformChain chain;
21 private string digestMethod;
22 private byte[] digestValue;
26 private HashAlgorithm hash;
28 static private string xmldsig = "http://www.w3.org/2000/09/xmldsig#";
29 static private string sha1 = xmldsig + "sha1";
33 chain = new TransformChain ();
37 public Reference (Stream stream) : this ()
41 public Reference (string uri) : this ()
47 public string DigestMethod {
48 get { return digestMethod; }
49 set { digestMethod = value; }
52 public byte[] DigestValue {
53 get { return digestValue; }
54 set { digestValue = value; }
62 public TransformChain TransformChain {
76 public void AddTransform (Transform transform)
78 chain.Add (transform);
81 public XmlElement GetXml ()
83 if (digestMethod == null)
84 throw new CryptographicException ("DigestMethod");
85 if (digestValue == null)
86 throw new NullReferenceException ("DigestValue");
88 StringBuilder sb = new StringBuilder ();
89 sb.Append ("<Reference");
96 sb.Append (" URI=\"");
101 sb.Append (" Type=\"");
105 sb.Append (" xmlns=\"");
109 if (chain.Count > 0) {
110 sb.Append ("<Transforms>");
111 sb.Append ("</Transforms>");
114 sb.Append ("<DigestMethod Algorithm=\"");
115 sb.Append (digestMethod);
117 sb.Append ("<DigestValue>");
118 sb.Append (Convert.ToBase64String (digestValue));
119 sb.Append ("</DigestValue>");
120 sb.Append ("</Reference>");
122 XmlDocument doc = new XmlDocument ();
123 doc.LoadXml (sb.ToString ());
125 if (chain.Count > 0) {
126 XmlNodeList xnl = doc.GetElementsByTagName ("Transforms");
127 foreach (Transform t in chain) {
128 XmlNode xn = t.GetXml ();
129 XmlNode newNode = doc.ImportNode (xn, true);
130 xnl[0].AppendChild (newNode);
134 return doc.DocumentElement;
137 private string GetAttributeFromElement (XmlElement xel, string attribute, string element)
139 string result = null;
140 XmlNodeList xnl = xel.GetElementsByTagName (element);
141 if ((xnl != null) && (xnl.Count > 0)) {
142 XmlAttribute xa = xnl[0].Attributes [attribute];
144 result = xa.InnerText;
149 // note: we do NOT return null -on purpose- if attribute isn't found
150 private string GetAttribute (XmlElement xel, string attribute)
152 XmlAttribute xa = xel.Attributes [attribute];
153 return ((xa != null) ? xa.InnerText : null);
156 public void LoadXml (XmlElement value)
159 throw new ArgumentNullException ("value");
161 if ((value.LocalName == "Reference") && (value.NamespaceURI == xmldsig)) {
162 id = GetAttribute (value, "Id");
163 uri = GetAttribute (value, "URI");
164 type = GetAttribute (value, "Type");
165 // Note: order is important for validations
166 XmlNodeList xnl = value.GetElementsByTagName ("Transform");
167 if ((xnl != null) && (xnl.Count > 0)) {
169 foreach (XmlNode xn in xnl) {
170 string a = GetAttribute ((XmlElement)xn, "Algorithm");
172 case "http://www.w3.org/2000/09/xmldsig#base64":
173 t = new XmlDsigBase64Transform ();
175 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
176 t = new XmlDsigC14NTransform ();
178 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
179 t = new XmlDsigC14NWithCommentsTransform ();
181 case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
182 t = new XmlDsigEnvelopedSignatureTransform ();
184 case "http://www.w3.org/TR/1999/REC-xpath-19991116":
185 t = new XmlDsigXPathTransform ();
187 case "http://www.w3.org/TR/1999/REC-xslt-19991116":
188 t = new XmlDsigXsltTransform ();
191 throw new NotSupportedException ();
197 DigestMethod = GetAttributeFromElement (value, "Algorithm", "DigestMethod");
199 xnl = value.GetElementsByTagName ("DigestValue");
200 if ((xnl != null) && (xnl.Count > 0)) {
201 DigestValue = Convert.FromBase64String (xnl[0].InnerText);
205 throw new CryptographicException ();