CryptoConfig.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. //
  2. // CryptoConfig.cs: Handles cryptographic implementations and OIDs.
  3. //
  4. // Author:
  5. // Sebastien Pouliot ([email protected])
  6. //
  7. // (C) 2002 Motus Technologies Inc. (http://www.motus.com)
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.Reflection;
  12. namespace System.Security.Cryptography
  13. {
  14. public class CryptoConfig
  15. {
  16. static private Hashtable algorithms;
  17. static private Hashtable oid;
  18. private const string defaultNamespace = "System.Security.Cryptography.";
  19. private const string defaultSHA1 = defaultNamespace + "SHA1CryptoServiceProvider";
  20. private const string defaultMD5 = defaultNamespace + "MD5CryptoServiceProvider";
  21. private const string defaultSHA256 = defaultNamespace + "SHA256Managed";
  22. private const string defaultSHA384 = defaultNamespace + "SHA384Managed";
  23. private const string defaultSHA512 = defaultNamespace + "SHA512Managed";
  24. private const string defaultRSA = defaultNamespace + "RSACryptoServiceProvider";
  25. private const string defaultDSA = defaultNamespace + "DSACryptoServiceProvider";
  26. private const string defaultDES = defaultNamespace + "DESCryptoServiceProvider";
  27. private const string default3DES = defaultNamespace + "TripleDESCryptoServiceProvider";
  28. private const string defaultRC2 = defaultNamespace + "RC2CryptoServiceProvider";
  29. private const string defaultAES = defaultNamespace + "RijndaelManaged";
  30. // LAMESPEC: undocumented names in CryptoConfig
  31. private const string defaultRNG = defaultNamespace + "RNGCryptoServiceProvider";
  32. private const string defaultHMAC = defaultNamespace + "HMACSHA1";
  33. private const string defaultMAC3DES = defaultNamespace + "MACTripleDES";
  34. // Oddly OID seems only available for hash algorithms
  35. private const string oidSHA1 = "1.3.14.3.2.26";
  36. private const string oidMD5 = "1.2.840.113549.2.5";
  37. private const string oidSHA256 = "2.16.840.1.101.3.4.1";
  38. private const string oidSHA384 = "2.16.840.1.101.3.4.2";
  39. private const string oidSHA512 = "2.16.840.1.101.3.4.3";
  40. private const string nameSHA1a = "SHA";
  41. private const string nameSHA1b = "SHA1";
  42. private const string nameSHA1c = "System.Security.Cryptography.SHA1";
  43. private const string nameSHA1d = "System.Security.Cryptography.HashAlgorithm";
  44. private const string nameMD5a = "MD5";
  45. private const string nameMD5b = "System.Security.Cryptography.MD5";
  46. private const string nameSHA256a = "SHA256";
  47. private const string nameSHA256b = "SHA-256";
  48. private const string nameSHA256c = "System.Security.Cryptography.SHA256";
  49. private const string nameSHA384a = "SHA384";
  50. private const string nameSHA384b = "SHA-384";
  51. private const string nameSHA384c = "System.Security.Cryptography.SHA384";
  52. private const string nameSHA512a = "SHA512";
  53. private const string nameSHA512b = "SHA-512";
  54. private const string nameSHA512c = "System.Security.Cryptography.SHA512";
  55. private const string nameRSAa = "RSA";
  56. private const string nameRSAb = "System.Security.Cryptography.RSA";
  57. private const string nameRSAc = "System.Security.Cryptography.AsymmetricAlgorithm";
  58. private const string nameDSAa = "DSA";
  59. private const string nameDSAb = "System.Security.Cryptography.DSA";
  60. private const string nameDESa = "DES";
  61. private const string nameDESb = "System.Security.Cryptography.DES";
  62. private const string name3DESa = "3DES";
  63. private const string name3DESb = "TripleDES";
  64. private const string name3DESc = "Triple DES";
  65. private const string name3DESd = "System.Security.Cryptography.TripleDES";
  66. private const string nameRC2a = "RC2";
  67. private const string nameRC2b = "System.Security.Cryptography.RC2";
  68. private const string nameAESa = "Rijndael";
  69. private const string nameAESb = "System.Security.Cryptography.Rijndael";
  70. private const string nameAESc = "System.Security.Cryptography.SymmetricAlgorithm";
  71. // LAMESPEC: undocumented names in CryptoConfig
  72. private const string nameRNGa = "RandomNumberGenerator";
  73. private const string nameRNGb = "System.Security.Cryptography.RandomNumberGenerator";
  74. private const string nameKeyHasha = "System.Security.Cryptography.KeyedHashAlgorithm";
  75. private const string nameHMACa = "HMACSHA1";
  76. private const string nameHMACb = "System.Security.Cryptography.HMACSHA1";
  77. private const string nameMAC3DESa = "MACTripleDES";
  78. private const string nameMAC3DESb = "System.Security.Cryptography.MACTripleDES";
  79. // ??? must we read from the machine.config each time or just at startup ???
  80. [MonoTODO ("support machine.config")]
  81. static CryptoConfig()
  82. {
  83. algorithms = new Hashtable ();
  84. // see list @ http://msdn.microsoft.com/library/en-us/cpref/html/
  85. // frlrfSystemSecurityCryptographyCryptoConfigClassTopic.asp
  86. algorithms.Add (nameSHA1a, defaultSHA1);
  87. algorithms.Add (nameSHA1b, defaultSHA1);
  88. algorithms.Add (nameSHA1c, defaultSHA1);
  89. algorithms.Add (nameSHA1d, defaultSHA1);
  90. algorithms.Add (nameMD5a, defaultMD5);
  91. algorithms.Add (nameMD5b, defaultMD5);
  92. algorithms.Add (nameSHA256a, defaultSHA256);
  93. algorithms.Add (nameSHA256b, defaultSHA256);
  94. algorithms.Add (nameSHA256c, defaultSHA256);
  95. algorithms.Add (nameSHA384a, defaultSHA384);
  96. algorithms.Add (nameSHA384b, defaultSHA384);
  97. algorithms.Add (nameSHA384c, defaultSHA384);
  98. algorithms.Add (nameSHA512a, defaultSHA512);
  99. algorithms.Add (nameSHA512b, defaultSHA512);
  100. algorithms.Add (nameSHA512c, defaultSHA512);
  101. algorithms.Add (nameRSAa, defaultRSA);
  102. algorithms.Add (nameRSAb, defaultRSA);
  103. algorithms.Add (nameRSAc, defaultRSA);
  104. algorithms.Add (nameDSAa, defaultDSA);
  105. algorithms.Add (nameDSAb, defaultDSA);
  106. algorithms.Add (nameDESa, defaultDES);
  107. algorithms.Add (nameDESb, defaultDES);
  108. algorithms.Add (name3DESa, default3DES);
  109. algorithms.Add (name3DESb, default3DES);
  110. algorithms.Add (name3DESc, default3DES);
  111. algorithms.Add (name3DESd, default3DES);
  112. algorithms.Add (nameRC2a, defaultRC2);
  113. algorithms.Add (nameRC2b, defaultRC2);
  114. algorithms.Add (nameAESa, defaultAES);
  115. algorithms.Add (nameAESb, defaultAES);
  116. // LAMESPEC SymmetricAlgorithm documented as TripleDESCryptoServiceProvider
  117. algorithms.Add (nameAESc, defaultAES);
  118. // LAMESPEC These names aren't documented but (hint) the classes also have
  119. // static Create methods. So logically they should (and are) here.
  120. algorithms.Add (nameRNGa, defaultRNG);
  121. algorithms.Add (nameRNGb, defaultRNG);
  122. algorithms.Add (nameKeyHasha, defaultHMAC);
  123. algorithms.Add (nameHMACa, defaultHMAC);
  124. algorithms.Add (nameHMACb, defaultHMAC);
  125. algorithms.Add (nameMAC3DESa, defaultMAC3DES);
  126. algorithms.Add (nameMAC3DESb, defaultMAC3DES);
  127. oid = new Hashtable ();
  128. // comments here are to match with MS implementation (but not with doc)
  129. // LAMESPEC: only HashAlgorithm seems to have their OID included
  130. // oid.Add (nameSHA1a, oidSHA1);
  131. oid.Add (nameSHA1b, oidSHA1);
  132. oid.Add (nameSHA1c, oidSHA1);
  133. // oid.Add (nameSHA1d, oidSHA1);
  134. oid.Add (nameMD5a, oidMD5);
  135. oid.Add (nameMD5b, oidMD5);
  136. oid.Add (nameSHA256a, oidSHA256);
  137. // oid.Add (nameSHA256b, oidSHA256);
  138. oid.Add (nameSHA256c, oidSHA256);
  139. oid.Add (nameSHA384a, oidSHA384);
  140. // oid.Add (nameSHA384b, oidSHA384);
  141. oid.Add (nameSHA384c, oidSHA384);
  142. oid.Add (nameSHA512a, oidSHA512);
  143. // oid.Add (nameSHA512b, oidSHA512);
  144. oid.Add (nameSHA512c, oidSHA512);
  145. }
  146. public static object CreateFromName (string name)
  147. {
  148. return CreateFromName (name, null);
  149. }
  150. public static object CreateFromName (string name, object[] args)
  151. {
  152. if (name == null)
  153. throw new ArgumentNullException ();
  154. try {
  155. string algo = (string)algorithms [name];
  156. Type algoClass = Type.GetType (algo);
  157. // call the constructor for the type
  158. return Activator.CreateInstance (algoClass, args);
  159. }
  160. catch {
  161. return null;
  162. }
  163. }
  164. // encode (7bits array) number greater than 127
  165. private static byte[] EncodeLongNumber (long x)
  166. {
  167. // for MS BCL compatibility
  168. // comment next two lines to remove restriction
  169. if ((x > Int32.MaxValue) || (x < Int32.MinValue))
  170. throw new OverflowException("part of OID doesn't fit in Int32");
  171. long y = x;
  172. // number of bytes required to encode this number
  173. int n = 1;
  174. while (y > 0x7F) {
  175. y = y >> 7;
  176. n++;
  177. }
  178. byte[] num = new byte [n];
  179. // encode all bytes
  180. for (int i = 0; i < n; i++) {
  181. y = x >> (7 * i);
  182. y = y & 0x7F;
  183. if (i != 0)
  184. y += 0x80;
  185. num[n-i-1] = Convert.ToByte (y);
  186. }
  187. return num;
  188. }
  189. public static byte[] EncodeOID (string str)
  190. {
  191. char[] delim = { '.' };
  192. string[] parts = str.Split (delim);
  193. // according to X.208 n is always at least 2
  194. if (parts.Length < 2)
  195. throw new CryptographicUnexpectedOperationException ();
  196. // we're sure that the encoded OID is shorter than its string representation
  197. byte[] oid = new byte [str.Length];
  198. // now encoding value
  199. try {
  200. byte part0 = Convert.ToByte (parts [0]);
  201. // OID[0] > 2 is invalid but "supported" in MS BCL
  202. // uncomment next line to trap this error
  203. // if (part0 > 2) throw new CryptographicUnexpectedOperationException ();
  204. byte part1 = Convert.ToByte (parts [1]);
  205. // OID[1] >= 40 is illegal for OID[0] < 2 because of the % 40
  206. // however the syntax is "supported" in MS BCL
  207. // uncomment next 2 lines to trap this error
  208. //if ((part0 < 2) && (part1 >= 40))
  209. // throw new CryptographicUnexpectedOperationException ();
  210. oid[2] = Convert.ToByte (part0 * 40 + part1);
  211. }
  212. catch {
  213. throw new CryptographicUnexpectedOperationException ();
  214. }
  215. int j = 3;
  216. for (int i = 2; i < parts.Length; i++) {
  217. long x = Convert.ToInt64( parts [i]);
  218. if (x > 0x7F) {
  219. byte[] num = EncodeLongNumber (x);
  220. Array.Copy(num, 0, oid, j, num.Length);
  221. j += num.Length;
  222. }
  223. else
  224. oid[j++] = Convert.ToByte (x);
  225. }
  226. int k = 2;
  227. // copy the exact number of byte required
  228. byte[] oid2 = new byte [j];
  229. oid2[0] = 0x06; // always - this tag means OID
  230. // Length (of value)
  231. if (j > 0x7F) {
  232. // for compatibility with MS BCL
  233. throw new CryptographicUnexpectedOperationException ("OID > 127 bytes");
  234. // comment exception and uncomment next 3 lines to remove restriction
  235. //byte[] num = EncodeLongNumber (j);
  236. //Array.Copy (num, 0, oid, j, num.Length);
  237. //k = num.Length + 1;
  238. }
  239. else
  240. oid2 [1] = Convert.ToByte (j - 2);
  241. System.Array.Copy (oid, k, oid2, k, j - k);
  242. return oid2;
  243. }
  244. public static string MapNameToOID (string name)
  245. {
  246. if (name == null)
  247. throw new ArgumentNullException ();
  248. return (string)oid [name];
  249. }
  250. }
  251. }