2 * monosn.c: Mono String Name Utility
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2002 Ximian, Inc.
10 #include <mono/metadata/class.h>
11 #include <mono/metadata/debug-helpers.h>
12 #include <mono/metadata/tokentype.h>
13 #include <mono/metadata/appdomain.h>
14 #include <mono/metadata/assembly.h>
15 #include "mono/utils/mono-digest.h"
21 #define RSA1_MAGIC 0x32415351
22 #define RSA2_MAGIC 0x32415352
23 #define PRIVKEY_MAGIC 0x00000207
24 #define PUBKEY_MAGIC 0x00008004
36 guchar modulus [MONO_ZERO_LEN_ARRAY];
40 print_data (const char *data, int len)
43 for (i = 0; i < len; ++i) {
46 printf ("%02x", data [i] & 0xff);
52 show_token (const char *file, int is_assembly, int show_pubkey) {
57 if (!g_file_get_contents (file, &pubkey, &len, NULL)) {
58 printf ("Cannot load file: %s\n", file);
61 mono_digest_get_public_token (token, pubkey, len);
63 printf ("Public key is\n");
64 print_data (pubkey, len);
72 mono_metadata_init ();
74 mono_assemblies_init ();
77 image = mono_image_open (file, NULL);
79 printf ("Cannot open image file: %s\n", file);
82 pubkey = mono_image_get_public_key (image, &len);
84 printf ("%s does not represent a strongly named assembly\n", mono_image_get_name(image));
85 mono_image_close (image);
89 printf ("Public key is\n");
90 print_data (pubkey, len);
92 mono_digest_get_public_token (token, pubkey, len);
93 mono_image_close (image);
95 printf ("Public key token is ");
96 print_data (token, 8);
101 extract_data_to_file (int pubk, const char *assembly, const char *outfile) {
107 image = mono_image_open (assembly, NULL);
109 printf ("Cannot open image file: %s\n", assembly);
113 pubkey = mono_image_get_public_key (image, &len);
115 pubkey = mono_image_get_strong_name (image, &len);
117 printf ("%s does not represent a strongly named assembly\n", mono_image_get_name(image));
118 mono_image_close (image);
121 if (!(file = fopen (outfile, "wb"))) {
122 printf ("Cannot open output file: %s\n", outfile);
125 fwrite (pubkey, len, 1, file);
127 mono_image_close (image);
131 const static guint8 asciitable [128] = {
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
139 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
140 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
141 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
142 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
143 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
144 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
145 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
146 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
147 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
148 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
149 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
150 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
151 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
152 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
156 /* data is changed in place */
158 pem_decode (guchar *data, int len, int *rlen) {
160 int b64len, i, rem = 0, full;
161 int b0, b1, b2, b3, offset, dlen;
163 p = strstr (data, "-----BEGIN");
164 s = strstr (data, "\n-----END");
167 while (*p != '\n') p++;
171 if (isalnum (*p) || *p == '+' || *p == '=' || *p == '/') {
181 if (data [b64len - 1] == '=') {
185 if (data [b64len - 2] == '=')
189 for (i = 0; i < full; ++i) {
190 b0 = asciitable [data [offset++]];
191 b1 = asciitable [data [offset++]];
192 b2 = asciitable [data [offset++]];
193 b3 = asciitable [data [offset++]];
195 *p++ = (b0 << 2) | (b1 >> 4);
196 *p++ = (b1 << 4) | (b2 >> 2);
197 *p++ = (b2 << 6) | b3;
202 b0 = asciitable [data [offset++]];
203 b1 = asciitable [data [offset++]];
204 b2 = asciitable [data [offset++]];
206 *p++ = (b0 << 2) | (b1 >> 4);
207 *p++ = (b1 << 4) | (b2 >> 2);
211 b0 = asciitable [data [offset++]];
212 b1 = asciitable [data [offset++]];
214 *p++ = (b0 << 2) | (b1 >> 4);
233 der_get_next (guchar *data, int dlen, int offset, int *len, guchar **rdata)
237 if (offset + 1 >= dlen)
240 type = data [offset++] & 0x1f;
241 if (data [offset] == 0x80) /* not supported */
244 if (data [offset] & 0x80) {
245 val = data [offset++] & 0x7f;
246 for (i = 0; i < val; ++i) {
247 l = (l << 8) | data [offset++];
253 *rdata = data + offset;
258 dump_asn1 (guchar *key, int len) {
259 int type, offset, elen;
263 while ((type = der_get_next (key, len, offset, &elen, &edata)) >= 0) {
266 g_print ("seq (%d) at %d\n", elen, offset);
267 dump_asn1 (edata, elen);
268 offset = elen + edata - key;
271 g_print ("bits (%d) at %p + %d\n", elen, edata, offset);
272 dump_asn1 (edata + 1, elen);
273 offset = 1 + elen + edata - key;
276 g_print ("int (%d) at %d\n", elen, offset);
277 offset = elen + edata - key;
280 g_print ("null (%d) at %d\n", elen, offset);
281 offset = elen + edata - key;
284 g_print ("objid (%d) at %d\n", elen, offset);
285 offset = elen + edata - key;
294 get_der_int (guchar *data, int len)
298 for (i = 0; i < len; ++i)
299 val = (val << 8) | data [i];
304 mem_reverse (guchar *p, int len) {
307 for (i = 0; i < len/2; ++i) {
309 p [i] = p [len - i - 1];
315 convert_der_key (guchar *key, int len, guchar **ret, int *retlen)
317 int type, offset, val, elen;
321 type = der_get_next (key, len, offset, &elen, &edata);
322 if (type != DER_SEQUENCE)
326 type = der_get_next (key, len, offset, &elen, &edata);
327 if (type == DER_INTEGER) {
332 /* a private RSA key */
333 val = get_der_int (edata, elen);
336 offset = elen + edata - key;
338 type = der_get_next (key, len, offset, &elen, &edata);
339 if (type != DER_INTEGER)
341 offset = elen + edata - key;
342 if ((elen & 1) && *edata == 0) {
346 r = g_new0 (guchar, elen*4 + elen/2 + 20);
347 r [0] = 0x7; r [1] = 0x2; r [5] = 0x24;
348 r [8] = 0x52; r [9] = 0x53; r [10] = 0x41; r [11] = 0x32;
349 *(guint32*)(r + 12) = elen * 8;
350 memcpy (r + 20, edata, elen);
351 mem_reverse (r + 20, elen);
354 type = der_get_next (key, len, offset, &elen, &edata);
355 if (type != DER_INTEGER)
357 offset = elen + edata - key;
358 val = get_der_int (edata, elen);
359 *(guint32*)(r + 16) = val;
360 for (i = 0; i < 6; i++) {
361 type = der_get_next (key, len, offset, &elen, &edata);
362 if (type != DER_INTEGER)
364 offset = elen + edata - key;
365 if ((elen & 1) && *edata == 0) {
371 g_print ("len: %d\n", elen);
374 g_print ("prime1 at %d (%d)\n", p-r, lengths [1]);
375 memcpy (p, ints [1], lengths [1]);
376 mem_reverse (p, lengths [1]);
379 g_print ("prime2 at %d (%d)\n", p-r, lengths [2]);
380 memcpy (p, ints [2], lengths [2]);
381 mem_reverse (p, lengths [2]);
384 g_print ("exp1 at %d (%d)\n", p-r, lengths [3]);
385 memcpy (p, ints [3], lengths [3]);
386 mem_reverse (p, lengths [3]);
389 g_print ("exp2 at %d (%d)\n", p-r, lengths [4]);
390 memcpy (p, ints [4], lengths [4]);
391 mem_reverse (p, lengths [4]);
394 g_print ("coeff at %d (%d)\n", p-r, lengths [5]);
395 memcpy (p, ints [5], lengths [5]);
396 mem_reverse (p, lengths [5]);
398 /* private exponent */
399 g_print ("prive at %d (%d)\n", p-r, lengths [0]);
400 memcpy (p, ints [0], lengths [0]);
401 mem_reverse (p, lengths [0]);
411 convert_format (const char *from, const char *outfile) {
412 guchar *key, *bindata, *keyout;
414 int binlen, ret, lenout;
417 if (!g_file_get_contents (from, (gchar**) &key, &len, NULL)) {
418 printf ("Cannot load file: %s\n", from);
422 if (*key == 0 || *key == 0x24) {
424 printf ("Cannot convert to pem format yet\n");
427 bindata = pem_decode (key, len, &binlen);
428 if (!(file = fopen (outfile, "wb"))) {
430 printf ("Cannot open output file: %s\n", outfile);
433 dump_asn1 (bindata, binlen);
434 ret = convert_der_key (bindata, binlen, &keyout, &lenout);
436 fwrite (keyout, lenout, 1, file);
439 printf ("Cannot convert key\n");
447 get_digest (const char *from, const char *outfile)
452 guint32 snpos, snsize;
455 MonoSHA1Context sha1;
457 image = mono_image_open (from, NULL);
459 printf ("Cannot open image file: %s\n", from);
462 snpos = mono_image_strong_name_position (image, &snsize);
464 /*printf ("%s does not represent a strongly named assembly\n", from);
465 mono_image_close (image);
470 if (!g_file_get_contents (from, (gchar**) &ass, &len, NULL)) {
471 printf ("Cannot load file: %s\n", from);
472 mono_image_close (image);
476 * FIXME: we may need to set the STRONGNAMESIGNED flag in the cli header
477 * before taking the sha1 digest of the image.
479 mono_sha1_init (&sha1);
480 mono_sha1_update (&sha1, ass, snpos);
481 mono_sha1_update (&sha1, ass + snpos + snsize, len - snsize - snpos);
482 mono_sha1_final (&sha1, digest);
484 mono_image_close (image);
486 if (!(file = fopen (outfile, "wb"))) {
487 printf ("Cannot open output file: %s\n", outfile);
490 fwrite (digest, 20, 1, file);
497 printf ("monosn: Mono Strong Name Utility\nUsage: monosn option [arguments]\n");
498 printf ("Available options:\n");
499 printf ("\t-C keyin keyout Convert key file format from PEM to cryptoAPI (or the reverse).\n");
500 printf ("\t-e assembly file Extract the public key from assembly to file.\n");
501 printf ("\t-E assembly file Extract the strong name from assembly to file.\n");
502 printf ("\t-r assembly file Extract the sha1 digest from assembly to file.\n");
503 printf ("\t-t[p] file Display the public key token from file.\n");
504 printf ("\t-T[p] assembly Display the public key token from assembly.\n");
509 main (int argc, char *argv[]) {
512 if (argc < 2 || argv [1] [0] != '-')
520 return convert_format (argv [2], argv [3]);
524 return extract_data_to_file (1, argv [2], argv [3]);
528 return extract_data_to_file (0, argv [2], argv [3]);
536 return get_digest (argv [2], argv [3]);
540 return show_token (argv [2], 0, argv [1] [2] == 'p');
544 return show_token (argv [2], 1, argv [1] [2] == 'p');