2 // KeyInfoX509Data.cs - KeyInfoX509Data implementation for XML Signature
5 // Sebastien Pouliot (spouliot@motus.com)
6 // Atsushi Enomoto (atsushi@ximian.com)
8 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
9 // (C) 2004 Novell Inc.
12 using System.Collections;
13 using System.Security.Cryptography.X509Certificates;
16 namespace System.Security.Cryptography.Xml {
18 // FIXME: framework class isn't documented so compatibility isn't assured!
19 internal class IssuerSerial
24 public IssuerSerial (string issuer, string serial)
31 public class KeyInfoX509Data : KeyInfoClause
34 private byte[] x509crl;
35 private ArrayList IssuerSerialList;
36 private ArrayList SubjectKeyIdList;
37 private ArrayList SubjectNameList;
38 private ArrayList X509CertificateList;
40 public KeyInfoX509Data ()
42 IssuerSerialList = new ArrayList ();
43 SubjectKeyIdList = new ArrayList ();
44 SubjectNameList = new ArrayList ();
45 X509CertificateList = new ArrayList ();
48 public KeyInfoX509Data (byte[] rgbCert) : this ()
50 AddCertificate (new X509Certificate (rgbCert));
53 public KeyInfoX509Data (X509Certificate cert) : this ()
55 AddCertificate (cert);
58 public ArrayList Certificates {
59 get { return X509CertificateList.Count != 0 ? X509CertificateList : null; }
63 get { return x509crl; }
64 set { x509crl = value; }
67 public ArrayList IssuerSerials {
68 get { return IssuerSerialList.Count != 0 ? IssuerSerialList : null; }
71 public ArrayList SubjectKeyIds {
72 get { return SubjectKeyIdList.Count != 0 ? SubjectKeyIdList : null; }
75 public ArrayList SubjectNames {
76 get { return SubjectNameList.Count != 0 ? SubjectNameList : null; }
79 public void AddCertificate (X509Certificate certificate)
81 X509CertificateList.Add (certificate);
84 public void AddIssuerSerial (string issuerName, string serialNumber)
86 IssuerSerial isser = new IssuerSerial (issuerName, serialNumber);
87 IssuerSerialList.Add (isser);
90 public void AddSubjectKeyId (byte[] subjectKeyId)
92 SubjectKeyIdList.Add (subjectKeyId);
95 public void AddSubjectName (string subjectName)
97 SubjectNameList.Add (subjectName);
100 public override XmlElement GetXml ()
103 int count = IssuerSerialList.Count + SubjectKeyIdList.Count + SubjectNameList.Count + X509CertificateList.Count;
104 if ((x509crl == null) && (count == 0))
105 throw new CryptographicException ("value");
107 XmlDocument document = new XmlDocument ();
108 XmlElement xel = document.CreateElement (XmlSignature.ElementNames.X509Data, XmlSignature.NamespaceURI);
109 // FIXME: hack to match MS implementation
110 xel.SetAttribute ("xmlns", XmlSignature.NamespaceURI);
111 // <X509IssuerSerial>
112 if (IssuerSerialList.Count > 0) {
113 foreach (IssuerSerial iser in IssuerSerialList) {
114 XmlElement isl = document.CreateElement (XmlSignature.ElementNames.X509IssuerSerial, XmlSignature.NamespaceURI);
115 XmlElement xin = document.CreateElement (XmlSignature.ElementNames.X509IssuerName, XmlSignature.NamespaceURI);
116 xin.InnerText = iser.Issuer;
117 isl.AppendChild (xin);
118 XmlElement xsn = document.CreateElement (XmlSignature.ElementNames.X509SerialNumber, XmlSignature.NamespaceURI);
119 xsn.InnerText = iser.Serial;
120 isl.AppendChild (xsn);
121 xel.AppendChild (isl);
125 if (SubjectKeyIdList.Count > 0) {
126 foreach (byte[] skid in SubjectKeyIdList) {
127 XmlElement ski = document.CreateElement (XmlSignature.ElementNames.X509SKI, XmlSignature.NamespaceURI);
128 ski.InnerText = Convert.ToBase64String (skid);
129 xel.AppendChild (ski);
133 if (SubjectNameList.Count > 0) {
134 foreach (string subject in SubjectNameList) {
135 XmlElement sn = document.CreateElement (XmlSignature.ElementNames.X509SubjectName, XmlSignature.NamespaceURI);
136 sn.InnerText = subject;
137 xel.AppendChild (sn);
141 if (X509CertificateList.Count > 0) {
142 foreach (X509Certificate x509 in X509CertificateList) {
143 XmlElement cert = document.CreateElement (XmlSignature.ElementNames.X509Certificate, XmlSignature.NamespaceURI);
144 cert.InnerText = Convert.ToBase64String (x509.GetRawCertData ());
145 xel.AppendChild (cert);
148 // only one <X509CRL>
149 if (x509crl != null) {
150 XmlElement crl = document.CreateElement (XmlSignature.ElementNames.X509CRL, XmlSignature.NamespaceURI);
151 crl.InnerText = Convert.ToBase64String (x509crl);
152 xel.AppendChild (crl);
157 public override void LoadXml (XmlElement element)
160 throw new ArgumentNullException ("element");
162 IssuerSerialList.Clear ();
163 SubjectKeyIdList.Clear ();
164 SubjectNameList.Clear ();
165 X509CertificateList.Clear ();
168 if ((element.LocalName != XmlSignature.ElementNames.X509Data) || (element.NamespaceURI != XmlSignature.NamespaceURI))
169 throw new CryptographicException ("element");
171 XmlElement [] xnl = null;
172 // <X509IssuerSerial>
173 xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509IssuerSerial);
175 for (int i=0; i < xnl.Length; i++) {
176 XmlElement xel = (XmlElement) xnl[i];
177 XmlElement issuer = XmlSignature.GetChildElement (xel, XmlSignature.ElementNames.X509IssuerName, XmlSignature.NamespaceURI);
178 XmlElement serial = XmlSignature.GetChildElement (xel, XmlSignature.ElementNames.X509SerialNumber, XmlSignature.NamespaceURI);
179 AddIssuerSerial (issuer.InnerText, serial.InnerText);
183 xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509SKI);
185 for (int i=0; i < xnl.Length; i++) {
186 byte[] skid = Convert.FromBase64String (xnl[i].InnerXml);
187 AddSubjectKeyId (skid);
191 xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509SubjectName);
193 for (int i=0; i < xnl.Length; i++) {
194 AddSubjectName (xnl[i].InnerXml);
198 xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509Certificate);
200 for (int i=0; i < xnl.Length; i++) {
201 byte[] cert = Convert.FromBase64String (xnl[i].InnerXml);
202 AddCertificate (new X509Certificate (cert));
205 // only one <X509CRL>
206 XmlElement x509el = XmlSignature.GetChildElement (element, XmlSignature.ElementNames.X509CRL, XmlSignature.NamespaceURI);
207 if (x509el != null) {
208 x509crl = Convert.FromBase64String (x509el.InnerXml);