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);
71 image = mono_image_open (file, NULL);
73 printf ("Cannot open image file: %s\n", file);
76 pubkey = mono_image_get_public_key (image, &len);
78 printf ("%s does not represent a strongly named assembly\n", image->name);
79 mono_image_close (image);
83 printf ("Public key is\n");
84 print_data (pubkey, len);
86 mono_digest_get_public_token (token, pubkey, len);
87 mono_image_close (image);
89 printf ("Public key token is ");
90 print_data (token, 8);
95 extract_data_to_file (int pubk, const char *assembly, const char *outfile) {
101 image = mono_image_open (assembly, NULL);
103 printf ("Cannot open image file: %s\n", assembly);
107 pubkey = mono_image_get_public_key (image, &len);
109 pubkey = mono_image_get_strong_name (image, &len);
111 printf ("%s does not represent a strongly named assembly\n", image->name);
112 mono_image_close (image);
115 if (!(file = fopen (outfile, "wb"))) {
116 printf ("Cannot open output file: %s\n", outfile);
119 fwrite (pubkey, len, 1, file);
121 mono_image_close (image);
125 const static guint8 asciitable [128] = {
126 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
134 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
135 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
136 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
137 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
138 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
139 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
140 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
141 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
142 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
143 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
144 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
145 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
146 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
150 /* data is changed in place */
152 pem_decode (guchar *data, int len, int *rlen) {
154 int b64len, i, rem = 0, full;
155 int b0, b1, b2, b3, offset, dlen;
157 p = strstr (data, "-----BEGIN");
158 s = strstr (data, "\n-----END");
161 while (*p != '\n') p++;
165 if (isalnum (*p) || *p == '+' || *p == '=' || *p == '/') {
175 if (data [b64len - 1] == '=') {
179 if (data [b64len - 2] == '=')
183 for (i = 0; i < full; ++i) {
184 b0 = asciitable [data [offset++]];
185 b1 = asciitable [data [offset++]];
186 b2 = asciitable [data [offset++]];
187 b3 = asciitable [data [offset++]];
189 *p++ = (b0 << 2) | (b1 >> 4);
190 *p++ = (b1 << 4) | (b2 >> 2);
191 *p++ = (b2 << 6) | b3;
196 b0 = asciitable [data [offset++]];
197 b1 = asciitable [data [offset++]];
198 b2 = asciitable [data [offset++]];
200 *p++ = (b0 << 2) | (b1 >> 4);
201 *p++ = (b1 << 4) | (b2 >> 2);
205 b0 = asciitable [data [offset++]];
206 b1 = asciitable [data [offset++]];
208 *p++ = (b0 << 2) | (b1 >> 4);
227 der_get_next (guchar *data, int dlen, int offset, int *len, guchar **rdata)
231 if (offset + 1 >= dlen)
234 type = data [offset++] & 0x1f;
235 if (data [offset] == 0x80) /* not supported */
238 if (data [offset] & 0x80) {
239 val = data [offset++] & 0x7f;
240 for (i = 0; i < val; ++i) {
241 l = (l << 8) | data [offset++];
247 *rdata = data + offset;
252 dump_asn1 (guchar *key, int len) {
253 int type, offset, elen;
257 while ((type = der_get_next (key, len, offset, &elen, &edata)) >= 0) {
260 g_print ("seq (%d) at %d\n", elen, offset);
261 dump_asn1 (edata, elen);
262 offset = elen + edata - key;
265 g_print ("bits (%d) at %p + %d\n", elen, edata, offset);
266 dump_asn1 (edata + 1, elen);
267 offset = 1 + elen + edata - key;
270 g_print ("int (%d) at %d\n", elen, offset);
271 offset = elen + edata - key;
274 g_print ("null (%d) at %d\n", elen, offset);
275 offset = elen + edata - key;
278 g_print ("objid (%d) at %d\n", elen, offset);
279 offset = elen + edata - key;
288 get_der_int (guchar *data, int len)
292 for (i = 0; i < len; ++i)
293 val = (val << 8) | data [i];
298 mem_reverse (guchar *p, int len) {
301 for (i = 0; i < len/2; ++i) {
303 p [i] = p [len - i - 1];
309 convert_der_key (guchar *key, int len, guchar **ret, int *retlen)
311 int type, offset, val, elen;
315 type = der_get_next (key, len, offset, &elen, &edata);
316 if (type != DER_SEQUENCE)
320 type = der_get_next (key, len, offset, &elen, &edata);
321 if (type == DER_INTEGER) {
326 /* a private RSA key */
327 val = get_der_int (edata, elen);
330 offset = elen + edata - key;
332 type = der_get_next (key, len, offset, &elen, &edata);
333 if (type != DER_INTEGER)
335 offset = elen + edata - key;
336 if ((elen & 1) && *edata == 0) {
340 r = g_new0 (guchar, elen*4 + elen/2 + 20);
341 r [0] = 0x7; r [1] = 0x2; r [5] = 0x24;
342 r [8] = 0x52; r [9] = 0x53; r [10] = 0x41; r [11] = 0x32;
343 *(guint32*)(r + 12) = elen * 8;
344 memcpy (r + 20, edata, elen);
345 mem_reverse (r + 20, elen);
348 type = der_get_next (key, len, offset, &elen, &edata);
349 if (type != DER_INTEGER)
351 offset = elen + edata - key;
352 val = get_der_int (edata, elen);
353 *(guint32*)(r + 16) = val;
354 for (i = 0; i < 6; i++) {
355 type = der_get_next (key, len, offset, &elen, &edata);
356 if (type != DER_INTEGER)
358 offset = elen + edata - key;
359 if ((elen & 1) && *edata == 0) {
365 g_print ("len: %d\n", elen);
368 g_print ("prime1 at %d (%d)\n", p-r, lengths [1]);
369 memcpy (p, ints [1], lengths [1]);
370 mem_reverse (p, lengths [1]);
373 g_print ("prime2 at %d (%d)\n", p-r, lengths [2]);
374 memcpy (p, ints [2], lengths [2]);
375 mem_reverse (p, lengths [2]);
378 g_print ("exp1 at %d (%d)\n", p-r, lengths [3]);
379 memcpy (p, ints [3], lengths [3]);
380 mem_reverse (p, lengths [3]);
383 g_print ("exp2 at %d (%d)\n", p-r, lengths [4]);
384 memcpy (p, ints [4], lengths [4]);
385 mem_reverse (p, lengths [4]);
388 g_print ("coeff at %d (%d)\n", p-r, lengths [5]);
389 memcpy (p, ints [5], lengths [5]);
390 mem_reverse (p, lengths [5]);
392 /* private exponent */
393 g_print ("prive at %d (%d)\n", p-r, lengths [0]);
394 memcpy (p, ints [0], lengths [0]);
395 mem_reverse (p, lengths [0]);
405 convert_format (const char *from, const char *outfile) {
406 guchar *key, *bindata, *keyout;
408 int binlen, ret, lenout;
411 if (!g_file_get_contents (from, (gchar**) &key, &len, NULL)) {
412 printf ("Cannot load file: %s\n", from);
416 if (*key == 0 || *key == 0x24) {
418 printf ("Cannot convert to pem format yet\n");
421 bindata = pem_decode (key, len, &binlen);
422 if (!(file = fopen (outfile, "wb"))) {
424 printf ("Cannot open output file: %s\n", outfile);
427 dump_asn1 (bindata, binlen);
428 ret = convert_der_key (bindata, binlen, &keyout, &lenout);
430 fwrite (keyout, lenout, 1, file);
433 printf ("Cannot convert key\n");
441 get_digest (const char *from, const char *outfile)
446 guint32 snpos, snsize;
449 MonoSHA1Context sha1;
451 image = mono_image_open (from, NULL);
453 printf ("Cannot open image file: %s\n", from);
456 snpos = mono_image_strong_name_position (image, &snsize);
458 /*printf ("%s does not represent a strongly named assembly\n", from);
459 mono_image_close (image);
464 if (!g_file_get_contents (from, (gchar**) &ass, &len, NULL)) {
465 printf ("Cannot load file: %s\n", from);
466 mono_image_close (image);
470 * FIXME: we may need to set the STRONGNAMESIGNED flag in the cli header
471 * before taking the sha1 digest of the image.
473 mono_sha1_init (&sha1);
474 mono_sha1_update (&sha1, ass, snpos);
475 mono_sha1_update (&sha1, ass + snpos + snsize, len - snsize - snpos);
476 mono_sha1_final (&sha1, digest);
478 mono_image_close (image);
480 if (!(file = fopen (outfile, "wb"))) {
481 printf ("Cannot open output file: %s\n", outfile);
484 fwrite (digest, 20, 1, file);
491 printf ("monosn: Mono Strong Name Utility\nUsage: monosn option [arguments]\n");
492 printf ("Available options:\n");
493 printf ("\t-C keyin keyout Convert key file format from PEM to cryptoAPI (or the reverse).\n");
494 printf ("\t-e assembly file Extract the public key from assembly to file.\n");
495 printf ("\t-E assembly file Extract the strong name from assembly to file.\n");
496 printf ("\t-r assembly file Extract the sha1 digest from assembly to file.\n");
497 printf ("\t-t[p] file Display the public key token from file.\n");
498 printf ("\t-T[p] assembly Display the public key token from assembly.\n");
503 main (int argc, char *argv[]) {
506 if (argc < 2 || argv [1] [0] != '-')
514 return convert_format (argv [2], argv [3]);
518 return extract_data_to_file (1, argv [2], argv [3]);
522 return extract_data_to_file (0, argv [2], argv [3]);
530 return get_digest (argv [2], argv [3]);
534 return show_token (argv [2], 0, argv [1] [2] == 'p');
538 return show_token (argv [2], 1, argv [1] [2] == 'p');