2004-04-06 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.Reflection / StrongNameKeyPair.cs
1 //
2 // System.Reflection.StrongNameKeyPair.cs
3 //
4 // Authors:
5 //      Kevin Winchester (kwin@ns.sympatico.ca)
6 //      Sebastien Pouliot (sebastien@ximian.com)
7 //
8 // (C) 2002 Kevin Winchester
9 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
10 // (C) 2004 Novell (http://www.novell.com)
11 //
12
13 using System.IO;
14 using System.Security.Cryptography;
15
16 using Mono.Security;
17 using Mono.Security.Cryptography;
18
19 namespace System.Reflection {
20
21 [Serializable]
22 public class StrongNameKeyPair 
23 {               
24         private byte[] publicKey;
25         private int bitLen;
26         private RSA rsa;
27
28         public StrongNameKeyPair (byte[] keyPairArray) 
29         {
30                 if (keyPairArray == null)
31                         throw new ArgumentNullException ("keyPairArray");
32
33                 LoadKey (keyPairArray);
34         }
35         
36         public StrongNameKeyPair (FileStream keyPairFile) 
37         {
38                 if (keyPairFile == null)
39                         throw new ArgumentNullException ("keyPairFile");
40
41                 byte[] input = new byte [keyPairFile.Length];
42                 keyPairFile.Read (input, 0, input.Length);
43                 LoadKey (input);
44         }
45         
46         public StrongNameKeyPair (string keyPairContainer) 
47         {
48                 // named key container
49                 if (keyPairContainer == null)
50                         throw new ArgumentNullException ("keyPairContainer");
51
52                 CspParameters csp = new CspParameters ();
53                 csp.KeyContainerName = keyPairContainer;
54                 rsa = new RSACryptoServiceProvider (csp);
55         }
56
57         private void LoadKey (byte[] key) 
58         {
59                 try {
60                         // check for ECMA key
61                         if (key.Length == 16) {
62                                 int i = 0;
63                                 int sum = 0;
64                                 while (i < key.Length)
65                                         sum += key [i++];
66                                 if (sum == 4) {
67                                         // it is the ECMA key
68                                         publicKey = (byte[]) key.Clone ();
69                                 }
70                         }
71                         else
72                                 rsa = CryptoConvert.FromCapiKeyBlob (key);
73                 }
74                 catch
75                 {
76                         // exception is thrown when getting PublicKey
77                         // to match MS implementation
78                 }
79         }
80
81         public byte[] PublicKey {
82                 get { 
83                         if (publicKey == null) {
84                                 // ECMA "key" is valid but doesn't produce a RSA instance
85                                 if (rsa == null)
86                                         throw new ArgumentException ("invalid keypair");
87
88                                 byte[] blob = CryptoConvert.ToCapiKeyBlob (rsa, false);
89                                 publicKey = new byte [blob.Length + 12];
90                                 // The first 12 bytes are documented at:\r
91                                 // http://msdn.microsoft.com/library/en-us/cprefadd/html/grfungethashfromfile.asp\r
92                                 // ALG_ID - Signature\r
93                                 publicKey[0] = 0x00;\r
94                                 publicKey[1] = 0x24;    \r
95                                 publicKey[2] = 0x00;    \r
96                                 publicKey[3] = 0x00;    \r
97                                 // ALG_ID - Hash\r
98                                 publicKey[4] = 0x04;\r
99                                 publicKey[5] = 0x80;\r
100                                 publicKey[6] = 0x00;\r
101                                 publicKey[7] = 0x00;\r
102                                 // Length of Public Key (in bytes)\r
103                                 int lastPart = blob.Length;\r
104                                 publicKey[8] = (byte)(lastPart % 256);\r
105                                 publicKey[9] = (byte)(lastPart / 256); // just in case\r
106                                 publicKey[10] = 0x00;\r
107                                 publicKey[11] = 0x00;\r
108
109                                 Buffer.BlockCopy (blob, 0, publicKey, 12, blob.Length);
110                         }
111                         return publicKey;
112                 }
113         }
114
115         internal StrongName StrongName () 
116         {
117                 if (rsa != null)
118                         return new StrongName (rsa);
119                 if (publicKey != null)
120                         return new StrongName (publicKey);
121                 return null;
122         }
123 }
124
125 }