[Mono-list] CryptoConfig and bug #30257 (repost)

Sebastien Pouliot Sebastien Pouliot <spouliot@videotron.ca>
Sat, 05 Oct 2002 17:02:15 -0400


This is a multi-part message in MIME format.

--Boundary_(ID_qV/239Up6QeZ4r7Z7Sp/Qg)
Content-type: text/plain; charset=iso-8859-1
Content-transfer-encoding: 8BIT

Note:    This is a repost because
a.    The mail didn't seem to reach the list;
b.    There was a file missing to run the test (AllTest.cs.diff)
---

While doing the X509Certificate class I found out that the CryptoConfig
class was missing. This is an important cryptographic class which role seems
little understood (
http://www.codeproject.com/dotnet/encryption_decryption.asp?df=100&forumid=3
466&select=296127#xx296127xx ). This is probably due to the really short
(one sentence), lame and sometimes wrong class documentation.

So here is the CryptoConfig class with it's NUnit test class. This should
make the GotDotNet "Hash" sample works normally (bug #30257 -
http://bugzilla.ximian.com/show_bug.cgi?id=30257 ) - at least it works under
Windows (both with Mono and MS).

Please note that the class isn't 100% complete because, under MS .NET
framework, it use the "machine.config" file to change default algorithm
implementation - and I couldn't find one in mono. Is there (yet) a
"machine.config" file in mono ?

If not, is there a similar .config file, on which I can base myself to
complete CryptoConfig ?

Note: Installing the WSDK (Web Services Development Kit) changes the
"machine.config" file. After the update the "SHA1" and
"System.Security.Cryptography.SHA1" maps to "SHA1Managed" class (instead of
"SHA1CryptoServiceProvider"). However both "SHA" and
"System.Security.Cryptography.HashAlgorithm" still maps to
"SHA1CryptoServiceProvider". What this means is that the unit test will FAIL
when run under MS framework if WSDK is installed !


Sébastien Pouliot
Security Architect, Motus Technologies, http://www.motus.com/
work: spouliot@motus.com
home: spouliot@videotron.ca

--Boundary_(ID_qV/239Up6QeZ4r7Z7Sp/Qg)
Content-type: application/octet-stream; name=AllTests.cs.diff
Content-transfer-encoding: quoted-printable
Content-disposition: attachment; filename=AllTests.cs.diff

2c2
< // TestSuite.System.Security.Cryptography.AllTests.cs
---
> // TestSuite.System.Security.Cryptography.AllCryptoTests.cs=0D
4c4
< // Authors:
---
> // Author:=0D
6,8d5
< //	Sebastien Pouliot (spouliot@motus.com)
< //
< // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
15,44c12,16
<=20
< /// <summary>
< ///   Combines all available crypto unit tests into one test suite.
< /// </summary>
< public class AllTests : TestCase {
< 	public AllTests (string name) : base (name) {}
<=20
< 	// because most crypto stuff works with byte[] buffers
< 	static public void AssertEquals (string msg, byte[] array1, byte[] =
array2)
< 	{
< 		if ((array1 =3D=3D null) && (array2 =3D=3D null))
< 			return;
< 		if (array1 =3D=3D null)
< 			Fail (msg + " -> First array is NULL");
< 		if (array2 =3D=3D null)
< 			Fail (msg + " -> Second array is NULL");
<=20
< 		bool a =3D (array1.Length =3D=3D array2.Length);
< 		if (a) {
< 			for (int i =3D 0; i < array1.Length; i++) {
< 				if (array1 [i] !=3D array2 [i]) {
< 					a =3D false;
< 					break;
< 				}
< 			}
< 		}
< 		msg +=3D " -> Expected " + BitConverter.ToString (array1, 0);
< 		msg +=3D " is different than " + BitConverter.ToString (array2, 0);
< 		Assert (msg, a);
< 	}
---
>         /// <summary>=0D
>         ///   Combines all available crypto unit tests into one test =
suite.=0D
>         /// </summary>=0D
>         public class AllTests : TestCase {=0D
>                 public AllTests(string name) : base(name) {}=0D
48c20,21
< 		get {
---
>                         get =0D
>                         {=0D
54c27,29
< 			suite.AddTest (CryptoConfigTest.Suite);
---
> 				suite.AddTest (RijndaelManagedTest.Suite);=0D
> 				suite.AddTest (MD5Test.Suite);=0D
> 				suite.AddTest (RC2Test.Suite);
58,59c33
< }
<=20
---
>         }=0D

--Boundary_(ID_qV/239Up6QeZ4r7Z7Sp/Qg)
Content-type: text/plain; name=CryptoConfigTest.cs
Content-transfer-encoding: 7BIT
Content-disposition: attachment; filename=CryptoConfigTest.cs

//
// CryptoConfigTest.cs - NUnit Test Cases for CryptoConfig
//
// Author:
//		Sebastien Pouliot (spouliot@motus.com)
//
// (C) 2002 Motus Technologies Inc. (http://www.motus.com)
//

using NUnit.Framework;
using System;
using System.Security.Cryptography;

namespace MonoTests.System.Security.Cryptography
{

public class CryptoConfigTest : TestCase 
{
	public CryptoConfigTest () : base ("System.Security.Cryptography.CryptoConfig testsuite") {}
	public CryptoConfigTest (string name) : base (name) {}

	protected override void SetUp () {}

	protected override void TearDown () {}

	public static ITest Suite {
		get { 
			return new TestSuite (typeof (CryptoConfigTest)); 
		}
	}

	public void AssertEquals (string msg, byte[] array1, byte[] array2)
	{
		AllTests.AssertEquals (msg, array1, array2);
	}

	void CreateFromName (string name, string objectname)
	{
		object o = CryptoConfig.CreateFromName (name);
		AssertEquals (name, o.ToString(), objectname);
	}

	// validate that CryptoConfig create the exact same implementation between mono and MS
	public void TestCreateFromName () 
	{
		try {
			object o = CryptoConfig.CreateFromName (null);
		}
		catch (ArgumentNullException) {
			// do nothing, this is what we expect
		}
		catch (Exception e) {
			Fail ("ArgumentNullException not thrown: " + e.ToString());
		}
		CreateFromName ("SHA", "System.Security.Cryptography.SHA1CryptoServiceProvider");
		// FIXME: We need to support the machine.config file to get exact same results
		// with the MS .NET Framework
		CreateFromName ("SHA1", "System.Security.Cryptography.SHA1CryptoServiceProvider");
		CreateFromName( "System.Security.Cryptography.SHA1", "System.Security.Cryptography.SHA1CryptoServiceProvider");
		// after installing the WSDK - changes to the machine.config file (not documented)
//		CreateFromName ("SHA1", "System.Security.Cryptography.SHA1Managed");
//		CreateFromName ("System.Security.Cryptography.SHA1", "System.Security.Cryptography.SHA1Managed");
		CreateFromName ("System.Security.Cryptography.HashAlgorithm", "System.Security.Cryptography.SHA1CryptoServiceProvider");
		CreateFromName ("MD5", "System.Security.Cryptography.MD5CryptoServiceProvider");  
		CreateFromName ("System.Security.Cryptography.MD5", "System.Security.Cryptography.MD5CryptoServiceProvider");  
		CreateFromName ("SHA256", "System.Security.Cryptography.SHA256Managed");  
		CreateFromName ("SHA-256", "System.Security.Cryptography.SHA256Managed");  
		CreateFromName ("System.Security.Cryptography.SHA256", "System.Security.Cryptography.SHA256Managed");  
		CreateFromName ("SHA384", "System.Security.Cryptography.SHA384Managed");  
		CreateFromName ("SHA-384", "System.Security.Cryptography.SHA384Managed");  
		CreateFromName ("System.Security.Cryptography.SHA384", "System.Security.Cryptography.SHA384Managed");  
		CreateFromName ("SHA512", "System.Security.Cryptography.SHA512Managed");  
		CreateFromName ("SHA-512", "System.Security.Cryptography.SHA512Managed");  
		CreateFromName ("System.Security.Cryptography.SHA512", "System.Security.Cryptography.SHA512Managed");  
		CreateFromName ("RSA", "System.Security.Cryptography.RSACryptoServiceProvider");  
		CreateFromName ("System.Security.Cryptography.RSA", "System.Security.Cryptography.RSACryptoServiceProvider");  
		CreateFromName ("System.Security.Cryptography.AsymmetricAlgorithm", "System.Security.Cryptography.RSACryptoServiceProvider");  
		CreateFromName ("DSA", "System.Security.Cryptography.DSACryptoServiceProvider");  
		CreateFromName ("System.Security.Cryptography.DSA", "System.Security.Cryptography.DSACryptoServiceProvider");  
		CreateFromName ("DES", "System.Security.Cryptography.DESCryptoServiceProvider");  
		CreateFromName ("System.Security.Cryptography.DES", "System.Security.Cryptography.DESCryptoServiceProvider");  
		CreateFromName ("3DES", "System.Security.Cryptography.TripleDESCryptoServiceProvider");  
		CreateFromName ("TripleDES", "System.Security.Cryptography.TripleDESCryptoServiceProvider");  
		CreateFromName ("Triple DES", "System.Security.Cryptography.TripleDESCryptoServiceProvider");  
		CreateFromName ("System.Security.Cryptography.TripleDES", "System.Security.Cryptography.TripleDESCryptoServiceProvider");  
		// LAMESPEC SymmetricAlgorithm documented as TripleDESCryptoServiceProvider
		CreateFromName ("System.Security.Cryptography.SymmetricAlgorithm", "System.Security.Cryptography.RijndaelManaged");  
		CreateFromName ("RC2", "System.Security.Cryptography.RC2CryptoServiceProvider");  
		CreateFromName ("System.Security.Cryptography.RC2", "System.Security.Cryptography.RC2CryptoServiceProvider");  
		CreateFromName ("Rijndael", "System.Security.Cryptography.RijndaelManaged");  
		CreateFromName ("System.Security.Cryptography.Rijndael", "System.Security.Cryptography.RijndaelManaged");
		// LAMESPEC Undocumented Names in CryptoConfig
		CreateFromName ("RandomNumberGenerator", "System.Security.Cryptography.RNGCryptoServiceProvider");
		CreateFromName ("System.Security.Cryptography.RandomNumberGenerator", "System.Security.Cryptography.RNGCryptoServiceProvider");
		CreateFromName ("System.Security.Cryptography.KeyedHashAlgorithm", "System.Security.Cryptography.HMACSHA1");
		CreateFromName ("HMACSHA1", "System.Security.Cryptography.HMACSHA1");
		CreateFromName ("System.Security.Cryptography.HMACSHA1", "System.Security.Cryptography.HMACSHA1");
		CreateFromName ("MACTripleDES", "System.Security.Cryptography.MACTripleDES");
		CreateFromName ("System.Security.Cryptography.MACTripleDES", "System.Security.Cryptography.MACTripleDES");
		// non existing algo should return null (without exception)
		AssertNull ("NonExistingAlgorithm", CryptoConfig.CreateFromName("NonExistingAlgorithm"));
	}

	// Tests created using "A Layer Man Guide to ASN.1" from RSA, page 19-20
	// Need to find an OID ? goto http://www.alvestrand.no/~hta/objectid/top.html
	static byte[] oidETSI = { 0x06, 0x03, 0x04, 0x00, 0x00 };
	static byte[] oidSHA1 = { 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A };
	static byte[] oidASN1CharacterModule = { 0x06, 0x04, 0x51, 0x00, 0x00, 0x00 };
	static byte[] oidmd5withRSAEncryption = { 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04 };

	// LAMESPEC NullReferenceException is thrown (not ArgumentNullException) if parameter is NULL
	public void TestEncodeOID () 
	{
		try {
			byte[] o = CryptoConfig.EncodeOID (null);
		}
		catch (NullReferenceException) {
			// do nothing, this is what we expect
		}
		catch (Exception e) {
			Fail ("NullReferenceException not thrown: " + e.ToString());
		}
		// OID starts with 0, 1 or 2
		AssertEquals ("OID starting with 0.", oidETSI, CryptoConfig.EncodeOID ("0.4.0.0"));
		AssertEquals ("OID starting with 1.", oidSHA1, CryptoConfig.EncodeOID ("1.3.14.3.2.26"));
		AssertEquals ("OID starting with 2.", oidASN1CharacterModule, CryptoConfig.EncodeOID ("2.1.0.0.0"));
		// OID numbers can span multiple bytes
		AssertEquals ("OID with numbers spanning multiple bytes", oidmd5withRSAEncryption, CryptoConfig.EncodeOID ("1.2.840.113549.1.1.4"));
		
		// "ms"-invalid OID - greater than 127 bytes (length encoding)
		// OID longer than 127 bytes (so length must be encoded on multiple bytes)
		// LAMESPEC: OID greater that 0x7F (127) bytes aren't supported by the MS Framework
		string baseOID = "1.3.6.1.4.1.11071.0.";
		string lastPart = "1111111111"; // must fit in int32
		for (int i = 1; i < 30; i++)
		{
			baseOID += lastPart + ".";
		}
		baseOID += "0";
		try {
			byte[] tooLongOID = CryptoConfig.EncodeOID (baseOID);
		}
		catch (CryptographicUnexpectedOperationException) {
			// do nothing, this is what we expect
		}
		catch (Exception e) {
			Fail ("CryptographicUnexpectedOperationException not thrown: " + e.ToString());
		}
		
		// "ms"-invalid OID - where a number of the OID > Int32
		// LAMESPEC: OID with numbers > Int32 aren't supported by the MS BCL
		try {
			byte[] tooLongOID = CryptoConfig.EncodeOID ("1.1.4294967295");
		}
		catch (OverflowException) {
			// do nothing, this is what we expect
		}
		catch (Exception e) {
			Fail( "OverflowException not thrown: " + e.ToString ());
		}

		// invalid OID - must start with 0, 1 or 2
		// however it works with MS BCL
		byte[] oid3 = CryptoConfig.EncodeOID ("3.0");
		byte[] res3 = { 0x06, 0x01, 0x78 };
		AssertEquals ("OID: 3.0", res3, oid3);

		// invalid OID - must have at least 2 parts (according to X.208)
		try {
			byte[] tooShortOID = CryptoConfig.EncodeOID ("0");
		}
		catch (CryptographicUnexpectedOperationException) {
			// do nothing, this is what we expect
		}
		catch (Exception e) {
			Fail("CryptographicUnexpectedOperationException not thrown: " + e.ToString());
		}

		// invalid OID - second value < 40 for 0. and 1. (modulo 40)
		// however it works with MS BCL
		byte[] tooBigSecondPartOID = CryptoConfig.EncodeOID ("0.40");
		byte[] tooBigSecondPartRes = { 0x06, 0x01, 0x28 };
		AssertEquals ("OID: 0.40", tooBigSecondPartRes, tooBigSecondPartOID);
	}

	private void MapNameToOID (string name, string oid)
	{
		AssertEquals ("oid(" + name + ")", oid, CryptoConfig.MapNameToOID (name));
	}

	// LAMESPEC doesn't support all names defined in CryptoConfig 
	// non supported names (in MSFW) are commented or null-ed
	public void TestMapNameToOID() 
	{
		try {
			CryptoConfig.MapNameToOID (null);
		}
		catch (ArgumentNullException) {
			// do nothing, this is what we expect
		}
		catch (Exception e) {
			Fail( "ArgumentNullException not thrown: " + e.ToString ());
		}
//		MapNameToOID ("SHA", "1.3.14.3.2.26");
		MapNameToOID ("SHA1", "1.3.14.3.2.26");
		MapNameToOID ("System.Security.Cryptography.SHA1", "1.3.14.3.2.26");
//		MapNameToOID ("System.Security.Cryptography.HashAlgorithm", "1.3.14.3.2.26");
		MapNameToOID ("MD5", "1.2.840.113549.2.5");
		MapNameToOID ("System.Security.Cryptography.MD5", "1.2.840.113549.2.5");
		MapNameToOID ("SHA256", "2.16.840.1.101.3.4.1");
//		MapNameToOID ("SHA-256", "2.16.840.1.101.3.4.1");
		MapNameToOID ("System.Security.Cryptography.SHA256", "2.16.840.1.101.3.4.1");
		MapNameToOID ("SHA384", "2.16.840.1.101.3.4.2");
//		MapNameToOID ("SHA-384", "2.16.840.1.101.3.4.2");
		MapNameToOID ("System.Security.Cryptography.SHA384", "2.16.840.1.101.3.4.2");
		MapNameToOID ("SHA512", "2.16.840.1.101.3.4.3");
//		MapNameToOID ("SHA-512", "2.16.840.1.101.3.4.3");
		MapNameToOID ("System.Security.Cryptography.SHA512", "2.16.840.1.101.3.4.3");
		// no OID defined ?
		MapNameToOID ("RSA", null);
		MapNameToOID ("System.Security.Cryptography.RSA", null);
		MapNameToOID ("System.Security.Cryptography.AsymmetricAlgorithm", null);
		MapNameToOID ("DSA", null);
		MapNameToOID ("System.Security.Cryptography.DSA", null);
		MapNameToOID ("DES", null);
		MapNameToOID ("System.Security.Cryptography.DES", null);
		MapNameToOID ("3DES", null);
		MapNameToOID ("TripleDES", null);
		MapNameToOID ("Triple DES", null);
		MapNameToOID ("System.Security.Cryptography.TripleDES", null);
		MapNameToOID ("RC2", null);
		MapNameToOID ("System.Security.Cryptography.RC2", null);
		MapNameToOID ("Rijndael", null);
		MapNameToOID ("System.Security.Cryptography.Rijndael", null);
		MapNameToOID ("System.Security.Cryptography.SymmetricAlgorithm", null);
		// LAMESPEC Undocumented Names in CryptoConfig
		MapNameToOID ("RandomNumberGenerator", null);
		MapNameToOID ("System.Security.Cryptography.RandomNumberGenerator", null);
		MapNameToOID ("System.Security.Cryptography.KeyedHashAlgorithm", null);
		MapNameToOID ("HMACSHA1", null);
		MapNameToOID ("System.Security.Cryptography.HMACSHA1", null);
		MapNameToOID ("MACTripleDES", null);
		MapNameToOID ("System.Security.Cryptography.MACTripleDES", null);
		// non existing algo should return null (without exception)
		MapNameToOID ("NonExistingAlgorithm", null);
	}

	public void TestToString() 
	{
		// under normal circumstance there are no need to create a CryptoConfig object
		// because all interesting stuff are in static methods
		CryptoConfig cc = new CryptoConfig ();
		AssertEquals ("System.Security.Cryptography.CryptoConfig", cc.ToString ());
	}
}

}

--Boundary_(ID_qV/239Up6QeZ4r7Z7Sp/Qg)
Content-type: text/plain; name=CryptoConfig.cs
Content-transfer-encoding: 7BIT
Content-disposition: attachment; filename=CryptoConfig.cs

//
// CryptoConfig.cs: Handles cryptographic implementations and OIDs.
//
// Author:
//		Sebastien Pouliot (spouliot@motus.com)
//
// (C) 2002 Motus Technologies Inc. (http://www.motus.com)
//

using System;
using System.Collections;
using System.Reflection;

namespace System.Security.Cryptography
{

public class CryptoConfig
{
	static private Hashtable algorithms;
	static private Hashtable oid;

	private const string defaultNamespace = "System.Security.Cryptography.";
	private const string defaultSHA1 = defaultNamespace + "SHA1CryptoServiceProvider";
	private const string defaultMD5 = defaultNamespace + "MD5CryptoServiceProvider";
	private const string defaultSHA256 = defaultNamespace + "SHA256Managed";
	private const string defaultSHA384 = defaultNamespace + "SHA384Managed";
	private const string defaultSHA512 = defaultNamespace + "SHA512Managed";
	private const string defaultRSA = defaultNamespace + "RSACryptoServiceProvider";
	private const string defaultDSA = defaultNamespace + "DSACryptoServiceProvider";
	private const string defaultDES = defaultNamespace + "DESCryptoServiceProvider";
	private const string default3DES = defaultNamespace + "TripleDESCryptoServiceProvider";
	private const string defaultRC2 = defaultNamespace + "RC2CryptoServiceProvider";
	private const string defaultAES = defaultNamespace + "RijndaelManaged";
	// LAMESPEC: undocumented names in CryptoConfig
	private const string defaultRNG = defaultNamespace + "RNGCryptoServiceProvider";
	private const string defaultHMAC = defaultNamespace + "HMACSHA1";
	private const string defaultMAC3DES = defaultNamespace + "MACTripleDES";

	// Oddly OID seems only available for hash algorithms
	private const string oidSHA1 = "1.3.14.3.2.26";
	private const string oidMD5 = "1.2.840.113549.2.5";
	private const string oidSHA256 = "2.16.840.1.101.3.4.1";
	private const string oidSHA384 = "2.16.840.1.101.3.4.2";
	private const string oidSHA512 = "2.16.840.1.101.3.4.3";

	private const string nameSHA1a = "SHA";
	private const string nameSHA1b = "SHA1";
	private const string nameSHA1c = "System.Security.Cryptography.SHA1";
	private const string nameSHA1d = "System.Security.Cryptography.HashAlgorithm";
	private const string nameMD5a = "MD5";
	private const string nameMD5b = "System.Security.Cryptography.MD5";
	private const string nameSHA256a = "SHA256";
	private const string nameSHA256b = "SHA-256";
	private const string nameSHA256c = "System.Security.Cryptography.SHA256";
	private const string nameSHA384a = "SHA384";
	private const string nameSHA384b = "SHA-384";
	private const string nameSHA384c = "System.Security.Cryptography.SHA384";
	private const string nameSHA512a = "SHA512";
	private const string nameSHA512b = "SHA-512";
	private const string nameSHA512c = "System.Security.Cryptography.SHA512";
	private const string nameRSAa = "RSA";
	private const string nameRSAb = "System.Security.Cryptography.RSA";
	private const string nameRSAc = "System.Security.Cryptography.AsymmetricAlgorithm";
	private const string nameDSAa = "DSA";
	private const string nameDSAb = "System.Security.Cryptography.DSA";
	private const string nameDESa = "DES";
	private const string nameDESb = "System.Security.Cryptography.DES";
	private const string name3DESa = "3DES";
	private const string name3DESb = "TripleDES";
	private const string name3DESc = "Triple DES";
	private const string name3DESd = "System.Security.Cryptography.TripleDES";
	private const string nameRC2a = "RC2";
	private const string nameRC2b = "System.Security.Cryptography.RC2";
	private const string nameAESa = "Rijndael";
	private const string nameAESb = "System.Security.Cryptography.Rijndael";
	private const string nameAESc = "System.Security.Cryptography.SymmetricAlgorithm";
	// LAMESPEC: undocumented names in CryptoConfig
	private const string nameRNGa = "RandomNumberGenerator";
	private const string nameRNGb = "System.Security.Cryptography.RandomNumberGenerator";
	private const string nameKeyHasha = "System.Security.Cryptography.KeyedHashAlgorithm";
	private const string nameHMACa = "HMACSHA1";
	private const string nameHMACb = "System.Security.Cryptography.HMACSHA1";
	private const string nameMAC3DESa = "MACTripleDES";
	private const string nameMAC3DESb = "System.Security.Cryptography.MACTripleDES";

	// ??? must we read from the machine.config each time or just at startup ???
	[MonoTODO ("support machine.config")]
	static CryptoConfig()
	{
		algorithms = new Hashtable ();
		// see list @ http://msdn.microsoft.com/library/en-us/cpref/html/
		// frlrfSystemSecurityCryptographyCryptoConfigClassTopic.asp
		algorithms.Add (nameSHA1a, defaultSHA1);
		algorithms.Add (nameSHA1b, defaultSHA1);
		algorithms.Add (nameSHA1c, defaultSHA1);
		algorithms.Add (nameSHA1d, defaultSHA1);

		algorithms.Add (nameMD5a, defaultMD5);
		algorithms.Add (nameMD5b, defaultMD5);

		algorithms.Add (nameSHA256a, defaultSHA256);
		algorithms.Add (nameSHA256b, defaultSHA256);
		algorithms.Add (nameSHA256c, defaultSHA256);

		algorithms.Add (nameSHA384a, defaultSHA384);
		algorithms.Add (nameSHA384b, defaultSHA384);
		algorithms.Add (nameSHA384c, defaultSHA384);

		algorithms.Add (nameSHA512a, defaultSHA512);
		algorithms.Add (nameSHA512b, defaultSHA512);
		algorithms.Add (nameSHA512c, defaultSHA512);

		algorithms.Add (nameRSAa, defaultRSA);
		algorithms.Add (nameRSAb, defaultRSA); 
		algorithms.Add (nameRSAc, defaultRSA);

		algorithms.Add (nameDSAa, defaultDSA);  
		algorithms.Add (nameDSAb, defaultDSA);  
	
		algorithms.Add (nameDESa, defaultDES);  
		algorithms.Add (nameDESb, defaultDES);  
	
		algorithms.Add (name3DESa, default3DES);    
		algorithms.Add (name3DESb, default3DES);    
		algorithms.Add (name3DESc, default3DES);     
		algorithms.Add (name3DESd, default3DES);    
	
		algorithms.Add (nameRC2a, defaultRC2);  
		algorithms.Add (nameRC2b, defaultRC2);  

		algorithms.Add (nameAESa, defaultAES);  
		algorithms.Add (nameAESb, defaultAES);
		// LAMESPEC SymmetricAlgorithm documented as TripleDESCryptoServiceProvider
		algorithms.Add (nameAESc, defaultAES);

		// LAMESPEC These names aren't documented but (hint) the classes also have
		// static Create methods. So logically they should (and are) here.
		algorithms.Add (nameRNGa, defaultRNG);
		algorithms.Add (nameRNGb, defaultRNG);
		algorithms.Add (nameKeyHasha, defaultHMAC);
		algorithms.Add (nameHMACa, defaultHMAC);
		algorithms.Add (nameHMACb, defaultHMAC);
		algorithms.Add (nameMAC3DESa, defaultMAC3DES);
		algorithms.Add (nameMAC3DESb, defaultMAC3DES);

		oid = new Hashtable ();
		// comments here are to match with MS implementation (but not with doc)
		// LAMESPEC: only HashAlgorithm seems to have their OID included
		// oid.Add (nameSHA1a, oidSHA1);
		oid.Add (nameSHA1b, oidSHA1);
		oid.Add (nameSHA1c, oidSHA1);
		// oid.Add (nameSHA1d, oidSHA1);
		oid.Add (nameMD5a, oidMD5);
		oid.Add (nameMD5b, oidMD5);
		oid.Add (nameSHA256a, oidSHA256);
		// oid.Add (nameSHA256b, oidSHA256);
		oid.Add (nameSHA256c, oidSHA256);
		oid.Add (nameSHA384a, oidSHA384);
		// oid.Add (nameSHA384b, oidSHA384);
		oid.Add (nameSHA384c, oidSHA384);
		oid.Add (nameSHA512a, oidSHA512);
		// oid.Add (nameSHA512b, oidSHA512);
		oid.Add (nameSHA512c, oidSHA512);
	}

	public static object CreateFromName (string name)
	{
		return CreateFromName (name, null);
	}

	public static object CreateFromName (string name, object[] args)
	{
		if (name == null)
			throw new ArgumentNullException ();
	
		try {
			string algo = (string)algorithms [name];
			Type algoClass = Type.GetType (algo);
			// call the constructor for the type
			return Activator.CreateInstance (algoClass, args);
		}
		catch {
			return null;
		}
	}

	// encode (7bits array) number greater than 127
	private static byte[] EncodeLongNumber (long x)
	{
		// for MS BCL compatibility
		// comment next two lines to remove restriction
		if ((x > Int32.MaxValue) || (x < Int32.MinValue))
			throw new OverflowException("part of OID doesn't fit in Int32");

		long y = x;
		// number of bytes required to encode this number
		int n = 1;
		while (y > 0x7F) {
			y = y >> 7;
			n++;
		}
		byte[] num = new byte [n];
		// encode all bytes 
		for (int i = 0; i < n; i++) {
			y = x >> (7 * i);
			y = y & 0x7F;
			if (i != 0)
				y += 0x80;
			num[n-i-1] = Convert.ToByte (y);
		}
		return num;
	}

	public static byte[] EncodeOID (string str)
	{
		char[] delim = { '.' };
		string[] parts = str.Split (delim);
		// according to X.208 n is always at least 2
		if (parts.Length < 2)
			throw new CryptographicUnexpectedOperationException ();
		// we're sure that the encoded OID is shorter than its string representation
		byte[] oid = new byte [str.Length];
		// now encoding value
		try {
			byte part0 = Convert.ToByte (parts [0]);
			// OID[0] > 2 is invalid but "supported" in MS BCL
			// uncomment next line to trap this error
			// if (part0 > 2) throw new CryptographicUnexpectedOperationException ();
			byte part1 = Convert.ToByte (parts [1]);
			// OID[1] >= 40 is illegal for OID[0] < 2 because of the % 40
			// however the syntax is "supported" in MS BCL
			// uncomment next 2 lines to trap this error
			//if ((part0 < 2) && (part1 >= 40))
			//	throw new CryptographicUnexpectedOperationException ();
			oid[2] = Convert.ToByte (part0 * 40 + part1);
		}
		catch {
			throw new CryptographicUnexpectedOperationException ();
		}
		int j = 3;
		for (int i = 2; i < parts.Length; i++) {
			long x = Convert.ToInt64( parts [i]);
			if (x > 0x7F) {
				byte[] num = EncodeLongNumber (x);
				Array.Copy(num, 0, oid, j, num.Length);
				j += num.Length;
			}
			else
				oid[j++] = Convert.ToByte (x);
		}

		int k = 2;
		// copy the exact number of byte required
		byte[] oid2 = new byte [j];
		oid2[0] = 0x06; // always - this tag means OID
		// Length (of value)
		if (j > 0x7F) {
			// for compatibility with MS BCL
			throw new CryptographicUnexpectedOperationException ("OID > 127 bytes");
			// comment exception and uncomment next 3 lines to remove restriction
			//byte[] num = EncodeLongNumber (j);
			//Array.Copy (num, 0, oid, j, num.Length);
			//k = num.Length + 1;
		}
		else
			oid2 [1] = Convert.ToByte (j - 2); 

		System.Array.Copy (oid, k, oid2, k, j - k);
		return oid2;
	}

	public static string MapNameToOID (string name)
	{
		if (name == null)
			throw new ArgumentNullException ();

		return (string)oid [name];
	}
}

}

--Boundary_(ID_qV/239Up6QeZ4r7Z7Sp/Qg)--