1  using System;
  2  using System.Diagnostics;
  3  using System.Globalization;
  4  using System.Text;
  5  using MS.StrongName;
  6  
  7  namespace MS.StrongName.ManagedSN
  8  {
  9      /// <summary>
10      ///     Handler for each of the commands that the managed strong name tool implements
11      /// </summary>
12      internal static class Commands
13      {
14          /// <summary>
15          ///     Delete a key pair from a key container (-d)
16          /// </summary>
17          /// <remarks>
18          ///     Expects one argument, the key container name
19          /// </remarks>
20          /// <returns>SuccessCode if the key was removed, ErrorCode otherwise</returns>
21          public static int DeleteKeyPair(string[] arguments)
22          {
23              Debug.Assert(arguments != null, "Null arguments");
24  
25              if(arguments.Length != 2)
26              {
27                  Help(arguments);
28                  return ManagedStrongName.ErrorCode;
29              }
30  
31              Debug.Assert(arguments[0].EndsWith("d"));
32  
33              // parse the arguments
34              string keyContainer = arguments[1];
35              if(String.IsNullOrEmpty(keyContainer) || String.IsNullOrEmpty(keyContainer.Trim()))
36              {
37                  Log.Error(String.Format(
38                      CultureInfo.CurrentCulture,
39                      Resources.BadKeyContainer,
40                      keyContainer));
41                  return ManagedStrongName.ErrorCode;
42              }
43  
44              // remove the key container
45              try
46              {
47                  Keys.Delete(keyContainer);
48              }
49              catch(InvalidOperationException e)
50              {
51                  Log.Error(String.Format(
52                      CultureInfo.CurrentCulture,
53                      Resources.BadOperation,
54                      e.Message));
55                  return ManagedStrongName.ErrorCode;
56              }
57  
58              Log.Message(String.Format(
59                  CultureInfo.CurrentCulture,
60                  Resources.KeyContainerDeleted,
61                  keyContainer));
62              return ManagedStrongName.SuccessCode;
63          }
64  
65          /// <summary>
66          ///     Display the public key token of an assembly (-T)
67          /// </summary>
68          /// <remarks>
69          ///     Expects one argument, the assembly to get the token of
70          /// </remarks>
71          /// <returns>SuccessCode if the token was displayed properly, ErrorCode otherwise</returns>
72          public static int DisplayPublicKeyTokenFromAssembly(string[] arguments)
73          {
74              Debug.Assert(arguments != null, "Null arguments");
75              
76              if(arguments.Length != 2)
77              {
78                  Help(arguments);
79                  return ManagedStrongName.ErrorCode;
80              }
81  
82              Debug.Assert(arguments[0].EndsWith("T"));
83  
84              // parse the arguments
85              string assembly = arguments[1];
86              if(String.IsNullOrEmpty(assembly))
87              {
88                  Log.Error(String.Format(
89                      CultureInfo.CurrentCulture,
90                      Resources.BadFile,
91                      String.Empty));
92                  return ManagedStrongName.ErrorCode;
93              }    
94  
95              return DisplayPublicKeyTokenFromAssembly(assembly, false);            
96          }
97  
98          /// <summary>
99          ///     Display the public key token and public key of an assembly (-Tp)
100          /// </summary>
101          /// <remarks>
102          ///     Expects one argument, the assembly to get the token of
103          /// </remarks>
104          /// <returns>SuccessCode if the token was displayed properly, ErrorCode otherwise</returns>        
105          public static int DisplayPublicKeyTokenWithKeyFromAssembly(string[] arguments)
106          {
107              Debug.Assert(arguments != null, "Null arguments");
108              
109              if(arguments.Length != 2)
110              {
111                  Help(arguments);
112                  return ManagedStrongName.ErrorCode;
113              }
114  
115              Debug.Assert(arguments[0].EndsWith("Tp"));
116  
117              // parse the arguments
118              string assembly = arguments[1];
119              if(String.IsNullOrEmpty(assembly))
120              {
121                  Log.Error(String.Format(
122                      CultureInfo.CurrentCulture,
123                      Resources.BadFile,
124                      String.Empty));
125                  return ManagedStrongName.ErrorCode;
126              }    
127  
128              return DisplayPublicKeyTokenFromAssembly(assembly, true);            
129          }
130          
131          /// <summary>
132          ///     Display the public key token of a file (-t)
133          /// </summary>
134          /// <remarks>
135          ///     Expects one argument, the public key to get the token of
136          /// </remarks>
137          /// <returns>SuccessCode if the token was displayed properly, ErrorCode otherwise</returns>
138          public static int DisplayPublicKeyTokenFromFile(string[] arguments)
139          {
140              Debug.Assert(arguments != null, "Null arguments");
141              
142              if(arguments.Length != 2)
143              {
144                  Help(arguments);
145                  return ManagedStrongName.ErrorCode;
146              }
147  
148              Debug.Assert(arguments[0].EndsWith("t"));
149  
150              // parse the arguments
151              string publicKeyFile = arguments[1];
152              if(String.IsNullOrEmpty(publicKeyFile))
153              {
154                  Log.Error(String.Format(
155                      CultureInfo.CurrentCulture,
156                      Resources.BadFile,
157                      String.Empty));
158                  return ManagedStrongName.ErrorCode;
159              }    
160  
161              return DisplayPublicKeyTokenFromFile(publicKeyFile, false);
162          }
163  
164          /// <summary>
165          ///     Display the public key token of a file along with the key (-tp)
166          /// </summary>
167          /// <remarks>
168          ///     Expects one argument, the public key to get the token of
169          /// </remarks>
170          /// <returns>SuccessCode if the token was displayed properly, ErrorCode otherwise</returns>        
171          public static int DisplayPublicKeyTokenWithKeyFromFile(string[] arguments)
172          {
173              Debug.Assert(arguments != null, "Null arguments");
174              
175              if(arguments.Length != 2)
176              {
177                  Help(arguments);
178                  return ManagedStrongName.ErrorCode;
179              }
180  
181              Debug.Assert(arguments[0].EndsWith("tp"));
182  
183              // parse the arguments
184              string publicKeyFile = arguments[1];
185              if(String.IsNullOrEmpty(publicKeyFile))
186              {
187                  Log.Error(String.Format(
188                      CultureInfo.CurrentCulture,
189                      Resources.BadFile,
190                      String.Empty));
191                  return ManagedStrongName.ErrorCode;
192              }
193  
194              return DisplayPublicKeyTokenFromFile(publicKeyFile, true);
195          }
196          
197          /// <summary>
198          ///     Extract the public key from an assembly (-e)
199          /// </summary>
200          /// <remarks>
201          ///     Expects two arguments, the assembly and the file to write into
202          /// </remarks>
203          /// <returns>SuccessCode if the key was extracted properly, ErrorCode otherwise</returns>
204          public static int ExtractAssemblyPublicKey(string[] arguments)
205          {
206              Debug.Assert(arguments != null, "Null arguments");
207              
208              if(arguments.Length != 3)
209              {
210                  Help(arguments);
211                  return ManagedStrongName.ErrorCode;
212              }
213  
214              Debug.Assert(arguments[0].EndsWith("e"));
215  
216              // parse the arguments
217              string assembly = arguments[1];
218              string output = arguments[2];
219  
220              if(String.IsNullOrEmpty(assembly) || String.IsNullOrEmpty(output))
221              {
222                  Log.Error(String.Format(
223                      CultureInfo.CurrentCulture,
224                      Resources.BadFile,
225                      String.Empty));
226                  return ManagedStrongName.ErrorCode;
227              }
228  
229              // do the extraction, and write it out
230              try
231              {
232                  byte[] keyBlob = Keys.ExtractPublicKeyFromAssembly(assembly);
233                  KeyFile.WriteKeyFile(keyBlob, output);
234              }
235              catch(InvalidOperationException e)
236              {
237                  Log.Error(String.Format(
238                      CultureInfo.CurrentCulture,
239                      Resources.BadOperation,
240                      e.Message));
241                  return ManagedStrongName.ErrorCode;
242              }
243  
244              Log.Message(String.Format(
245                  CultureInfo.CurrentCulture,
246                  Resources.PublicKeyExtracted,
247                  output));
248              return ManagedStrongName.SuccessCode;
249          }
250  
251          /// <summary>
252          ///     Extract the public key from a key container (-pc)
253          /// </summary>
254          /// <remarks>
255          ///     Expects two arguments, the key container and the file to write into
256          /// </remarks>
257          /// <returns>SuccessCode if the key was extracted properly, ErrorCode otherwise</returns>
258          public static int ExtractPublicKeyFromKeyContainer(string[] arguments)
259          {
260              Debug.Assert(arguments != null, "Null arguments");
261              
262              if(arguments.Length != 3)
263              {
264                  Help(arguments);
265                  return ManagedStrongName.ErrorCode;
266              }
267  
268              // parse the arguments
269              string keyContainer = arguments[1];
270              string output = arguments[2];
271  
272              if(String.IsNullOrEmpty(keyContainer) || String.IsNullOrEmpty(output))
273              {
274                  Log.Error(String.Format(
275                      CultureInfo.CurrentCulture,
276                      Resources.BadFile,
277                      String.Empty));
278                  return ManagedStrongName.ErrorCode;
279              }
280  
281              // do the extraction, and write it out
282              try
283              {
284                  byte[] keyBlob = Keys.ExtractPublicKeyFromKeyContainer(keyContainer);
285                  KeyFile.WriteKeyFile(keyBlob, output);
286              }
287              catch(InvalidOperationException e)
288              {
289                  Log.Error(String.Format(
290                      CultureInfo.CurrentCulture,
291                      Resources.BadOperation,
292                      e.Message));
293                  return ManagedStrongName.ErrorCode;
294              }
295  
296              Log.Message(String.Format(
297                  CultureInfo.CurrentCulture,
298                  Resources.PublicKeyExtracted,
299                  output));
300              return ManagedStrongName.SuccessCode;
301          }
302  
303          /// <summary>
304          ///     Extract the public key from a key pair (-p)
305          /// </summary>
306          /// <remarks>
307          ///     Expects two arguments, the input file and the file to write into
308          /// </remarks>
309          /// <returns>SuccessCode if the key was extracted properly, ErrorCode otherwise</returns>
310          public static int ExtractPublicKeyFromKeyPair(string[] arguments)
311          {
312              Debug.Assert(arguments != null, "Null arguments");
313              
314              if(arguments.Length != 3)
315              {
316                  Help(arguments);
317                  return ManagedStrongName.ErrorCode;
318              }
319  
320              // parse the arguments
321              string keyFile = arguments[1];
322              string output = arguments[2];
323  
324              if(String.IsNullOrEmpty(keyFile) || String.IsNullOrEmpty(output))
325              {
326                  Log.Error(String.Format(
327                      CultureInfo.CurrentCulture,
328                      Resources.BadFile,
329                      String.Empty));
330                  return ManagedStrongName.ErrorCode;
331              }
332  
333              // do the extraction, and write it out
334              try
335              {
336                  byte[] keyBlob = Keys.ExtractPublicKeyFromKeyPair(KeyFile.ReadKeyFile(keyFile));
337                  KeyFile.WriteKeyFile(keyBlob, output);
338              }
339              catch(InvalidOperationException e)
340              {
341                  Log.Error(String.Format(
342                      CultureInfo.CurrentCulture,
343                      Resources.BadOperation,
344                      e.Message));
345                  return ManagedStrongName.ErrorCode;
346              }
347  
348              Log.Message(String.Format(
349                  CultureInfo.CurrentCulture,
350                  Resources.PublicKeyExtracted,
351                  output));
352              return ManagedStrongName.SuccessCode;
353          }
354  
355          /// <summary>
356          ///     Verify an assembly, ignoring the skip verification registry (-vf)
357          /// </summary>
358          /// <remarks>
359          ///     Expects one argument, the name of the assembly to verify
360          /// </remarks>
361          /// <returns>SuccessCode if the signature verifies, ErrorCode otherwise</returns>
362          public static int ForceVerify(string[] arguments)
363          {
364              Debug.Assert(arguments != null, "Null arguments");
365  
366              if(arguments.Length != 2)
367              {
368                  Help(arguments);
369                  return ManagedStrongName.ErrorCode;
370              }
371  
372              Debug.Assert(arguments[0].EndsWith("vf"));
373  
374              string assembly = arguments[1];
375              if(String.IsNullOrEmpty(assembly))
376              {
377                  Log.Error(String.Format(
378                      CultureInfo.CurrentCulture,
379                      Resources.BadFile,
380                      String.Empty));
381                  return ManagedStrongName.ErrorCode;
382              }
383  
384              switch(Signatures.VerifyAssembly(assembly, true))
385              {
386                  case VerificationResult.NotVerified:
387                      Log.Message(String.Format(
388                          CultureInfo.CurrentCulture,
389                          Resources.AssemblyNotVerified,
390                          assembly));
391                      return ManagedStrongName.ErrorCode;
392  
393                  case VerificationResult.DelaySigned:
394                      Log.Message(String.Format(
395                          CultureInfo.CurrentCulture,
396                          Resources.AssemblyDelaySigned,
397                          assembly));
398                      return ManagedStrongName.SuccessCode;
399  
400                  case VerificationResult.Verified:                  
401                      Log.Message(String.Format(
402                          CultureInfo.CurrentCulture,
403                          Resources.AssemblyVerified,
404                          assembly));
405                      return ManagedStrongName.SuccessCode;
406  
407                  default:
408                      Debug.Assert(false, "Unknown verification result");
409                      Log.Error(String.Format(
410                          CultureInfo.CurrentCulture,
411                          Resources.InternalError));
412                      return ManagedStrongName.ErrorCode;
413              }
414          }
415          
416          /// <summary>
417          ///     Generate a key (-k)
418          /// </summary>
419          /// <remarks>
420          ///     Expects one or two arguments, key size and file to write to
421          /// </remarks>
422          /// <returns>SuccessCode if the key generated properly, ErrorCode otherwise</returns>
423          public static int GenerateKey(string[] arguments)
424          {
425              Debug.Assert(arguments != null, "Null arguments");
426  
427              if(!(arguments.Length == 2 || arguments.Length == 3))
428              {
429                  Help(arguments);
430                  return ManagedStrongName.ErrorCode;
431              }
432  
433              Debug.Assert(arguments[0].EndsWith("k"));
434  
435              // parse the arguments
436              int keySize = 1024;
437              string fileName;
438  
439              if(arguments.Length == 3)
440              {
441                  // specified with both keysize and filename
442                  if(!Int32.TryParse(arguments[1], out keySize))
443                  {
444                      Log.Error(String.Format(
445                          CultureInfo.CurrentCulture,
446                          Resources.BadKeySize,
447                          arguments[1]));
448                      return ManagedStrongName.ErrorCode;
449                  }
450  
451                  fileName = arguments[2];
452              }
453              else
454              {
455                  // specified with only filename
456                  fileName = arguments[1];
457              }
458  
459              if(String.IsNullOrEmpty(fileName))
460              {
461                  Log.Error(String.Format(
462                      CultureInfo.CurrentCulture,
463                      Resources.BadFile,
464                      String.Empty));
465                  return ManagedStrongName.ErrorCode;
466              }
467  
468              if(keySize <= 0)
469                  Log.Error(String.Format(
470                      CultureInfo.CurrentCulture,
471                      Resources.BadKeySize,
472                      keySize));
473  
474              try
475              {
476                  byte[] key = Keys.GenerateKeyPair(keySize);
477                  KeyFile.WriteKeyFile(key, fileName);
478              }
479              catch(InvalidOperationException e)
480              {
481                  Log.Error(String.Format(
482                      CultureInfo.CurrentCulture,
483                      Resources.BadOperation,
484                      e.Message));
485                  return ManagedStrongName.ErrorCode;
486              }
487  
488              Log.Message(String.Format(
489                  CultureInfo.CurrentCulture,
490                  Resources.KeyWritten,
491                  fileName));
492              return ManagedStrongName.SuccessCode;
493          }
494  
495          /// <summary>
496          ///     Display usage information
497          /// </summary>
498          public static int Help(string[] arguments)
499          {
500              Log.Message(Resources.Usage);
501              Log.Message(Resources.OptionHeader);
502  
503              // sort the commands by option
504              Command[] sortedCommands = new Command[ManagedStrongName.CommandTable.Values.Count];
505              ManagedStrongName.CommandTable.Values.CopyTo(sortedCommands, 0);
506              Array.Sort(sortedCommands);
507  
508              // display them all
509              foreach(Command command in sortedCommands)
510              {
511                  Log.Message(String.Format(
512                      CultureInfo.CurrentCulture,
513                      Resources.OptionFormat,
514                      command.Option,
515                      command.Arguments));
516  
517                  foreach(string line in ManagedStrongName.FormatHelp(command.Help, 4))
518                      Log.Message(line);
519              }
520              
521              return ManagedStrongName.SuccessCode;
522          }
523  
524          /// <summary>
525          ///     Install a key into a key container (-i)
526          /// </summary>
527          /// <remarks>
528          ///     Expects two arguments, file name and key container name
529          /// </remarks>
530          /// <returns>SuccessCode if the key generated properly, ErrorCode otherwise</returns>
531          public static int InstallKeyPair(string[] arguments)
532          {
533              Debug.Assert(arguments != null, "Null arguments");
534              
535              if(arguments.Length != 3)
536              {
537                  Help(arguments);
538                  return ManagedStrongName.ErrorCode;
539              }
540  
541              Debug.Assert(arguments[0].EndsWith("i"));
542  
543              // parse the arguments
544              string keyFile = arguments[1];
545              string keyContainer = arguments[2];
546  
547              // do some basic validation on the parameters
548              if(String.IsNullOrEmpty(keyFile) || String.IsNullOrEmpty(keyFile.Trim()))
549              {
550                  Log.Error(String.Format(
551                      CultureInfo.CurrentCulture,
552                      Resources.BadFile,
553                      keyFile));
554                  return ManagedStrongName.ErrorCode;
555              }
556              
557              if(String.IsNullOrEmpty(keyContainer) || String.IsNullOrEmpty(keyContainer.Trim()))
558              {
559                  Log.Error(String.Format(
560                      CultureInfo.CurrentCulture,
561                      Resources.BadKeyContainer,
562                      keyContainer));
563                  return ManagedStrongName.ErrorCode;
564              }
565  
566              try
567              {
568                  // install it into the key container
569                  Keys.InstallKey(KeyFile.ReadKeyFile(keyFile), keyContainer);
570              }
571              catch(InvalidOperationException e)
572              {
573                  Log.Error(String.Format(
574                      CultureInfo.CurrentCulture,
575                      Resources.BadOperation,
576                      e.Message));
577                  return ManagedStrongName.ErrorCode;
578              }
579  
580              Log.Message(String.Format(
581                  CultureInfo.CurrentCulture,
582                  Resources.KeyPairInstalled,
583                  keyContainer));
584              return ManagedStrongName.SuccessCode;
585          }
586  
587          /// <summary>
588          ///     Check or set if key store operations should use the machine store (-m)
589          /// </summary>
590          /// <remarks>
591          ///     Expects zero or one arguments
592          /// </remarks>
593          /// <returns>SuccessCode if the command finished without error, ErrorCode otherwise</returns>
594          public static int MachineKeyStore(string[] arguments)
595          {
596              Debug.Assert(arguments != null, "Null arguments");
597              
598              if(arguments.Length != 1 && arguments.Length != 2)
599              {
600                  Help(arguments);
601                  return ManagedStrongName.ErrorCode;
602              }
603  
604              Debug.Assert(arguments[0].EndsWith("m"));
605  
606              if(arguments.Length == 2)
607              {
608                  try
609                  {
610                      // figure out if we're setting to on or off
611                      switch(arguments[1].Trim().ToLower(CultureInfo.InvariantCulture))
612                      {
613                          case "y":
614                              Keys.DefaultKeyStore = KeyStore.Machine;
615                              break;
616                          
617                          case "n":
618                              Keys.DefaultKeyStore = KeyStore.User;
619                              break;
620                          
621                          default:
622                              Help(arguments);
623                              return ManagedStrongName.ErrorCode;
624                      }
625                  }
626                  catch(UnauthorizedAccessException e)
627                  {
628                      Log.Error(String.Format(
629                          CultureInfo.CurrentCulture,
630                          Resources.BadOperation,
631                          e.Message));
632                      return ManagedStrongName.ErrorCode;
633                  }
634                  catch(InvalidOperationException e)
635                  {
636                      Log.Error(String.Format(
637                          CultureInfo.CurrentCulture,
638                          Resources.BadOperation,
639                          e.Message));
640                      return ManagedStrongName.ErrorCode;
641                  }
642              }
643  
644              try
645              {
646                  // finish by displaying the current state of the machine key store use
647                  switch(Keys.DefaultKeyStore)
648                  {
649                      case KeyStore.Machine:
650                          Log.Message(Resources.UsingMachineKeyContainers);
651                          break;
652  
653                      case KeyStore.User:
654                          Log.Message(Resources.UsingUserKeyContainers);
655                          break;
656  
657                      default:
658                          Log.Message(Resources.InternalError);
659                          return ManagedStrongName.ErrorCode;
660                  }
661                  
662              }
663              catch(InvalidOperationException e)
664              {
665                  Log.Error(String.Format(
666                      CultureInfo.CurrentCulture,
667                      Resources.BadOperation,
668                      e.Message));
669                  return ManagedStrongName.ErrorCode;
670              }
671              
672              return ManagedStrongName.SuccessCode;
673          }
674  
675          /// <summary>
676          ///     Verify an assembly (-v)
677          /// </summary>
678          /// <remarks>
679          ///     Expects one argument, the name of the assembly to verify
680          /// </remarks>
681          /// <returns>SuccessCode if the signature verifies, ErrorCode otherwise</returns>
682          public static int Verify(string[] arguments)
683          {
684              Debug.Assert(arguments != null, "Null arguments");
685  
686              if(arguments.Length != 2)
687              {
688                  Help(arguments);
689                  return ManagedStrongName.ErrorCode;
690              }
691  
692              Debug.Assert(arguments[0].EndsWith("v"));
693  
694              string assembly = arguments[1];
695              if(String.IsNullOrEmpty(assembly))
696              {
697                  Log.Error(String.Format(
698                      CultureInfo.CurrentCulture,
699                      Resources.BadFile,
700                      String.Empty));
701                  return ManagedStrongName.ErrorCode;
702              }
703              
704              switch(Signatures.VerifyAssembly(assembly, false))
705              {
706                  case VerificationResult.NotVerified:
707                      Log.Message(String.Format(
708                          CultureInfo.CurrentCulture,
709                          Resources.AssemblyNotVerified,
710                          assembly));
711                      return ManagedStrongName.ErrorCode;
712  
713                  case VerificationResult.DelaySigned:
714                      Log.Message(String.Format(
715                          CultureInfo.CurrentCulture,
716                          Resources.AssemblyDelaySigned,
717                          assembly));
718                      return ManagedStrongName.SuccessCode;
719  
720                  case VerificationResult.Verified:                  
721                      Log.Message(String.Format(
722                          CultureInfo.CurrentCulture,
723                          Resources.AssemblyVerified,
724                          assembly));
725                      return ManagedStrongName.SuccessCode;
726  
727                  default:
728                      Debug.Assert(false, "Unknown verification result");
729                      Log.Error(Resources.InternalError);
730                      return ManagedStrongName.ErrorCode;
731              }
732          }
733  
734          /// <summary>
735          ///     Display the public key token, and optionally the key itself, from a file
736          /// </summary>
737          /// <param name="publicKeyFile">
738          ///     File the public key is stored into
739          /// </param>
740          /// <param name="displayPublicKey">
741          ///     Display the key as well as the token
742          /// </param>
743          /// <returns>SuccessCode on success, ErrorCode on error</returns>
744          private static int DisplayPublicKeyTokenFromFile(string publicKeyFile, bool displayPublicKey)
745          {
746              Debug.Assert(!String.IsNullOrEmpty(publicKeyFile), "No file to work with");
747  
748              // get the token and key and write them out
749              try
750              {
751                  byte[] key = KeyFile.ReadKeyFile(publicKeyFile);
752                  byte[] token = Keys.CreateTokenFromPublicKey(KeyFile.ReadKeyFile(publicKeyFile));
753  
754                  if(displayPublicKey)
755                  {
756                      StringBuilder keyString = new StringBuilder(key.Length * 2);
757                      foreach(byte b in key)
758                          keyString.Append(b.ToString("x2"));
759  
760                      Log.Message(String.Format(
761                          CultureInfo.CurrentCulture,
762                          Resources.PublicKey,
763                          keyString.ToString()));
764                  }
765                  
766                  StringBuilder tokenString = new StringBuilder(token.Length * 2);
767                  foreach(byte b in token)
768                      tokenString.Append(b.ToString("x2"));
769                  
770                  Log.Message(String.Format(
771                      CultureInfo.CurrentCulture,
772                      Resources.PublicKeyToken,
773                      tokenString.ToString()));
774              }
775              catch(InvalidOperationException e)
776              {
777                  Log.Error(String.Format(
778                      CultureInfo.CurrentCulture,
779                      Resources.BadOperation,
780                      e.Message));
781                  return ManagedStrongName.ErrorCode;
782              }
783  
784              return ManagedStrongName.SuccessCode;  
785          }
786  
787          /// <summary>
788          ///     Display the public key token, and optionally the key itself, from a file
789          /// </summary>
790          /// <param name="assembly">
791          ///     File the public key is stored into
792          /// </param>
793          /// <param name="displayPublicKey">
794          ///     Display the key as well as the token
795          /// </param>
796          /// <returns>SuccessCode on success, ErrorCode on error</returns>
797          private static int DisplayPublicKeyTokenFromAssembly(string assembly, bool displayPublicKey)
798          {
799              Debug.Assert(!String.IsNullOrEmpty(assembly), "No assembly to work with");
800  
801              // write out the public key if requested
802              if(displayPublicKey)
803              {
804                  try
805                  {
806                      byte[] key = Keys.ExtractPublicKeyFromAssembly(assembly);
807                      StringBuilder keyString = new StringBuilder(key.Length * 2);
808                      foreach(byte b in key)
809                          keyString.Append(b.ToString("x2"));
810  
811                      Log.Message(String.Format(
812                          CultureInfo.CurrentCulture,
813                          Resources.PublicKey,
814                          keyString.ToString()));                    
815                  }
816                  catch(InvalidOperationException e)
817                  {
818                      Log.Error(String.Format(
819                          CultureInfo.CurrentCulture,
820                          Resources.BadOperation,
821                          e.Message));
822                      return ManagedStrongName.ErrorCode;
823                  }            
824              }
825  
826              // now write out the token
827              try
828              {
829                  byte[] token = Keys.CreateTokenFromAssembly(assembly);
830                  StringBuilder tokenString = new StringBuilder(token.Length * 2);
831                  foreach(byte b in token)
832                      tokenString.Append(b.ToString("x2"));
833                  
834                  Log.Message(String.Format(
835                      CultureInfo.CurrentCulture,
836                      Resources.PublicKeyToken,
837                      tokenString.ToString()));
838                  
839              }
840              catch(InvalidOperationException e)
841              {
842                  Log.Error(String.Format(
843                      CultureInfo.CurrentCulture,
844                      Resources.BadOperation,
845                      e.Message));
846                  return ManagedStrongName.ErrorCode;                
847              }
848  
849              return ManagedStrongName.SuccessCode;
850          }
851      }
852  }