2 // Signature.cs - Signature implementation for XML Signature
5 // Sebastien Pouliot (spouliot@motus.com)
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
10 using System.Collections;
11 using System.Security.Cryptography;
14 namespace System.Security.Cryptography.Xml {
16 public class Signature {
17 static XmlNamespaceManager dsigNsmgr;
21 dsigNsmgr = new XmlNamespaceManager (new NameTable ());
22 dsigNsmgr.AddNamespace ("xd", XmlSignature.NamespaceURI);
25 private ArrayList list;
26 private SignedInfo info;
29 private byte[] signature;
30 private XmlElement element;
34 list = new ArrayList ();
45 public KeyInfo KeyInfo {
53 public IList ObjectList {
55 set { list = ArrayList.Adapter (value); }
58 public byte[] SignatureValue {
59 get { return signature; }
66 public SignedInfo SignedInfo {
74 public void AddObject (DataObject dataObject)
76 list.Add (dataObject);
79 public XmlElement GetXml ()
85 throw new CryptographicException ("SignedInfo");
86 if (signature == null)
87 throw new CryptographicException ("SignatureValue");
89 XmlDocument document = new XmlDocument ();
90 XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Signature, XmlSignature.NamespaceURI);
92 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
94 XmlNode xn = info.GetXml ();
95 XmlNode newNode = document.ImportNode (xn, true);
96 xel.AppendChild (newNode);
98 if (signature != null) {
99 XmlElement sv = document.CreateElement (XmlSignature.ElementNames.SignatureValue, XmlSignature.NamespaceURI);
100 sv.InnerText = Convert.ToBase64String (signature);
101 xel.AppendChild (sv);
106 newNode = document.ImportNode (xn, true);
107 xel.AppendChild (newNode);
110 if (list.Count > 0) {
111 foreach (DataObject obj in list) {
113 newNode = document.ImportNode (xn, true);
114 xel.AppendChild (newNode);
121 private string GetAttribute (XmlElement xel, string attribute)
123 XmlAttribute xa = xel.Attributes [attribute];
124 return ((xa != null) ? xa.InnerText : null);
127 public void LoadXml (XmlElement value)
130 throw new ArgumentNullException ("value");
132 if ((value.LocalName == XmlSignature.ElementNames.Signature) && (value.NamespaceURI == XmlSignature.NamespaceURI)) {
133 id = GetAttribute (value, XmlSignature.AttributeNames.Id);
135 // LAMESPEC: This library is totally useless against eXtensibly Marked-up document.
136 int i = NextElementPos (value.ChildNodes, 0, XmlSignature.ElementNames.SignedInfo, XmlSignature.NamespaceURI, true);
137 XmlElement sinfo = (XmlElement) value.ChildNodes [i];
138 info = new SignedInfo ();
139 info.LoadXml (sinfo);
141 i = NextElementPos (value.ChildNodes, ++i, XmlSignature.ElementNames.SignatureValue, XmlSignature.NamespaceURI, true);
142 XmlElement sigValue = (XmlElement) value.ChildNodes [i];
143 signature = Convert.FromBase64String (sigValue.InnerText);
145 // signature isn't required: <element ref="ds:KeyInfo" minOccurs="0"/>
146 i = NextElementPos (value.ChildNodes, ++i, XmlSignature.ElementNames.KeyInfo, XmlSignature.NamespaceURI, false);
148 XmlElement kinfo = (XmlElement) value.ChildNodes [i];
149 key = new KeyInfo ();
153 XmlNodeList xnl = value.SelectNodes ("xd:Object", dsigNsmgr);
154 foreach (XmlElement xn in xnl) {
155 DataObject obj = new DataObject ();
161 throw new CryptographicException ("Malformed element: Signature.");
165 throw new CryptographicException ("SignedInfo");
166 if (signature == null)
167 throw new CryptographicException ("SignatureValue");
170 private int NextElementPos (XmlNodeList nl, int pos, string name, string ns, bool required)
172 while (pos < nl.Count) {
173 if (nl [pos].NodeType == XmlNodeType.Element) {
174 if (nl [pos].LocalName != name && nl [pos].NamespaceURI != ns) {
176 throw new CryptographicException ("Malformed element " + name);
186 throw new CryptographicException ("Malformed element " + name);