signcode.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. //
  2. // SignCode.cs: secutil clone tool
  3. //
  4. // Author:
  5. // Sebastien Pouliot <[email protected]>
  6. //
  7. // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
  8. // (C) 2004 Novell (http://www.novell.com)
  9. //
  10. using System;
  11. using System.Reflection;
  12. using System.Security.Cryptography;
  13. using System.Security.Cryptography.X509Certificates;
  14. using System.Text;
  15. using System.Threading;
  16. using Mono.Security.Authenticode;
  17. [assembly: AssemblyTitle("Mono SignCode")]
  18. [assembly: AssemblyDescription("Sign assemblies and PE files using Authenticode(tm).")]
  19. namespace Mono.Tools {
  20. class SignCode {
  21. static private void Header ()
  22. {
  23. Assembly a = Assembly.GetExecutingAssembly ();
  24. AssemblyName an = a.GetName ();
  25. object [] att = a.GetCustomAttributes (typeof (AssemblyTitleAttribute), false);
  26. string title = ((att.Length > 0) ? ((AssemblyTitleAttribute) att [0]).Title : "Mono SignCode");
  27. att = a.GetCustomAttributes (typeof (AssemblyCopyrightAttribute), false);
  28. string copyright = ((att.Length > 0) ? ((AssemblyCopyrightAttribute) att [0]).Copyright : "");
  29. Console.WriteLine ("{0} {1}", title, an.Version.ToString ());
  30. Console.WriteLine ("{0}{1}", copyright, Environment.NewLine);
  31. }
  32. static private void Help ()
  33. {
  34. Console.WriteLine ("Usage: signcode [options] filename{0}", Environment.NewLine);
  35. Console.WriteLine ("\t-spc spc\tSoftware Publisher Certificate file");
  36. Console.WriteLine ("\t-v pvk\tPrivate Key file");
  37. Console.WriteLine ("\t-a md5 | sha1\tHash Algorithm (default: MD5)");
  38. Console.WriteLine ("\t-$ indivisual | commercial\tSignature type");
  39. Console.WriteLine ("\t-n\tDescription for the signed file");
  40. Console.WriteLine ("\t-i\tURL for the signed file");
  41. Console.WriteLine ("Timestamp options");
  42. Console.WriteLine ("\t-t url\tTimestamp service http URL");
  43. Console.WriteLine ("\t-tr #\tNumber of retries for timestamp");
  44. Console.WriteLine ("\t-tw #\tDelay between retries");
  45. Console.WriteLine ("\t-x\tOnly timestamp (no signature)");
  46. Console.WriteLine ("CSP options");
  47. Console.WriteLine ("\t-k name\tKey Container Name");
  48. Console.WriteLine ("\t-p name\tProvider Name");
  49. Console.WriteLine ("\t-y #\tProvider Type");
  50. Console.WriteLine ("\t-ky [signature|exchange|#]\tKey Type");
  51. Console.WriteLine ("\t-r [localMachine|currentUser]\tKey Location");
  52. }
  53. [STAThread]
  54. static int Main(string[] args)
  55. {
  56. Header ();
  57. if (args.Length < 1) {
  58. Help ();
  59. return 1;
  60. }
  61. CspParameters csp = new CspParameters ();
  62. string pvkFilename = null;
  63. string spcFilename = null;
  64. int timestampRetry = 0;
  65. int timestampDelay = 0;
  66. bool sign = true;
  67. // to be signed
  68. string tbsFilename = args [args.Length - 1];
  69. AuthenticodeFormatter af = new AuthenticodeFormatter ();
  70. int i = 0;
  71. while (i < args.Length) {
  72. switch (args[i++]) {
  73. case "-spc":
  74. spcFilename = args [i++];
  75. break;
  76. case "-v":
  77. pvkFilename = args [i++];
  78. break;
  79. case "-a":
  80. af.Hash = args [i++];
  81. break;
  82. case "-$":
  83. string auth = args [i++].ToLower ();
  84. switch (auth) {
  85. case "individual":
  86. af.Authority = Authority.Commercial;
  87. break;
  88. case "commercial":
  89. af.Authority = Authority.Individual;
  90. break;
  91. default:
  92. Console.WriteLine ("Unknown authority {0}", auth);
  93. return 1;
  94. }
  95. break;
  96. case "-i":
  97. af.Description = args [i++];
  98. break;
  99. case "-n":
  100. af.Url = new Uri (args [i++]);
  101. break;
  102. // timestamp options
  103. case "-t":
  104. af.TimestampUrl = new Uri (args [i++]);
  105. break;
  106. case "-tr":
  107. timestampRetry = Convert.ToInt32 (args [i++]);
  108. break;
  109. case "-tw":
  110. timestampDelay = Convert.ToInt32 (args [i++]) * 1000;
  111. break;
  112. case "-x":
  113. // only timestamp
  114. sign = false;
  115. break;
  116. // CSP provider options
  117. case "-k":
  118. csp.KeyContainerName = args [i++];
  119. break;
  120. case "-p":
  121. csp.ProviderName = args [i++];
  122. break;
  123. case "-y":
  124. csp.ProviderType = Convert.ToInt32 (args [i++]);
  125. break;
  126. case "-ky":
  127. string key = args [i++];
  128. switch (key) {
  129. case "signature":
  130. csp.KeyNumber = 0;
  131. break;
  132. case "exchange":
  133. csp.KeyNumber = 0;
  134. break;
  135. default:
  136. csp.KeyNumber = Convert.ToInt32 (key);
  137. break;
  138. }
  139. break;
  140. case "-r":
  141. string location = args [i++];
  142. switch (location) {
  143. case "localMachine":
  144. csp.Flags = CspProviderFlags.UseMachineKeyStore;
  145. break;
  146. case "currentUser":
  147. csp.Flags = CspProviderFlags.UseDefaultKeyContainer;
  148. break;
  149. default:
  150. Console.WriteLine ("Unknown location {0}", location);
  151. return 1;
  152. }
  153. break;
  154. // unsupported options
  155. case "-j":
  156. case "-jp":
  157. Console.WriteLine ("Unsupported option {0}", args[i-1]);
  158. return 1;
  159. }
  160. }
  161. if (sign) {
  162. RSACryptoServiceProvider rsa = new RSACryptoServiceProvider (csp);
  163. if (pvkFilename != null) {
  164. PrivateKey pvk = PrivateKey.CreateFromFile (pvkFilename);
  165. if (pvk.Encrypted) {
  166. Console.WriteLine ("Enter password for {0}: ", pvkFilename);
  167. string pvkPassword = Console.ReadLine ();
  168. pvk = PrivateKey.CreateFromFile (pvkFilename, pvkPassword);
  169. }
  170. if (pvk.RSA != null) {
  171. rsa.ImportParameters (pvk.RSA.ExportParameters (true));
  172. }
  173. else {
  174. Console.WriteLine ("Invalid password for {0}", pvkFilename);
  175. return 1;
  176. }
  177. }
  178. SoftwarePublisherCertificate spc = null;
  179. if (spcFilename != null) {
  180. spc = SoftwarePublisherCertificate.CreateFromFile (spcFilename);
  181. af.Certificates.AddRange (spc.Certificates);
  182. // TODO CRL
  183. }
  184. af.RSA = rsa;
  185. af.Sign (tbsFilename);
  186. }
  187. /* TODO
  188. if (af.TimestampURL != null) {
  189. for (int j=0; j < timestampRetry + 1; j++) {
  190. if (!af.Timestamp (tbsFilename)) {
  191. Thread.Sleep (timestampDelay);
  192. continue;
  193. }
  194. break;
  195. }
  196. }*/
  197. return 0;
  198. }
  199. }
  200. }