**** Merged from MCS ****
[mono-project.git] / mcs / class / System.Security / Test / standalone_tests / xmldsig.cs
blobbcf42fc3b716caa77064591ace776ea3e0094bec
1 //
2 // xmldsig.cs: XML Digital Signature Tests
3 //
4 // Authors:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 // Sebastien Pouliot <sebastien@ximian.com>
7 //
8 // (C) 2004 Novell (http://www.novell.com)
9 //
11 using System;
12 using System.Collections;
13 using System.IO;
14 using System.Reflection;
15 using System.Security.Cryptography;
16 using System.Security.Cryptography.X509Certificates;
17 using System.Security.Cryptography.Xml;
18 using System.Text;
19 using System.Xml;
20 using System.Xml.Xsl;
22 using Mono.Security.X509;
24 public class MyClass {
25 static int valid = 0;
26 static int invalid = 0;
27 static int error = 0;
28 static int skip = 0;
30 static bool exc14n;
31 static bool hmacmd5;
33 public static void Main()
35 try {
36 // automagically ajust tests to run depending on system config
37 exc14n = (CryptoConfig.CreateFromName ("http://www.w3.org/2001/10/xml-exc-c14n#WithComments") != null);
38 hmacmd5 = (CryptoConfig.CreateFromName ("HMACMD5") != null);
40 Console.WriteLine ("MERLIN");
41 Merlin ();
42 Console.WriteLine ();
43 // Non working on MS runtime;
44 // they have insufficient support for namespaces.
45 Console.WriteLine ("PHAOS");
46 Phaos ();
48 catch (Exception ex) {
49 Console.WriteLine (ex);
51 finally {
52 Console.WriteLine ();
53 Console.WriteLine ("TOTAL VALID {0}", valid);
54 Console.WriteLine ("TOTAL INVALID {0}", invalid);
55 Console.WriteLine ("TOTAL ERROR {0}", error);
56 Console.WriteLine ("TOTAL SKIP {0}", skip);
58 Console.WriteLine ("Finished.");
62 static Mono.Security.X509.X509Certificate LoadCertificate (string filename)
64 Mono.Security.X509.X509Certificate mx = null;
65 if (File.Exists (filename)) {
66 using (FileStream fs = File.OpenRead (filename)) {
67 byte[] data = new byte [fs.Length];
68 fs.Read (data, 0, data.Length);
69 mx = new Mono.Security.X509.X509Certificate (data);
72 return mx;
75 static string GetPath (string dir, string name)
77 string path = Path.GetDirectoryName (dir);
78 path = Path.Combine (path, "certs");
79 path = Path.Combine (path, name);
80 return path;
83 static void Symmetric (string filename, byte[] key)
85 string shortName = Path.GetFileName (filename);
87 XmlDocument doc = new XmlDocument ();
88 doc.PreserveWhitespace = true;
89 doc.Load (filename);
91 try {
92 XmlNodeList nodeList = doc.GetElementsByTagName ("Signature", SignedXml.XmlDsigNamespaceUrl);
93 XmlElement signature = (XmlElement) nodeList [0];
95 SignedXml s = new SignedXml ();
96 s.LoadXml (signature);
98 HMACSHA1 mac = new HMACSHA1 (key);
99 if (s.CheckSignature (mac)) {
100 Console.WriteLine ("valid {0}", shortName);
101 valid++;
103 else {
104 Console.WriteLine ("INVALID {0}", shortName);
105 invalid++;
108 catch (Exception ex) {
109 Console.WriteLine ("EXCEPTION " + shortName + " " + ex);
110 error++;
114 static void Asymmetric (string filename)
116 string shortName = Path.GetFileName (filename);
118 XmlDocument doc = new XmlDocument ();
119 doc.PreserveWhitespace = true;
120 doc.Load (filename);
122 try {
123 SignedXml s = null;
124 if (filename.IndexOf ("enveloped") >= 0)
125 s = new SignedXml (doc);
126 else
127 s = new SignedXml ();
129 XmlNodeList nodeList = doc.GetElementsByTagName ("Signature", "http://www.w3.org/2000/09/xmldsig#");
130 s.LoadXml ((XmlElement) nodeList [0]);
132 #if false // wanna dump?
133 Console.WriteLine ("\n\nFilename : " + fi.Name);
134 DumpSignedXml (s);
135 #endif
136 // MS doesn't extract the public key out of the certificates
137 // http://www.dotnet247.com/247reference/a.aspx?u=http://www.kbalertz.com/Feedback_320602.aspx
138 Mono.Security.X509.X509Certificate mx = null;
139 foreach (KeyInfoClause kic in s.KeyInfo) {
140 if (kic is KeyInfoX509Data) {
141 KeyInfoX509Data kix = (kic as KeyInfoX509Data);
142 if ((kix.Certificates != null) && (kix.Certificates.Count > 0)) {
143 System.Security.Cryptography.X509Certificates.X509Certificate x509 = (System.Security.Cryptography.X509Certificates.X509Certificate) kix.Certificates [0];
144 byte[] data = x509.GetRawCertData ();
145 mx = new Mono.Security.X509.X509Certificate (data);
150 // special cases
151 // 1- Merlin's certificate resolution (manual)
152 // 2- Phaos (because Fx doesn't support RetrievalMethod
153 switch (shortName) {
154 case "signature-keyname.xml":
155 mx = LoadCertificate (GetPath (filename, "lugh.crt"));
156 break;
157 case "signature-retrievalmethod-rawx509crt.xml":
158 mx = LoadCertificate (GetPath (filename, "balor.crt"));
159 break;
160 case "signature-x509-is.xml":
161 mx = LoadCertificate (GetPath (filename, "macha.crt"));
162 break;
163 case "signature-x509-ski.xml":
164 mx = LoadCertificate (GetPath (filename, "nemain.crt"));
165 break;
166 case "signature-x509-sn.xml":
167 mx = LoadCertificate (GetPath (filename, "badb.crt"));
168 break;
169 // Phaos
170 case "signature-big.xml":
171 case "signature-rsa-manifest-x509-data-issuer-serial.xml":
172 case "signature-rsa-manifest-x509-data-ski.xml":
173 case "signature-rsa-manifest-x509-data-subject-name.xml":
174 case "signature-rsa-detached-xslt-transform-retrieval-method.xml":
175 mx = LoadCertificate (GetPath (filename, "rsa-cert.der"));
176 break;
177 case "signature-rsa-detached-xslt-transform-bad-retrieval-method.xml":
178 mx = LoadCertificate (GetPath (filename, "dsa-ca-cert.der"));
179 break;
180 default:
181 break;
184 bool result = false;
185 if (mx != null) {
186 if (mx.RSA != null) {
187 result = s.CheckSignature (mx.RSA);
189 else if (mx.DSA != null) {
190 result = s.CheckSignature (mx.DSA);
193 else {
194 // use a key existing in the document
195 result = s.CheckSignature ();
198 if (result) {
199 Console.WriteLine ("valid " + shortName);
200 valid++;
202 else {
203 Console.WriteLine ("INVALID {0}", shortName);
204 invalid++;
207 catch (Exception ex) {
208 Console.WriteLine ("EXCEPTION " + shortName + " " + ex);
209 error++;
213 static void Merlin ()
215 // see README
216 byte[] key = Encoding.ASCII.GetBytes ("secret");
218 foreach (FileInfo fi in new DirectoryInfo ("merlin-xmldsig-twenty-three").GetFiles ("signature-*.xml")) {
219 if (fi.Name.IndexOf ("hmac") >= 0) {
220 Symmetric (fi.FullName, key);
222 else {
223 Asymmetric (fi.FullName);
228 static void Phaos ()
230 // see README
231 byte[] key = Encoding.ASCII.GetBytes ("test");
233 // some documents references other documents in the directory
234 Directory.SetCurrentDirectory ("phaos-xmldsig-three");
235 foreach (FileInfo fi in new DirectoryInfo (".").GetFiles ("signature-*.xml")) {
236 if ((fi.Name.IndexOf ("exclusive") >= 0) && (!exc14n)) {
237 Console.WriteLine ("NOT RUN: " + fi.Name + " : System.Security.dll cannot validate exclusive-c14n.");
238 skip++;
239 continue;
241 if ((fi.Name.IndexOf ("md5") >= 0) && (!hmacmd5)) {
242 Console.WriteLine ("NOT RUN: " + fi.Name + " : System.Security.dll doesn't support HMAC-MD5.");
243 skip++;
244 continue;
246 if (fi.Name.IndexOf ("hmac") >= 0) {
247 Symmetric (fi.FullName, key);
249 else {
250 Asymmetric (fi.FullName);
253 // return home before next tests
254 Directory.SetCurrentDirectory ("..");
257 // dump methods under construction ;-)
259 static void DumpSignedXml (SignedXml s)
261 Console.WriteLine ("*** SignedXml ***");
262 Console.WriteLine (s.SigningKeyName);
263 Console.WriteLine (s.SigningKey);
264 if (s.Signature != null)
265 DumpSignature (s.Signature);
266 if (s.SignedInfo != null)
267 DumpSignedInfo (s.SignedInfo);
268 Console.WriteLine (s.SignatureMethod);
269 Console.WriteLine (s.SignatureLength);
270 Console.WriteLine (s.SignatureValue);
271 if (s.KeyInfo != null)
272 DumpKeyInfo (s.KeyInfo);
275 static void DumpSignature (Signature s)
277 Console.WriteLine ("*** Signature ***");
278 Console.WriteLine ("Id: " + s.Id);
279 if (s.KeyInfo != null)
280 DumpKeyInfo (s.KeyInfo);
281 Console.WriteLine ("ObjectList: " + s.ObjectList);
282 Console.WriteLine ("SignatureValue: " + s.SignatureValue);
283 if (s.SignedInfo != null)
284 DumpSignedInfo (s.SignedInfo);
287 static void DumpSignedInfo (SignedInfo s)
289 Console.WriteLine ("*** SignedInfo ***");
290 Console.WriteLine ("CanonicalizationMethod: " + s.CanonicalizationMethod);
291 Console.WriteLine ("Id: " + s.Id);
292 Console.WriteLine ("References: " + s.References);
293 Console.WriteLine ("SignatureLength: " + s.SignatureLength);
294 Console.WriteLine ("SignatureMethod: " + s.SignatureMethod);
297 static void DumpKeyInfo (KeyInfo ki)
299 Console.WriteLine ("*** KeyInfo ***" + ki);
300 Console.WriteLine ("Id: " + ki.Id);
301 Console.WriteLine ("Count: " + ki.Count);
302 foreach (KeyInfoClause kic in ki)
303 DumpKeyInfoClause (kic);
306 static void DumpKeyInfoClause (KeyInfoClause kic)
308 KeyInfoName kn = kic as KeyInfoName;
309 if (kn != null) {
310 Console.WriteLine ("*** KeyInfoName ***");
311 Console.WriteLine ("Value: " + kn.Value);
312 return;
314 KeyInfoX509Data k509 = kic as KeyInfoX509Data;
315 if (k509 != null) {
316 Console.WriteLine ("*** KeyInfoX509Data ***");
317 Console.WriteLine ("Certificates : " + k509.Certificates);
318 Console.WriteLine ("CRL : " + k509.CRL);
319 Console.WriteLine ("IssuerSerials : " + k509.IssuerSerials);
320 Console.WriteLine ("SubjectKeyIds : " + k509.SubjectKeyIds);
321 Console.WriteLine ("SubjectNames : " + k509.SubjectNames);
322 return;
327 class MySignedXml : SignedXml
329 public void TestKey ()
331 Console.WriteLine (GetPublicKey () == null);