Reference.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. //
  2. // Reference.cs - Reference implementation for XML Signature
  3. //
  4. // Author:
  5. // Sebastien Pouliot <[email protected]>
  6. //
  7. // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
  8. // (C) 2004 Novell (http://www.novell.com)
  9. //
  10. using System.IO;
  11. using System.Xml;
  12. namespace System.Security.Cryptography.Xml {
  13. // http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html#sec-Reference
  14. public class Reference {
  15. private TransformChain chain;
  16. private string digestMethod;
  17. private byte[] digestValue;
  18. private string id;
  19. private string uri;
  20. private string type;
  21. private Stream stream;
  22. private XmlElement element;
  23. public Reference ()
  24. {
  25. chain = new TransformChain ();
  26. digestMethod = XmlSignature.NamespaceURI + "sha1";
  27. }
  28. [MonoTODO ("There is no description about how it is used.")]
  29. public Reference (Stream stream) : this ()
  30. {
  31. this.stream = stream;
  32. }
  33. public Reference (string uri) : this ()
  34. {
  35. this.uri = uri;
  36. }
  37. // default to SHA1
  38. public string DigestMethod {
  39. get { return digestMethod; }
  40. set {
  41. element = null;
  42. digestMethod = value;
  43. }
  44. }
  45. public byte[] DigestValue {
  46. get { return digestValue; }
  47. set {
  48. element = null;
  49. digestValue = value;
  50. }
  51. }
  52. public string Id {
  53. get { return id; }
  54. set {
  55. element = null;
  56. id = value;
  57. }
  58. }
  59. public TransformChain TransformChain {
  60. get { return chain; }
  61. }
  62. public string Type {
  63. get { return type; }
  64. set {
  65. element = null;
  66. type = value;
  67. }
  68. }
  69. public string Uri {
  70. get { return uri; }
  71. set {
  72. element = null;
  73. uri = value;
  74. }
  75. }
  76. public void AddTransform (Transform transform)
  77. {
  78. chain.Add (transform);
  79. }
  80. public XmlElement GetXml ()
  81. {
  82. if (element != null)
  83. return element;
  84. if (digestMethod == null)
  85. throw new CryptographicException ("DigestMethod");
  86. if (digestValue == null)
  87. throw new NullReferenceException ("DigestValue");
  88. XmlDocument document = new XmlDocument ();
  89. XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Reference, XmlSignature.NamespaceURI);
  90. if (id != null)
  91. xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
  92. if (uri != null)
  93. xel.SetAttribute (XmlSignature.AttributeNames.URI, uri);
  94. if (type != null)
  95. xel.SetAttribute (XmlSignature.AttributeNames.Type, type);
  96. if (chain.Count > 0) {
  97. XmlElement ts = document.CreateElement (XmlSignature.ElementNames.Transforms, XmlSignature.NamespaceURI);
  98. foreach (Transform t in chain) {
  99. XmlNode xn = t.GetXml ();
  100. XmlNode newNode = document.ImportNode (xn, true);
  101. ts.AppendChild (newNode);
  102. }
  103. xel.AppendChild (ts);
  104. }
  105. XmlElement dm = document.CreateElement (XmlSignature.ElementNames.DigestMethod, XmlSignature.NamespaceURI);
  106. dm.SetAttribute (XmlSignature.AttributeNames.Algorithm, digestMethod);
  107. xel.AppendChild (dm);
  108. XmlElement dv = document.CreateElement (XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
  109. dv.InnerText = Convert.ToBase64String (digestValue);
  110. xel.AppendChild (dv);
  111. return xel;
  112. }
  113. // note: we do NOT return null -on purpose- if attribute isn't found
  114. private string GetAttribute (XmlElement xel, string attribute)
  115. {
  116. XmlAttribute xa = xel.Attributes [attribute];
  117. return ((xa != null) ? xa.InnerText : null);
  118. }
  119. public void LoadXml (XmlElement value)
  120. {
  121. if (value == null)
  122. throw new ArgumentNullException ("value");
  123. if ((value.LocalName != XmlSignature.ElementNames.Reference) || (value.NamespaceURI != XmlSignature.NamespaceURI))
  124. throw new CryptographicException ();
  125. id = GetAttribute (value, XmlSignature.AttributeNames.Id);
  126. uri = GetAttribute (value, XmlSignature.AttributeNames.URI);
  127. type = GetAttribute (value, XmlSignature.AttributeNames.Type);
  128. // Note: order is important for validations
  129. XmlNodeList xnl = value.GetElementsByTagName (XmlSignature.ElementNames.Transform, XmlSignature.NamespaceURI);
  130. if ((xnl != null) && (xnl.Count > 0)) {
  131. Transform t = null;
  132. foreach (XmlNode xn in xnl) {
  133. string a = GetAttribute ((XmlElement)xn, XmlSignature.AttributeNames.Algorithm);
  134. /* This code is useful for debugging in VS.NET because using CryptoConfig
  135. (from MS mscorlib) would throw InvalidCastException because it's
  136. Transform would come from MS System.Security.dll not Mono's.
  137. switch (a) {
  138. case "http://www.w3.org/2000/09/xmldsig#base64":
  139. t = new XmlDsigBase64Transform ();
  140. break;
  141. case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
  142. t = new XmlDsigC14NTransform ();
  143. break;
  144. case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
  145. t = new XmlDsigC14NWithCommentsTransform ();
  146. break;
  147. case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
  148. t = new XmlDsigEnvelopedSignatureTransform ();
  149. break;
  150. case "http://www.w3.org/TR/1999/REC-xpath-19991116":
  151. t = new XmlDsigXPathTransform ();
  152. break;
  153. case "http://www.w3.org/TR/1999/REC-xslt-19991116":
  154. t = new XmlDsigXsltTransform ();
  155. break;
  156. default:
  157. throw new NotSupportedException ();
  158. }
  159. */
  160. t = (Transform) CryptoConfig.CreateFromName (a);
  161. if (t == null)
  162. throw new CryptographicException ("Unknown transform {0}.", a);
  163. if (xn.ChildNodes.Count > 0) {
  164. t.LoadInnerXml (xn.ChildNodes);
  165. }
  166. AddTransform (t);
  167. }
  168. }
  169. // get DigestMethod
  170. DigestMethod = XmlSignature.GetAttributeFromElement (value, XmlSignature.AttributeNames.Algorithm, XmlSignature.ElementNames.DigestMethod);
  171. // get DigestValue
  172. XmlElement dig = XmlSignature.GetChildElement (value, XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
  173. if (dig != null)
  174. DigestValue = Convert.FromBase64String (dig.InnerText);
  175. element = value;
  176. }
  177. }
  178. }