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;
28 chain = new TransformChain ();
29 digestMethod = XmlSignature.NamespaceURI + "sha1";
33 public Reference (Stream stream) : this ()
37 public Reference (string uri) : this ()
43 public string DigestMethod {
44 get { return digestMethod; }
45 set { digestMethod = value; }
48 public byte[] DigestValue {
49 get { return digestValue; }
50 set { digestValue = value; }
58 public TransformChain TransformChain {
72 public void AddTransform (Transform transform)
74 chain.Add (transform);
77 public XmlElement GetXml ()
79 if (digestMethod == null)
80 throw new CryptographicException ("DigestMethod");
81 if (digestValue == null)
82 throw new NullReferenceException ("DigestValue");
84 XmlDocument document = new XmlDocument ();
85 XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Reference, XmlSignature.NamespaceURI);
87 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
89 xel.SetAttribute (XmlSignature.AttributeNames.URI, uri);
91 xel.SetAttribute (XmlSignature.AttributeNames.Type, type);
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);
100 xel.AppendChild (ts);
103 XmlElement dm = document.CreateElement (XmlSignature.ElementNames.DigestMethod, XmlSignature.NamespaceURI);
104 dm.SetAttribute (XmlSignature.AttributeNames.Algorithm, digestMethod);
105 xel.AppendChild (dm);
107 XmlElement dv = document.CreateElement (XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
108 dv.InnerText = Convert.ToBase64String (digestValue);
109 xel.AppendChild (dv);
114 // note: we do NOT return null -on purpose- if attribute isn't found
115 private string GetAttribute (XmlElement xel, string attribute)
117 XmlAttribute xa = xel.Attributes [attribute];
118 return ((xa != null) ? xa.InnerText : null);
121 public void LoadXml (XmlElement value)
124 throw new ArgumentNullException ("value");
126 if ((value.LocalName != XmlSignature.ElementNames.Reference) || (value.NamespaceURI != XmlSignature.NamespaceURI))
127 throw new CryptographicException ();
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)) {
136 foreach (XmlNode xn in xnl) {
137 string a = GetAttribute ((XmlElement)xn, XmlSignature.AttributeNames.Algorithm);
139 case "http://www.w3.org/2000/09/xmldsig#base64":
140 t = new XmlDsigBase64Transform ();
142 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
143 t = new XmlDsigC14NTransform ();
145 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
146 t = new XmlDsigC14NWithCommentsTransform ();
148 case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
149 t = new XmlDsigEnvelopedSignatureTransform ();
151 case "http://www.w3.org/TR/1999/REC-xpath-19991116":
152 t = new XmlDsigXPathTransform ();
154 case "http://www.w3.org/TR/1999/REC-xslt-19991116":
155 t = new XmlDsigXsltTransform ();
158 throw new NotSupportedException ();
160 if (xn.ChildNodes.Count > 0) {
161 t.LoadInnerXml (xn.ChildNodes);
167 DigestMethod = XmlSignature.GetAttributeFromElement (value, XmlSignature.AttributeNames.Algorithm, XmlSignature.ElementNames.DigestMethod);
169 XmlElement dig = XmlSignature.GetChildElement (value, XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
171 DigestValue = Convert.FromBase64String (dig.InnerText);