2 // xmldsig.cs: XML Digital Signature Tests
5 // Atsushi Enomoto <atsushi@ximian.com>
6 // Sebastien Pouliot <sebastien@ximian.com>
8 // (C) 2004 Novell (http://www.novell.com)
12 using System
.Collections
;
14 using System
.Reflection
;
15 using System
.Security
.Cryptography
;
16 using System
.Security
.Cryptography
.X509Certificates
;
17 using System
.Security
.Cryptography
.Xml
;
22 using Mono
.Security
.X509
;
24 public class MyClass
{
26 static int invalid
= 0;
33 public static void Main()
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");
43 // Non working on MS runtime;
44 // they have insufficient support for namespaces.
45 Console
.WriteLine ("PHAOS");
48 catch (Exception ex
) {
49 Console
.WriteLine (ex
);
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
);
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
);
83 static void Symmetric (string filename
, byte[] key
)
85 string shortName
= Path
.GetFileName (filename
);
87 XmlDocument doc
= new XmlDocument ();
88 doc
.PreserveWhitespace
= true;
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
);
104 Console
.WriteLine ("INVALID {0}", shortName
);
108 catch (Exception ex
) {
109 Console
.WriteLine ("EXCEPTION " + shortName
+ " " + ex
);
114 static void Asymmetric (string filename
)
116 string shortName
= Path
.GetFileName (filename
);
118 XmlDocument doc
= new XmlDocument ();
119 doc
.PreserveWhitespace
= true;
124 if (filename
.IndexOf ("enveloped") >= 0)
125 s
= new SignedXml (doc
);
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
);
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
);
151 // 1- Merlin's certificate resolution (manual)
152 // 2- Phaos (because Fx doesn't support RetrievalMethod
154 case "signature-keyname.xml":
155 mx
= LoadCertificate (GetPath (filename
, "lugh.crt"));
157 case "signature-retrievalmethod-rawx509crt.xml":
158 mx
= LoadCertificate (GetPath (filename
, "balor.crt"));
160 case "signature-x509-is.xml":
161 mx
= LoadCertificate (GetPath (filename
, "macha.crt"));
163 case "signature-x509-ski.xml":
164 mx
= LoadCertificate (GetPath (filename
, "nemain.crt"));
166 case "signature-x509-sn.xml":
167 mx
= LoadCertificate (GetPath (filename
, "badb.crt"));
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"));
177 case "signature-rsa-detached-xslt-transform-bad-retrieval-method.xml":
178 mx
= LoadCertificate (GetPath (filename
, "dsa-ca-cert.der"));
186 if (mx
.RSA
!= null) {
187 result
= s
.CheckSignature (mx
.RSA
);
189 else if (mx
.DSA
!= null) {
190 result
= s
.CheckSignature (mx
.DSA
);
194 // use a key existing in the document
195 result
= s
.CheckSignature ();
199 Console
.WriteLine ("valid " + shortName
);
203 Console
.WriteLine ("INVALID {0}", shortName
);
207 catch (Exception ex
) {
208 Console
.WriteLine ("EXCEPTION " + shortName
+ " " + ex
);
213 static void Merlin ()
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
);
223 Asymmetric (fi
.FullName
);
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.");
241 if ((fi
.Name
.IndexOf ("md5") >= 0) && (!hmacmd5
)) {
242 Console
.WriteLine ("NOT RUN: " + fi
.Name
+ " : System.Security.dll doesn't support HMAC-MD5.");
246 if (fi
.Name
.IndexOf ("hmac") >= 0) {
247 Symmetric (fi
.FullName
, key
);
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
;
310 Console
.WriteLine ("*** KeyInfoName ***");
311 Console
.WriteLine ("Value: " + kn
.Value
);
314 KeyInfoX509Data k509
= kic
as KeyInfoX509Data
;
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
);
327 class MySignedXml
: SignedXml
329 public void TestKey ()
331 Console
.WriteLine (GetPublicKey () == null);