2003-03-08 Sebastien Pouliot <spouliot@videotron.ca>
[mono.git] / mcs / tools / security / sn.cs
1 //
2 // SN.cs: sn clone tool
3 //
4 // Author:
5 //      Sebastien Pouliot (spouliot@motus.com)
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 //
9
10 using System;
11 using System.IO;
12 using System.Reflection;
13 using System.Security.Cryptography;
14 using System.Text;
15
16 using Mono.Security;
17 using Mono.Security.Cryptography;
18
19 [assembly: AssemblyTitle("Mono StrongName")]
20 [assembly: AssemblyDescription("StrongName utility for signing assemblies")]
21
22 namespace Mono.Tools {
23
24         class SN {
25
26                 static private void Header () 
27                 {
28                         Assembly a = Assembly.GetExecutingAssembly ();
29                         AssemblyName an = a.GetName ();
30                 
31                         object [] att = a.GetCustomAttributes (typeof (AssemblyTitleAttribute), false);
32                         string title = ((att.Length > 0) ? ((AssemblyTitleAttribute) att [0]).Title : "Mono StrongName");
33
34                         att = a.GetCustomAttributes (typeof (AssemblyCopyrightAttribute), false);
35                         string copyright = ((att.Length > 0) ? ((AssemblyCopyrightAttribute) att [0]).Copyright : "");
36
37                         Console.WriteLine ("{0} {1}", title, an.Version.ToString ());
38                         Console.WriteLine ("{0}{1}", copyright, Environment.NewLine);
39                 }
40
41                 static string defaultCSP = null;
42
43                 static bool LoadConfig () 
44                 {
45                         // default CSP
46                         return false;
47                 }
48
49                 static int SaveConfig () 
50                 {
51                         // default CSP
52                         return 1;
53                 }
54
55                 static byte[] ReadFromFile (string fileName) 
56                 {
57                         byte[] data = null;
58                         FileStream fs = File.Open (fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
59                         try {
60                                 data = new byte [fs.Length];
61                                 fs.Read (data, 0, data.Length);
62                         }
63                         finally {
64                                 fs.Close ();
65                         }
66                         return data;
67                 }
68
69                 static void WriteToFile (string fileName, byte[] data) 
70                 {
71                         FileStream fs = File.Open (fileName, FileMode.Create, FileAccess.Write);
72                         try {
73                                 fs.Write (data, 0, data.Length);
74                         }
75                         finally {
76                                 fs.Close ();
77                         }
78                 }
79
80                 static void WriteCSVToFile (string fileName, byte[] data, string mask) 
81                 {
82                         StreamWriter sw = File.CreateText (fileName);
83                         try {
84                                 for (int i=0; i < data.Length; i++) {
85                                         if (mask [0] == 'X')
86                                                 sw.Write ("0x");
87                                         sw.Write (data [i].ToString (mask));
88                                         sw.Write (", ");
89                                 }
90                         }
91                         finally {
92                                 sw.Close ();
93                         }
94                 }
95
96                 static string ToString (byte[] data) 
97                 {
98                         StringBuilder sb = new StringBuilder ();
99                         for (int i=0; i < data.Length; i++) {
100                                 if ((i % 39 == 0) && (data.Length > 39))
101                                         sb.Append (Environment.NewLine);
102                                 sb.Append (data [i].ToString ("x2"));
103                                 if (i > 1000) {
104                                         sb.Append (" !!! TOO LONG !!!");
105                                         break;
106                                 }
107                         }
108                         return sb.ToString ();
109                 }
110
111                 static void Help (string details) 
112                 {
113                         Console.WriteLine ("Usage: sn [-q | -quiet] options [parameters]{0}", Environment.NewLine);
114                         Console.WriteLine (" -q | -quiet    \tQuiet mode (minimal display){0}", Environment.NewLine);
115                         switch (details) {
116                                 case "config":
117                                         Console.WriteLine ("Configuration options <1>");
118                                         Console.WriteLine (" -c provider{0}\tChange the default CSP provider", Environment.NewLine);
119                                         Console.WriteLine (" -m [y|n]{0}\tUse a machine [y] key container or user key container [n]", Environment.NewLine);
120                                         Console.WriteLine (" -Vl{0}\tList the verification options", Environment.NewLine);
121                                         Console.WriteLine (" -Vr assembly [userlist]{0}\tExempt the specified assembly from verification for the user list", Environment.NewLine);
122                                         Console.WriteLine (" -Vu assembly{0}\tRemove exemption entry for the specified assembly", Environment.NewLine);
123                                         Console.WriteLine (" -Vx{0}\tRemove all exemptions entries", Environment.NewLine);
124                                         break;
125                                 case "csp":
126                                         Console.WriteLine ("CSP related options <2>");
127                                         Console.WriteLine (" -d container{0}\tDelete the specified key container", Environment.NewLine);
128                                         Console.WriteLine (" -i keypair.snk container{0}\tImport the keypair from a SNK file into a CSP container", Environment.NewLine);
129                                         Console.WriteLine (" -pc container public.key{0}\tExport the public key from a CSP container to the specified file", Environment.NewLine);
130                                         break;
131                                 case "convert":
132                                         Console.WriteLine ("Convertion options");
133                                         Console.WriteLine (" -e assembly output.pub{0}\tExport the assembly public key to the specified file", Environment.NewLine);
134                                         Console.WriteLine (" -p keypair.snk output.pub{0}\tExport the public key from a SNK file to the specified file", Environment.NewLine);
135                                         Console.WriteLine (" -o input output.txt{0}\tConvert the input file to a CVS file (using decimal).", Environment.NewLine);
136                                         Console.WriteLine (" -oh input output.txt{0}\tConvert the input file to a CVS file (using hexadecimal).", Environment.NewLine);
137                                         break;
138                                 case "sn":
139                                         Console.WriteLine ("StrongName signing options");
140                                         Console.WriteLine (" -D assembly1 assembly2{0}\tCompare assembly1 and assembly2 (without signatures) <1>", Environment.NewLine);
141                                         Console.WriteLine (" -k keypair.snk{0}\tCreate a new keypair in the specified file", Environment.NewLine);
142                                         Console.WriteLine (" -R assembly keypair.snk{0}\tResign the assembly with the specified StrongName key file", Environment.NewLine);
143                                         Console.WriteLine (" -Rc assembly container{0}\tResign the assembly with the specified CSP container", Environment.NewLine);
144                                         Console.WriteLine (" -t file{0}\tShow the public key from the specified file [1]", Environment.NewLine);
145                                         Console.WriteLine (" -tp file{0}\tShow the public key and pk token from the specified file <1>", Environment.NewLine);
146                                         Console.WriteLine (" -T assembly{0}\tShow the public key from the specified assembly", Environment.NewLine);
147                                         Console.WriteLine (" -Tp assembly{0}\tShow the public key and pk token from the specified assembly", Environment.NewLine);
148                                         Console.WriteLine (" -V assembly{0}\tVerify the specified assembly signature <1>", Environment.NewLine);
149                                         Console.WriteLine (" -Vf assembly{0}\tVerify the specified assembly signature (even if disabled) <1>.", Environment.NewLine);
150                                         break;
151                                 default:
152                                         Console.WriteLine ("Help options");
153                                         Console.WriteLine (" -? | -h        \tShow this help screen about the tool");
154                                         Console.WriteLine (" -? | -h config \tConfiguration options (see strongname.xml)");
155                                         Console.WriteLine (" -? | -h csp    \tCrypto Service Provider (CSP) related options");
156                                         Console.WriteLine (" -? | -h convert\tFormat convertion options");
157                                         Console.WriteLine (" -? | -h sn     \tStrongName signing options");
158                                         break;
159                         }
160                         Console.WriteLine ("{0}<1> Currently not implemented in the tool", Environment.NewLine);
161                         Console.WriteLine ("<2> Implemented in the tool but not in Mono{0}", Environment.NewLine);
162                 }
163
164                 [STAThread]
165                 static int Main (string[] args)
166                 {
167                         if (args.Length < 1) {
168                                 Header ();
169                                 Help (null);
170                                 return 1;
171                         }
172
173                         int i = 0;
174                         string param = args [i];
175                         bool quiet = ((param == "-quiet") || (param == "-q"));
176                         if (quiet)
177                                 i++;
178                         else
179                                 Header();
180
181                         bool config = LoadConfig ();
182
183                         StrongName sn = null;
184                         AssemblyName an = null;
185                         RSACryptoServiceProvider rsa = null;
186                         CspParameters csp = new CspParameters ();
187                         csp.ProviderName = defaultCSP;
188
189                         switch (args [i++]) {
190                                 case "-c":
191                                         // Change global CSP provider options
192                                         defaultCSP = args [i];
193                                         return SaveConfig ();
194                                 case "-d":
195                                         // Delete specified key container
196                                         csp.KeyContainerName = args [i];
197                                         rsa = new RSACryptoServiceProvider (csp);
198                                         rsa.PersistKeyInCsp = false;
199                                         if (!quiet)
200                                                 Console.WriteLine ("Keypair in container {0} has been deleted", args [i]);
201                                         break;
202                                 case "-D":
203                                         Console.WriteLine ("Unimplemented option");
204                                         break;
205                                 case "-e":
206                                         // Export public key from assembly
207                                         an = AssemblyName.GetAssemblyName (args [i++]);
208                                         WriteToFile (args[i], an.GetPublicKey ());
209                                         if (!quiet)
210                                                 Console.WriteLine ("Public Key extracted to file {0}", args [i]);
211                                         break;
212                                 case "-i":
213                                         // import keypair from SNK to container
214                                         sn = new StrongName (ReadFromFile (args [i++]));
215                                         csp.KeyContainerName = args [i];
216                                         rsa = new RSACryptoServiceProvider (csp);
217                                         rsa.ImportParameters (sn.RSA.ExportParameters (true));
218                                         break;
219                                 case "-k":
220                                         // Create a new strong name key pair
221                                         // (a new RSA keypair automagically if none is present)
222                                         sn = new StrongName ();
223                                         WriteToFile (args[i], CryptoConvert.ToCapiKeyBlob (sn.RSA, true));
224                                         if (!quiet)
225                                                 Console.WriteLine ("A new strong name keypair has been generated in {0}", args [i]);
226                                         break;
227                                 case "-o":
228                                         byte[] infileD = ReadFromFile (args [i++]);
229                                         WriteCSVToFile (args [i], infileD, "D");
230                                         if (!quiet)
231                                                 Console.WriteLine ("Output CVS file is {0} (decimal format)", args [i]);
232                                         break;
233                                 case "-oh":
234                                         byte[] infileX2 = ReadFromFile (args [i++]);
235                                         WriteCSVToFile (args [i], infileX2, "X2");
236                                         if (!quiet)
237                                                 Console.WriteLine ("Output CVS file is {0} (hexadecimal format)", args [i]);
238                                         break;
239                                 case "-p":
240                                         // Extract public key from SNK file
241                                         sn = new StrongName (ReadFromFile (args [i++]));
242                                         WriteToFile (args[i], CryptoConvert.ToCapiKeyBlob (sn.RSA, false));
243                                         if (!quiet)
244                                                 Console.WriteLine ("Public Key extracted to file {0}", args [i]);
245                                         break;
246                                 case "-pc":
247                                         // Extract public key from container
248                                         csp.KeyContainerName = args [i++];
249                                         rsa = new RSACryptoServiceProvider (csp);
250                                         WriteToFile (args[i], CryptoConvert.ToCapiKeyBlob (rsa, false));
251                                         if (!quiet)
252                                                 Console.WriteLine ("Public Key extracted to file {0}", args [i]);
253                                         break;
254                                 case "-R":
255                                         Console.WriteLine ("Unimplemented option");
256                                         break;
257                                 case "-Rc":
258                                         Console.WriteLine ("Unimplemented option");
259                                         break;
260                                 case "-t":
261                                         // Show public key token from file
262                                         sn = new StrongName (ReadFromFile (args [i]));
263                                         // note: ignore quiet
264                                         Console.WriteLine ("Public Key Token: " + ToString (sn.PublicKeyToken), Environment.NewLine);
265                                         break;
266                                 case "-tp":
267                                         // Show public key and public key token from assembly
268                                         sn = new StrongName (ReadFromFile (args [i]));
269                                         // note: ignore quiet
270                                         Console.WriteLine ("Public Key:" + ToString (sn.PublicKey));
271                                         Console.WriteLine ("{0}Public Key Token: " + ToString (sn.PublicKeyToken), Environment.NewLine);
272                                         break;
273                                 case "-T":
274                                         // Show public key token from assembly
275                                         an = AssemblyName.GetAssemblyName (args [i++]);
276                                         // note: ignore quiet
277                                         Console.WriteLine ("Public Key Token: " + ToString (an.GetPublicKeyToken ()));
278                                         break;
279                                 case "-Tp":
280                                         // Show public key and public key token from assembly
281                                         an = AssemblyName.GetAssemblyName (args [i++]);
282                                         // note: ignore quiet
283                                         Console.WriteLine ("Public Key:" + ToString (an.GetPublicKey ()));
284                                         Console.WriteLine ("{0}Public Key Token: " + ToString (an.GetPublicKeyToken ()), Environment.NewLine);
285                                         break;
286                                 case "-V":
287                                         Console.WriteLine ("Unimplemented option");
288                                         break;
289                                 case "-Vf":
290                                         Console.WriteLine ("Unimplemented option");
291                                         break;
292                                 case "-Vl":
293                                         Console.WriteLine ("Unimplemented option");
294                                         break;
295                                 case "-Vr":
296                                         Console.WriteLine ("Unimplemented option");
297                                         break;
298                                 case "-Vu":
299                                         Console.WriteLine ("Unimplemented option");
300                                         break;
301                                 case "-Vx":
302                                         Console.WriteLine ("Unimplemented option");
303                                         break;
304                                 case "-?":
305                                 case "-h":
306                                         Help ((i < args.Length) ? args [i] : null);
307                                         break;
308                                 default:
309                                         if (!quiet)
310                                                 Console.WriteLine ("Unknown option {0}", args [i-1]);
311                                         return 1;
312                         }
313                         return 0;
314                 }
315         }
316 }