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;
33 list = new ArrayList ();
41 public KeyInfo KeyInfo {
46 public IList ObjectList {
48 set { list = ArrayList.Adapter (value); }
51 public byte[] SignatureValue {
52 get { return signature; }
53 set { signature = value; }
56 public SignedInfo SignedInfo {
61 public void AddObject (DataObject dataObject)
63 list.Add (dataObject);
66 public XmlElement GetXml ()
69 throw new CryptographicException ("SignedInfo");
70 if (signature == null)
71 throw new CryptographicException ("SignatureValue");
73 XmlDocument document = new XmlDocument ();
74 XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Signature, XmlSignature.NamespaceURI);
76 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
78 XmlNode xn = info.GetXml ();
79 XmlNode newNode = document.ImportNode (xn, true);
80 xel.AppendChild (newNode);
82 if (signature != null) {
83 XmlElement sv = document.CreateElement (XmlSignature.ElementNames.SignatureValue, XmlSignature.NamespaceURI);
84 sv.InnerText = Convert.ToBase64String (signature);
90 newNode = document.ImportNode (xn, true);
91 xel.AppendChild (newNode);
95 foreach (DataObject obj in list) {
97 newNode = document.ImportNode (xn, true);
98 xel.AppendChild (newNode);
105 private string GetAttribute (XmlElement xel, string attribute)
107 XmlAttribute xa = xel.Attributes [attribute];
108 return ((xa != null) ? xa.InnerText : null);
111 public void LoadXml (XmlElement value)
114 throw new ArgumentNullException ("value");
116 if ((value.LocalName == XmlSignature.ElementNames.Signature) && (value.NamespaceURI == XmlSignature.NamespaceURI)) {
117 id = GetAttribute (value, XmlSignature.AttributeNames.Id);
119 // LAMESPEC: This library is totally useless against eXtensibly Marked-up document.
120 int i = NextElementPos (value.ChildNodes, 0, XmlSignature.ElementNames.SignedInfo, XmlSignature.NamespaceURI, true);
121 XmlElement sinfo = (XmlElement) value.ChildNodes [i];
122 info = new SignedInfo ();
123 info.LoadXml (sinfo);
125 i = NextElementPos (value.ChildNodes, ++i, XmlSignature.ElementNames.SignatureValue, XmlSignature.NamespaceURI, true);
126 XmlElement sigValue = (XmlElement) value.ChildNodes [i];
127 signature = Convert.FromBase64String (sigValue.InnerText);
129 // signature isn't required: <element ref="ds:KeyInfo" minOccurs="0"/>
130 i = NextElementPos (value.ChildNodes, ++i, XmlSignature.ElementNames.KeyInfo, XmlSignature.NamespaceURI, false);
132 XmlElement kinfo = (XmlElement) value.ChildNodes [i];
133 key = new KeyInfo ();
137 XmlNodeList xnl = value.SelectNodes ("xd:Object", dsigNsmgr);
138 foreach (XmlElement xn in xnl) {
139 DataObject obj = new DataObject ();
145 throw new CryptographicException ("Malformed element: Signature.");
149 throw new CryptographicException ("SignedInfo");
150 if (signature == null)
151 throw new CryptographicException ("SignatureValue");
154 private int NextElementPos (XmlNodeList nl, int pos, string name, string ns, bool required)
156 while (pos < nl.Count) {
157 if (nl [pos].NodeType == XmlNodeType.Element) {
158 if (nl [pos].LocalName != name && nl [pos].NamespaceURI != ns) {
160 throw new CryptographicException ("Malformed element " + name);
170 throw new CryptographicException ("Malformed element " + name);