2 // Reference.cs - Reference implementation for XML Signature
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
12 using System
.Security
.Cryptography
;
16 using System
.Security
.Cryptography
.Xml
;
18 namespace Microsoft
.Web
.Services
.Security
{
20 namespace System
.Security
.Cryptography
.Xml
{
22 // http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html#sec-Reference
23 public class Reference
{
25 private TransformChain chain
;
26 private string digestMethod
;
27 private byte[] digestValue
;
31 private HashAlgorithm hash
;
35 chain
= new TransformChain ();
36 digestMethod
= XmlSignature
.NamespaceURI
+ "sha1";
40 public Reference (Stream stream
) : this ()
44 public Reference (string uri
) : this ()
50 public string DigestMethod
{
51 get { return digestMethod; }
52 set { digestMethod = value; }
55 public byte[] DigestValue
{
56 get { return digestValue; }
57 set { digestValue = value; }
65 public TransformChain TransformChain
{
79 public void AddTransform (Transform transform
)
81 chain
.Add (transform
);
84 public XmlElement
GetXml ()
86 if (digestMethod
== null)
87 throw new CryptographicException ("DigestMethod");
88 if (digestValue
== null)
89 throw new NullReferenceException ("DigestValue");
91 XmlDocument document
= new XmlDocument ();
92 XmlElement xel
= document
.CreateElement (XmlSignature
.ElementNames
.Reference
, XmlSignature
.NamespaceURI
);
94 xel
.SetAttribute (XmlSignature
.AttributeNames
.Id
, id
);
96 xel
.SetAttribute (XmlSignature
.AttributeNames
.URI
, uri
);
98 xel
.SetAttribute (XmlSignature
.AttributeNames
.Type
, type
);
100 if (chain
.Count
> 0) {
101 XmlElement ts
= document
.CreateElement (XmlSignature
.ElementNames
.Transforms
, XmlSignature
.NamespaceURI
);
102 foreach (Transform t
in chain
) {
103 XmlNode xn
= t
.GetXml ();
104 XmlNode newNode
= document
.ImportNode (xn
, true);
105 ts
.AppendChild (newNode
);
107 xel
.AppendChild (ts
);
110 XmlElement dm
= document
.CreateElement (XmlSignature
.ElementNames
.DigestMethod
, XmlSignature
.NamespaceURI
);
111 dm
.SetAttribute (XmlSignature
.AttributeNames
.Algorithm
, digestMethod
);
112 xel
.AppendChild (dm
);
114 XmlElement dv
= document
.CreateElement (XmlSignature
.ElementNames
.DigestValue
, XmlSignature
.NamespaceURI
);
115 dv
.InnerText
= Convert
.ToBase64String (digestValue
);
116 xel
.AppendChild (dv
);
121 private string GetAttributeFromElement (XmlElement xel
, string attribute
, string element
)
123 string result
= null;
124 XmlNodeList xnl
= xel
.GetElementsByTagName (element
);
125 if ((xnl
!= null) && (xnl
.Count
> 0)) {
126 XmlAttribute xa
= xnl
[0].Attributes
[attribute
];
128 result
= xa
.InnerText
;
133 // note: we do NOT return null -on purpose- if attribute isn't found
134 private string GetAttribute (XmlElement xel
, string attribute
)
136 XmlAttribute xa
= xel
.Attributes
[attribute
];
137 return ((xa
!= null) ? xa
.InnerText
: null);
140 public void LoadXml (XmlElement
value)
143 throw new ArgumentNullException ("value");
145 if ((value.LocalName
!= XmlSignature
.ElementNames
.Reference
) || (value.NamespaceURI
!= XmlSignature
.NamespaceURI
))
146 throw new CryptographicException ();
148 id
= GetAttribute (value, XmlSignature
.AttributeNames
.Id
);
149 uri
= GetAttribute (value, XmlSignature
.AttributeNames
.URI
);
150 type
= GetAttribute (value, XmlSignature
.AttributeNames
.Type
);
151 // Note: order is important for validations
152 XmlNodeList xnl
= value.GetElementsByTagName (XmlSignature
.ElementNames
.Transform
);
153 if ((xnl
!= null) && (xnl
.Count
> 0)) {
155 foreach (XmlNode xn
in xnl
) {
156 string a
= GetAttribute ((XmlElement
)xn
, XmlSignature
.AttributeNames
.Algorithm
);
158 case "http://www.w3.org/2000/09/xmldsig#base64":
159 t
= new XmlDsigBase64Transform ();
161 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
162 t
= new XmlDsigC14NTransform ();
164 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
165 t
= new XmlDsigC14NWithCommentsTransform ();
167 case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
168 t
= new XmlDsigEnvelopedSignatureTransform ();
170 case "http://www.w3.org/TR/1999/REC-xpath-19991116":
171 t
= new XmlDsigXPathTransform ();
173 case "http://www.w3.org/TR/1999/REC-xslt-19991116":
174 t
= new XmlDsigXsltTransform ();
177 throw new NotSupportedException ();
183 DigestMethod
= GetAttributeFromElement (value, XmlSignature
.AttributeNames
.Algorithm
, XmlSignature
.ElementNames
.DigestMethod
);
185 xnl
= value.GetElementsByTagName (XmlSignature
.ElementNames
.DigestValue
);
186 if ((xnl
!= null) && (xnl
.Count
> 0)) {
187 DigestValue
= Convert
.FromBase64String (xnl
[0].InnerText
);