2 * monosn.c: Mono String Name Utility
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 #include <mono/metadata/class.h>
12 #include <mono/metadata/debug-helpers.h>
13 #include <mono/metadata/tokentype.h>
14 #include <mono/metadata/appdomain.h>
15 #include <mono/metadata/assembly.h>
16 #include "mono/utils/mono-digest.h"
22 #define RSA1_MAGIC 0x32415351
23 #define RSA2_MAGIC 0x32415352
24 #define PRIVKEY_MAGIC 0x00000207
25 #define PUBKEY_MAGIC 0x00008004
37 guchar modulus
[MONO_ZERO_LEN_ARRAY
];
41 print_data (const char *data
, int len
)
44 for (i
= 0; i
< len
; ++i
) {
47 printf ("%02x", data
[i
] & 0xff);
53 show_token (const char *file
, int is_assembly
, int show_pubkey
) {
58 if (!g_file_get_contents (file
, &pubkey
, &len
, NULL
)) {
59 printf ("Cannot load file: %s\n", file
);
62 mono_digest_get_public_token (token
, pubkey
, len
);
64 printf ("Public key is\n");
65 print_data (pubkey
, len
);
73 mono_metadata_init ();
75 mono_assemblies_init ();
78 image
= mono_image_open (file
, NULL
);
80 printf ("Cannot open image file: %s\n", file
);
83 pubkey
= mono_image_get_public_key (image
, &len
);
85 printf ("%s does not represent a strongly named assembly\n", mono_image_get_name(image
));
86 mono_image_close (image
);
90 printf ("Public key is\n");
91 print_data (pubkey
, len
);
93 mono_digest_get_public_token (token
, pubkey
, len
);
94 mono_image_close (image
);
96 printf ("Public key token is ");
97 print_data (token
, 8);
102 extract_data_to_file (int pubk
, const char *assembly
, const char *outfile
) {
108 image
= mono_image_open (assembly
, NULL
);
110 printf ("Cannot open image file: %s\n", assembly
);
114 pubkey
= mono_image_get_public_key (image
, &len
);
116 pubkey
= mono_image_get_strong_name (image
, &len
);
118 printf ("%s does not represent a strongly named assembly\n", mono_image_get_name(image
));
119 mono_image_close (image
);
122 if (!(file
= fopen (outfile
, "wb"))) {
123 printf ("Cannot open output file: %s\n", outfile
);
126 fwrite (pubkey
, len
, 1, file
);
128 mono_image_close (image
);
132 const static guint8 asciitable
[128] = {
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, 0xff, 0xff, 0xff, 0xff, 0xff,
140 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
141 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
142 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
143 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
144 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
145 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
146 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
147 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
148 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
149 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
150 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
151 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
152 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
153 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
157 /* data is changed in place */
159 pem_decode (guchar
*data
, int len
, int *rlen
) {
161 int b64len
, i
, rem
= 0, full
;
162 int b0
, b1
, b2
, b3
, offset
, dlen
;
164 p
= strstr (data
, "-----BEGIN");
165 s
= strstr (data
, "\n-----END");
168 while (*p
!= '\n') p
++;
172 if (isalnum (*p
) || *p
== '+' || *p
== '=' || *p
== '/') {
182 if (data
[b64len
- 1] == '=') {
186 if (data
[b64len
- 2] == '=')
190 for (i
= 0; i
< full
; ++i
) {
191 b0
= asciitable
[data
[offset
++]];
192 b1
= asciitable
[data
[offset
++]];
193 b2
= asciitable
[data
[offset
++]];
194 b3
= asciitable
[data
[offset
++]];
196 *p
++ = (b0
<< 2) | (b1
>> 4);
197 *p
++ = (b1
<< 4) | (b2
>> 2);
198 *p
++ = (b2
<< 6) | b3
;
203 b0
= asciitable
[data
[offset
++]];
204 b1
= asciitable
[data
[offset
++]];
205 b2
= asciitable
[data
[offset
++]];
207 *p
++ = (b0
<< 2) | (b1
>> 4);
208 *p
++ = (b1
<< 4) | (b2
>> 2);
212 b0
= asciitable
[data
[offset
++]];
213 b1
= asciitable
[data
[offset
++]];
215 *p
++ = (b0
<< 2) | (b1
>> 4);
234 der_get_next (guchar
*data
, int dlen
, int offset
, int *len
, guchar
**rdata
)
238 if (offset
+ 1 >= dlen
)
241 type
= data
[offset
++] & 0x1f;
242 if (data
[offset
] == 0x80) /* not supported */
245 if (data
[offset
] & 0x80) {
246 val
= data
[offset
++] & 0x7f;
247 for (i
= 0; i
< val
; ++i
) {
248 l
= (l
<< 8) | data
[offset
++];
254 *rdata
= data
+ offset
;
259 dump_asn1 (guchar
*key
, int len
) {
260 int type
, offset
, elen
;
264 while ((type
= der_get_next (key
, len
, offset
, &elen
, &edata
)) >= 0) {
267 g_print ("seq (%d) at %d\n", elen
, offset
);
268 dump_asn1 (edata
, elen
);
269 offset
= elen
+ edata
- key
;
272 g_print ("bits (%d) at %p + %d\n", elen
, edata
, offset
);
273 dump_asn1 (edata
+ 1, elen
);
274 offset
= 1 + elen
+ edata
- key
;
277 g_print ("int (%d) at %d\n", elen
, offset
);
278 offset
= elen
+ edata
- key
;
281 g_print ("null (%d) at %d\n", elen
, offset
);
282 offset
= elen
+ edata
- key
;
285 g_print ("objid (%d) at %d\n", elen
, offset
);
286 offset
= elen
+ edata
- key
;
295 get_der_int (guchar
*data
, int len
)
299 for (i
= 0; i
< len
; ++i
)
300 val
= (val
<< 8) | data
[i
];
305 mem_reverse (guchar
*p
, int len
) {
308 for (i
= 0; i
< len
/2; ++i
) {
310 p
[i
] = p
[len
- i
- 1];
316 convert_der_key (guchar
*key
, int len
, guchar
**ret
, int *retlen
)
318 int type
, offset
, val
, elen
;
322 type
= der_get_next (key
, len
, offset
, &elen
, &edata
);
323 if (type
!= DER_SEQUENCE
)
327 type
= der_get_next (key
, len
, offset
, &elen
, &edata
);
328 if (type
== DER_INTEGER
) {
333 /* a private RSA key */
334 val
= get_der_int (edata
, elen
);
337 offset
= elen
+ edata
- key
;
339 type
= der_get_next (key
, len
, offset
, &elen
, &edata
);
340 if (type
!= DER_INTEGER
)
342 offset
= elen
+ edata
- key
;
343 if ((elen
& 1) && *edata
== 0) {
347 r
= g_new0 (guchar
, elen
*4 + elen
/2 + 20);
348 r
[0] = 0x7; r
[1] = 0x2; r
[5] = 0x24;
349 r
[8] = 0x52; r
[9] = 0x53; r
[10] = 0x41; r
[11] = 0x32;
350 *(guint32
*)(r
+ 12) = elen
* 8;
351 memcpy (r
+ 20, edata
, elen
);
352 mem_reverse (r
+ 20, elen
);
355 type
= der_get_next (key
, len
, offset
, &elen
, &edata
);
356 if (type
!= DER_INTEGER
)
358 offset
= elen
+ edata
- key
;
359 val
= get_der_int (edata
, elen
);
360 *(guint32
*)(r
+ 16) = val
;
361 for (i
= 0; i
< 6; i
++) {
362 type
= der_get_next (key
, len
, offset
, &elen
, &edata
);
363 if (type
!= DER_INTEGER
)
365 offset
= elen
+ edata
- key
;
366 if ((elen
& 1) && *edata
== 0) {
372 g_print ("len: %d\n", elen
);
375 g_print ("prime1 at %d (%d)\n", p
-r
, lengths
[1]);
376 memcpy (p
, ints
[1], lengths
[1]);
377 mem_reverse (p
, lengths
[1]);
380 g_print ("prime2 at %d (%d)\n", p
-r
, lengths
[2]);
381 memcpy (p
, ints
[2], lengths
[2]);
382 mem_reverse (p
, lengths
[2]);
385 g_print ("exp1 at %d (%d)\n", p
-r
, lengths
[3]);
386 memcpy (p
, ints
[3], lengths
[3]);
387 mem_reverse (p
, lengths
[3]);
390 g_print ("exp2 at %d (%d)\n", p
-r
, lengths
[4]);
391 memcpy (p
, ints
[4], lengths
[4]);
392 mem_reverse (p
, lengths
[4]);
395 g_print ("coeff at %d (%d)\n", p
-r
, lengths
[5]);
396 memcpy (p
, ints
[5], lengths
[5]);
397 mem_reverse (p
, lengths
[5]);
399 /* private exponent */
400 g_print ("prive at %d (%d)\n", p
-r
, lengths
[0]);
401 memcpy (p
, ints
[0], lengths
[0]);
402 mem_reverse (p
, lengths
[0]);
412 convert_format (const char *from
, const char *outfile
) {
413 guchar
*key
, *bindata
, *keyout
;
415 int binlen
, ret
, lenout
;
418 if (!g_file_get_contents (from
, (gchar
**) &key
, &len
, NULL
)) {
419 printf ("Cannot load file: %s\n", from
);
423 if (*key
== 0 || *key
== 0x24) {
425 printf ("Cannot convert to pem format yet\n");
428 bindata
= pem_decode (key
, len
, &binlen
);
429 if (!(file
= fopen (outfile
, "wb"))) {
431 printf ("Cannot open output file: %s\n", outfile
);
434 dump_asn1 (bindata
, binlen
);
435 ret
= convert_der_key (bindata
, binlen
, &keyout
, &lenout
);
437 fwrite (keyout
, lenout
, 1, file
);
440 printf ("Cannot convert key\n");
448 get_digest (const char *from
, const char *outfile
)
453 guint32 snpos
, snsize
;
456 MonoSHA1Context sha1
;
458 image
= mono_image_open (from
, NULL
);
460 printf ("Cannot open image file: %s\n", from
);
463 snpos
= mono_image_strong_name_position (image
, &snsize
);
465 /*printf ("%s does not represent a strongly named assembly\n", from);
466 mono_image_close (image);
471 if (!g_file_get_contents (from
, (gchar
**) &ass
, &len
, NULL
)) {
472 printf ("Cannot load file: %s\n", from
);
473 mono_image_close (image
);
477 * FIXME: we may need to set the STRONGNAMESIGNED flag in the cli header
478 * before taking the sha1 digest of the image.
480 mono_sha1_init (&sha1
);
481 mono_sha1_update (&sha1
, ass
, snpos
);
482 mono_sha1_update (&sha1
, ass
+ snpos
+ snsize
, len
- snsize
- snpos
);
483 mono_sha1_final (&sha1
, digest
);
485 mono_image_close (image
);
487 if (!(file
= fopen (outfile
, "wb"))) {
488 printf ("Cannot open output file: %s\n", outfile
);
491 fwrite (digest
, 20, 1, file
);
498 printf ("monosn: Mono Strong Name Utility\nUsage: monosn option [arguments]\n");
499 printf ("Available options:\n");
500 printf ("\t-C keyin keyout Convert key file format from PEM to cryptoAPI (or the reverse).\n");
501 printf ("\t-e assembly file Extract the public key from assembly to file.\n");
502 printf ("\t-E assembly file Extract the strong name from assembly to file.\n");
503 printf ("\t-r assembly file Extract the sha1 digest from assembly to file.\n");
504 printf ("\t-t[p] file Display the public key token from file.\n");
505 printf ("\t-T[p] assembly Display the public key token from assembly.\n");
510 main (int argc
, char *argv
[]) {
513 if (argc
< 2 || argv
[1] [0] != '-')
521 return convert_format (argv
[2], argv
[3]);
525 return extract_data_to_file (1, argv
[2], argv
[3]);
529 return extract_data_to_file (0, argv
[2], argv
[3]);
537 return get_digest (argv
[2], argv
[3]);
541 return show_token (argv
[2], 0, argv
[1] [2] == 'p');
545 return show_token (argv
[2], 1, argv
[1] [2] == 'p');