Reference.cs 5.0 KB

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