//
// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
// Copyright (C) Tim Coleman, 2004
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2007,2011 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2011 Xamarin Inc. http://www.xamarin.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+#if !MOONLIGHT
+
using System.Collections;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
namespace System.Security.Cryptography {
-public class CryptoConfig {
+[ComVisible (true)]
+public partial class CryptoConfig {
static private object lockObject;
- static private Hashtable algorithms;
- static private Hashtable oid;
+ static private Dictionary<string,Type> algorithms;
+ static private Dictionary<string,string> unresolved_algorithms;
+ static private Dictionary<string,string> oids;
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";
+ static Type defaultSHA1 = typeof (SHA1CryptoServiceProvider);
+ static Type defaultMD5 = typeof (MD5CryptoServiceProvider);
+ static Type defaultSHA256 = typeof (SHA256Managed);
+ static Type defaultSHA384 = typeof (SHA384Managed);
+ static Type defaultSHA512 = typeof (SHA512Managed);
+ static Type defaultRSA = typeof (RSACryptoServiceProvider);
+ static Type defaultDSA = typeof (DSACryptoServiceProvider);
+ static Type defaultDES = typeof (DESCryptoServiceProvider);
+ static Type default3DES = typeof (TripleDESCryptoServiceProvider);
+ static Type defaultRC2 = typeof (RC2CryptoServiceProvider);
+ static Type defaultAES = typeof (RijndaelManaged);
// LAMESPEC: undocumented names in CryptoConfig
- private const string defaultRNG = defaultNamespace + "RNGCryptoServiceProvider";
- private const string defaultHMAC = defaultNamespace + "HMACSHA1";
- private const string defaultMAC3DES = defaultNamespace + "MACTripleDES";
+ static Type defaultRNG = typeof (RNGCryptoServiceProvider);
+ static Type defaultHMAC = typeof (HMACSHA1);
+ static Type defaultMAC3DES = typeof (MACTripleDES);
// LAMESPEC: undocumented classes (also undocumented in CryptoConfig ;-)
- private const string defaultDSASigDesc = defaultNamespace + "DSASignatureDescription";
- private const string defaultRSASigDesc = defaultNamespace + "RSAPKCS1SHA1SignatureDescription";
-#if NET_2_0
- private const string defaultRIPEMD160 = defaultNamespace + "RIPEMD160Managed";
- private const string defaultHMACMD5 = defaultNamespace + "HMACMD5";
- private const string defaultHMACRIPEMD160 = defaultNamespace + "HMACRIPEMD160";
- private const string defaultHMACSHA256 = defaultNamespace + "HMACSHA256";
- private const string defaultHMACSHA384 = defaultNamespace + "HMACSHA384";
- private const string defaultHMACSHA512 = defaultNamespace + "HMACSHA512";
-#endif
+ static Type defaultDSASigDesc = typeof (DSASignatureDescription);
+ static Type defaultRSASigDesc = typeof (RSAPKCS1SHA1SignatureDescription);
+ static Type defaultRIPEMD160 = typeof (RIPEMD160Managed);
+ static Type defaultHMACMD5 = typeof (HMACMD5);
+ static Type defaultHMACRIPEMD160 = typeof (HMACRIPEMD160);
+ static Type defaultHMACSHA256 = typeof (HMACSHA256);
+ static Type defaultHMACSHA384 = typeof (HMACSHA384);
+ static Type defaultHMACSHA512 = typeof (HMACSHA512);
// LAMESPEC: undocumented names in CryptoConfig
-#if (NET_2_0)
- private const string xmlAssembly = ", System.Security, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
-#elif (NET_1_1)
- private const string xmlAssembly = ", System.Security, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
-#elif (NET_1_0)
- private const string xmlAssembly = ", System.Security, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
-#else
- private const string xmlAssembly = ", System.Security, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
-#endif
- private const string defaultC14N = defaultNamespace + "Xml.XmlDsigC14NTransform" + xmlAssembly;
- private const string defaultC14NWithComments = defaultNamespace + "Xml.XmlDsigC14NWithCommentsTransform" + xmlAssembly;
- private const string defaultBase64 = defaultNamespace + "Xml.XmlDsigBase64Transform" + xmlAssembly;
- private const string defaultXPath = defaultNamespace + "Xml.XmlDsigXPathTransform" + xmlAssembly;
- private const string defaultXslt = defaultNamespace + "Xml.XmlDsigXsltTransform" + xmlAssembly;
- private const string defaultEnveloped = defaultNamespace + "Xml.XmlDsigEnvelopedSignatureTransform" + xmlAssembly;
-#if NET_2_0
- private const string defaultXmlDecryption = defaultNamespace + "Xml.XmlDecryptionTransform" + xmlAssembly;
- private const string defaultExcC14N = defaultNamespace + "Xml.XmlDsigExcC14NTransform" + xmlAssembly;
- private const string defaultExcC14NWithComments = defaultNamespace + "Xml.XmlDsigExcC14NWithCommentsTransform" + xmlAssembly;
-#endif
+ private const string defaultC14N = defaultNamespace + "Xml.XmlDsigC14NTransform, " + Consts.AssemblySystem_Security;
+ private const string defaultC14NWithComments = defaultNamespace + "Xml.XmlDsigC14NWithCommentsTransform, " + Consts.AssemblySystem_Security;
+ private const string defaultBase64 = defaultNamespace + "Xml.XmlDsigBase64Transform, " + Consts.AssemblySystem_Security;
+ private const string defaultXPath = defaultNamespace + "Xml.XmlDsigXPathTransform, " + Consts.AssemblySystem_Security;
+ private const string defaultXslt = defaultNamespace + "Xml.XmlDsigXsltTransform, " + Consts.AssemblySystem_Security;
+ private const string defaultEnveloped = defaultNamespace + "Xml.XmlDsigEnvelopedSignatureTransform, " + Consts.AssemblySystem_Security;
+ private const string defaultXmlDecryption = defaultNamespace + "Xml.XmlDecryptionTransform, " + Consts.AssemblySystem_Security;
+ private const string defaultExcC14N = defaultNamespace + "Xml.XmlDsigExcC14NTransform, " + Consts.AssemblySystem_Security;
+ private const string defaultExcC14NWithComments = defaultNamespace + "Xml.XmlDsigExcC14NWithCommentsTransform, " + Consts.AssemblySystem_Security;
// LAMESPEC: only documentated in ".NET Framework Security" book
- private const string defaultX509Data = defaultNamespace + "Xml.KeyInfoX509Data" + xmlAssembly;
- private const string defaultKeyName = defaultNamespace + "Xml.KeyInfoName" + xmlAssembly;
- private const string defaultKeyValueDSA = defaultNamespace + "Xml.DSAKeyValue" + xmlAssembly;
- private const string defaultKeyValueRSA = defaultNamespace + "Xml.RSAKeyValue" + xmlAssembly;
- private const string defaultRetrievalMethod = defaultNamespace + "Xml.KeyInfoRetrievalMethod" + xmlAssembly;
+ private const string defaultX509Data = defaultNamespace + "Xml.KeyInfoX509Data, " + Consts.AssemblySystem_Security;
+ private const string defaultKeyName = defaultNamespace + "Xml.KeyInfoName, " + Consts.AssemblySystem_Security;
+ private const string defaultKeyValueDSA = defaultNamespace + "Xml.DSAKeyValue, " + Consts.AssemblySystem_Security;
+ private const string defaultKeyValueRSA = defaultNamespace + "Xml.RSAKeyValue, " + Consts.AssemblySystem_Security;
+ private const string defaultRetrievalMethod = defaultNamespace + "Xml.KeyInfoRetrievalMethod, " + Consts.AssemblySystem_Security;
private const string managedSHA1 = defaultNamespace + "SHA1Managed";
// 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";
-#if NET_2_0
// changed in 2.0
private const string oidSHA256 = "2.16.840.1.101.3.4.2.1";
private const string oidSHA384 = "2.16.840.1.101.3.4.2.2";
private const string oidSHA512 = "2.16.840.1.101.3.4.2.3";
+ private const string oidRIPEMD160 = "1.3.36.3.2.1";
// new in 2.0
- private const string oidRSA = "1.2.840.113549.1.1.1";
- private const string oidDSA = "1.2.840.10040.4.1";
+// private const string oidRSA = "1.2.840.113549.1.1.1";
+// private const string oidDSA = "1.2.840.10040.4.1";
private const string oidDES = "1.3.14.3.2.7";
private const string oid3DES = "1.2.840.113549.3.7";
private const string oidRC2 = "1.2.840.113549.3.2";
-#else
- 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";
-#endif
// LAMESPEC: only documentated in ".NET Framework Security" book
private const string oid3DESKeyWrap = "1.2.840.113549.1.9.16.3.6";
+ private const string nameSHA1 = "System.Security.Cryptography.SHA1CryptoServiceProvider";
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 nameMD5 = "System.Security.Cryptography.MD5CryptoServiceProvider";
private const string nameMD5a = "MD5";
private const string nameMD5b = "System.Security.Cryptography.MD5";
+ private const string nameSHA256 = "System.Security.Cryptography.SHA256Managed";
private const string nameSHA256a = "SHA256";
private const string nameSHA256b = "SHA-256";
private const string nameSHA256c = "System.Security.Cryptography.SHA256";
+ private const string nameSHA384 = "System.Security.Cryptography.SHA384Managed";
private const string nameSHA384a = "SHA384";
private const string nameSHA384b = "SHA-384";
private const string nameSHA384c = "System.Security.Cryptography.SHA384";
+ private const string nameSHA512 = "System.Security.Cryptography.SHA512Managed";
private const string nameSHA512a = "SHA512";
private const string nameSHA512b = "SHA-512";
private const string nameSHA512c = "System.Security.Cryptography.SHA512";
private const string nameMAC3DESb = "System.Security.Cryptography.MACTripleDES";
// LAMESPEC: only documentated in ".NET Framework Security" book
private const string name3DESKeyWrap = "TripleDESKeyWrap";
-#if NET_2_0
+ private const string nameRIPEMD160 = "System.Security.Cryptography.RIPEMD160Managed";
private const string nameRIPEMD160a = "RIPEMD160";
private const string nameRIPEMD160b = "RIPEMD-160";
private const string nameRIPEMD160c = "System.Security.Cryptography.RIPEMD160";
- private const string nameHMACa = "HMAC";
+// private const string nameHMACa = "HMAC";
private const string nameHMACb = "System.Security.Cryptography.HMAC";
private const string nameHMACMD5a = "HMACMD5";
private const string nameHMACMD5b = "System.Security.Cryptography.HMACMD5";
private const string nameHMACSHA384b = "System.Security.Cryptography.HMACSHA384";
private const string nameHMACSHA512a = "HMACSHA512";
private const string nameHMACSHA512b = "System.Security.Cryptography.HMACSHA512";
-#endif
private const string urlXmlDsig = "http://www.w3.org/2000/09/xmldsig#";
// LAMESPEC: undocumented URLs in CryptoConfig
private const string urlXPath = "http://www.w3.org/TR/1999/REC-xpath-19991116";
private const string urlXslt = "http://www.w3.org/TR/1999/REC-xslt-19991116";
private const string urlEnveloped = urlXmlDsig + "enveloped-signature"; // no space
-#if NET_2_0
private const string urlXmlDecryption = "http://www.w3.org/2002/07/decrypt#XML";
- private const string urlExcC14N = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
- private const string urlExcC14NWithComments = "http://www.w3.org/2001/10/xml-exc-c14n#";
-#endif
+ private const string urlExcC14NWithComments = "http://www.w3.org/2001/10/xml-exc-c14n#WithComments";
+ private const string urlExcC14N = "http://www.w3.org/2001/10/xml-exc-c14n#";
+ private const string urlSHA256 = "http://www.w3.org/2001/04/xmlenc#sha256";
+ private const string urlSHA512 = "http://www.w3.org/2001/04/xmlenc#sha512";
+ private const string urlHMACSHA256 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256";
+ private const string urlHMACSHA384 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha384";
+ private const string urlHMACSHA512 = "http://www.w3.org/2001/04/xmldsig-more#hmac-sha512";
+ private const string urlHMACRIPEMD160 = "http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160";
// LAMESPEC: only documentated in ".NET Framework Security" book
private const string urlX509Data = urlXmlDsig + " X509Data"; // space is required
private const string urlKeyValueRSA = urlXmlDsig + " KeyValue/RSAKeyValue"; // space is required
private const string urlRetrievalMethod = urlXmlDsig + " RetrievalMethod"; // space is required
+ // new (2.0) X509 certificate extensions
+ private const string oidX509SubjectKeyIdentifier = "2.5.29.14";
+ private const string oidX509KeyUsage = "2.5.29.15";
+ private const string oidX509BasicConstraints = "2.5.29.19";
+ private const string oidX509EnhancedKeyUsage = "2.5.29.37";
+
+ private const string nameX509SubjectKeyIdentifier = defaultNamespace + "X509Certificates.X509SubjectKeyIdentifierExtension, " + Consts.AssemblySystem;
+ private const string nameX509KeyUsage = defaultNamespace + "X509Certificates.X509KeyUsageExtension, " + Consts.AssemblySystem;
+ private const string nameX509BasicConstraints = defaultNamespace + "X509Certificates.X509BasicConstraintsExtension, " + Consts.AssemblySystem;
+ private const string nameX509EnhancedKeyUsage = defaultNamespace + "X509Certificates.X509EnhancedKeyUsageExtension, " + Consts.AssemblySystem;
+
+ // new (2.0) X509 Chain
+ private const string nameX509Chain = "X509Chain";
+ private const string defaultX509Chain = defaultNamespace + "X509Certificates.X509Chain, " + Consts.AssemblySystem;
+#if NET_4_0
+ // AES
+ const string system_core_assembly = ", System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
+ const string nameAES_1 = "AES";
+ const string nameAES_2 = "System.Security.Cryptography.AesCryptoServiceProvider";
+ const string defaultAES_1 = "System.Security.Cryptography.AesCryptoServiceProvider" + system_core_assembly;
+
+ const string nameAESManaged_1 = "AesManaged";
+ const string nameAESManaged_2 = "System.Security.Cryptography.AesManaged";
+ const string defaultAESManaged = "System.Security.Cryptography.AesManaged" + system_core_assembly;
+
+ // ECDiffieHellman - not implemented in System.Core at the moment
+ const string nameECDiffieHellman_1 = "ECDH";
+ const string nameECDiffieHellman_2 = "ECDiffieHellman";
+ const string nameECDiffieHellman_3 = "ECDiffieHellmanCng";
+ const string nameECDiffieHellman_4 = "System.Security.Cryptography.ECDiffieHellmanCng";
+ const string defaultECDiffieHellman = "System.Security.Cryptography.ECDiffieHellmanCng" + system_core_assembly;
+
+ // ECDsa - not implemented in System.Core at the moment
+ const string nameECDsa_1 = "ECDsa";
+ const string nameECDsa_2 = "ECDsaCng";
+ const string nameECDsa_3 = "System.Security.Cryptography.ECDsaCng";
+ const string defaultECDsa = "System.Security.Cryptography.ECDsaCng" + system_core_assembly;
+
+ // SHA1Cng
+ const string nameSHA1Cng = "System.Security.Cryptography.SHA1Cng";
+ const string defaultSHA1Cng = "System.Security.Cryptography.SHA1Cng" + system_core_assembly;
+
+ // SHA256Cng
+ const string nameSHA256Cng = "System.Security.Cryptography.SHA256Cng";
+ const string defaultSHA256Cng = "System.Security.Cryptography.SHA256Cng" + system_core_assembly;
+
+ // SHA256 provider
+ const string nameSHA256Provider = "System.Security.Cryptography.SHA256CryptoServiceProvider";
+ const string defaultSHA256Provider = "System.Security.Cryptography.SHA256CryptoServiceProvider" + system_core_assembly;
+
+ // SHA384Cng
+ const string nameSHA384Cng = "System.Security.Cryptography.SHA384Cng";
+ const string defaultSHA384Cng = "System.Security.Cryptography.SHA384Cng" + system_core_assembly;
+
+ // SHA384 provider
+ const string nameSHA384Provider = "System.Security.Cryptography.SHA384CryptoServiceProvider";
+ const string defaultSHA384Provider = "System.Security.Cryptography.SHA384CryptoServiceProvider" + system_core_assembly;
+
+ // SHA512Cng
+ const string nameSHA512Cng = "System.Security.Cryptography.SHA512Cng";
+ const string defaultSHA512Cng = "System.Security.Cryptography.SHA512Cng" + system_core_assembly;
+
+ // SHA512 provider
+ const string nameSHA512Provider = "System.Security.Cryptography.SHA512CryptoServiceProvider";
+ const string defaultSHA512Provider = "System.Security.Cryptography.SHA512CryptoServiceProvider" + system_core_assembly;
+#endif
static CryptoConfig ()
{
// lock(this) is bad
private static void Initialize ()
{
- algorithms = new Hashtable ();
+ Dictionary<string,Type> algorithms = new Dictionary<string, Type> (StringComparer.OrdinalIgnoreCase);
// see list @ http://msdn.microsoft.com/library/en-us/cpref/html/
// frlrfSystemSecurityCryptographyCryptoConfigClassTopic.asp
algorithms.Add (nameSHA1a, defaultSHA1);
algorithms.Add (nameHMACSHA1b, defaultHMAC);
algorithms.Add (nameMAC3DESa, defaultMAC3DES);
algorithms.Add (nameMAC3DESb, defaultMAC3DES);
-#if NET_2_0
algorithms.Add (nameRIPEMD160a, defaultRIPEMD160);
algorithms.Add (nameRIPEMD160b, defaultRIPEMD160);
algorithms.Add (nameRIPEMD160c, defaultRIPEMD160);
algorithms.Add (nameHMACSHA384b, defaultHMACSHA384);
algorithms.Add (nameHMACSHA512a, defaultHMACSHA512);
algorithms.Add (nameHMACSHA512b, defaultHMACSHA512);
-#endif
-
+
+ // we do not want to load the types (and assemblies) unless we really need them
+ // so we keep those names as strings
+ Dictionary<string,string> unresolved_algorithms = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
+
// LAMESPEC These URLs aren't documented but (hint) installing the WSDK
// add some of the XMLDSIG urls into machine.config (and they make a LOT
// of sense for implementing XMLDSIG in System.Security.Cryptography.Xml)
algorithms.Add (urlDSASHA1, defaultDSASigDesc);
algorithms.Add (urlRSASHA1, defaultRSASigDesc);
algorithms.Add (urlSHA1, defaultSHA1);
- algorithms.Add (urlC14N, defaultC14N);
- algorithms.Add (urlC14NWithComments, defaultC14NWithComments);
- algorithms.Add (urlBase64, defaultBase64);
- algorithms.Add (urlXPath, defaultXPath);
- algorithms.Add (urlXslt, defaultXslt);
- algorithms.Add (urlEnveloped, defaultEnveloped);
-#if NET_2_0
- algorithms.Add (urlExcC14N, defaultExcC14N);
- algorithms.Add (urlExcC14NWithComments, defaultExcC14NWithComments);
- algorithms.Add (urlXmlDecryption, defaultXmlDecryption);
-#endif
+ unresolved_algorithms.Add (urlC14N, defaultC14N);
+ unresolved_algorithms.Add (urlC14NWithComments, defaultC14NWithComments);
+ unresolved_algorithms.Add (urlBase64, defaultBase64);
+ unresolved_algorithms.Add (urlXPath, defaultXPath);
+ unresolved_algorithms.Add (urlXslt, defaultXslt);
+ unresolved_algorithms.Add (urlEnveloped, defaultEnveloped);
+ unresolved_algorithms.Add (urlExcC14N, defaultExcC14N);
+ unresolved_algorithms.Add (urlExcC14NWithComments, defaultExcC14NWithComments);
+ unresolved_algorithms.Add (urlXmlDecryption, defaultXmlDecryption);
+ algorithms.Add (urlSHA256, defaultSHA256);
+ // xmlenc does not include a definition for SHA384
+ algorithms.Add (urlSHA512, defaultSHA512);
+ algorithms.Add (urlHMACSHA256, defaultHMACSHA256);
+ algorithms.Add (urlHMACSHA384, defaultHMACSHA384);
+ algorithms.Add (urlHMACSHA512, defaultHMACSHA512);
+ algorithms.Add (urlHMACRIPEMD160, defaultHMACRIPEMD160);
// LAMESPEC: only documentated in ".NET Framework Security" book
- algorithms.Add (urlX509Data, defaultX509Data);
- algorithms.Add (urlKeyName, defaultKeyName);
- algorithms.Add (urlKeyValueDSA, defaultKeyValueDSA);
- algorithms.Add (urlKeyValueRSA, defaultKeyValueRSA);
- algorithms.Add (urlRetrievalMethod, defaultRetrievalMethod);
+ unresolved_algorithms.Add (urlX509Data, defaultX509Data);
+ unresolved_algorithms.Add (urlKeyName, defaultKeyName);
+ unresolved_algorithms.Add (urlKeyValueDSA, defaultKeyValueDSA);
+ unresolved_algorithms.Add (urlKeyValueRSA, defaultKeyValueRSA);
+ unresolved_algorithms.Add (urlRetrievalMethod, defaultRetrievalMethod);
+
+ // note: X.509 extensions aren't part of OID but names
+ unresolved_algorithms.Add (oidX509SubjectKeyIdentifier, nameX509SubjectKeyIdentifier);
+ unresolved_algorithms.Add (oidX509KeyUsage, nameX509KeyUsage);
+ unresolved_algorithms.Add (oidX509BasicConstraints, nameX509BasicConstraints);
+ unresolved_algorithms.Add (oidX509EnhancedKeyUsage, nameX509EnhancedKeyUsage);
+ // note: the default X.509Chain can also be created this way
+ unresolved_algorithms.Add (nameX509Chain, defaultX509Chain);
+#if NET_4_0
+ unresolved_algorithms.Add (nameAES_1, defaultAES_1);
+ unresolved_algorithms.Add (nameAES_2, defaultAES_1);
+ unresolved_algorithms.Add (nameAESManaged_1, defaultAESManaged);
+ unresolved_algorithms.Add (nameAESManaged_2, defaultAESManaged);
+
+ unresolved_algorithms.Add (nameECDiffieHellman_1, defaultECDiffieHellman);
+ unresolved_algorithms.Add (nameECDiffieHellman_2, defaultECDiffieHellman);
+ unresolved_algorithms.Add (nameECDiffieHellman_3, defaultECDiffieHellman);
+ unresolved_algorithms.Add (nameECDiffieHellman_4, defaultECDiffieHellman);
+
+ unresolved_algorithms.Add (nameECDsa_1, defaultECDsa);
+ unresolved_algorithms.Add (nameECDsa_2, defaultECDsa);
+ unresolved_algorithms.Add (nameECDsa_3, defaultECDsa);
+
+ unresolved_algorithms.Add (nameSHA1Cng, defaultSHA1Cng);
+ unresolved_algorithms.Add (nameSHA256Cng, defaultSHA256Cng);
+ unresolved_algorithms.Add (nameSHA256Provider, defaultSHA256Provider);
+ unresolved_algorithms.Add (nameSHA384Cng, defaultSHA384Cng);
+ unresolved_algorithms.Add (nameSHA384Provider, defaultSHA384Provider);
+ unresolved_algorithms.Add (nameSHA512Cng, defaultSHA512Cng);
+ unresolved_algorithms.Add (nameSHA512Provider, defaultSHA512Provider);
+#endif
+ Dictionary<string,string> oid = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
- 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 (defaultSHA1, oidSHA1);
+ oid.Add (nameSHA1, oidSHA1);
oid.Add (managedSHA1, oidSHA1);
oid.Add (nameSHA1b, oidSHA1);
oid.Add (nameSHA1c, oidSHA1);
- oid.Add (defaultMD5, oidMD5);
+ oid.Add (nameMD5, oidMD5);
oid.Add (nameMD5a, oidMD5);
oid.Add (nameMD5b, oidMD5);
- oid.Add (defaultSHA256, oidSHA256);
+ oid.Add (nameSHA256, oidSHA256);
oid.Add (nameSHA256a, oidSHA256);
oid.Add (nameSHA256c, oidSHA256);
- oid.Add (defaultSHA384, oidSHA384);
+ oid.Add (nameSHA384, oidSHA384);
oid.Add (nameSHA384a, oidSHA384);
oid.Add (nameSHA384c, oidSHA384);
- oid.Add (defaultSHA512, oidSHA512);
+ oid.Add (nameSHA512, oidSHA512);
oid.Add (nameSHA512a, oidSHA512);
oid.Add (nameSHA512c, oidSHA512);
+ oid.Add (nameRIPEMD160, oidRIPEMD160);
+ oid.Add (nameRIPEMD160a, oidRIPEMD160);
+ oid.Add (nameRIPEMD160c, oidRIPEMD160);
+
// surprise! documented in ".NET Framework Security" book
oid.Add (name3DESKeyWrap, oid3DESKeyWrap);
-#if NET_2_0
- oid.Add (nameRSAa, oidRSA);
- oid.Add (nameDSAa, oidDSA);
oid.Add (nameDESa, oidDES);
- oid.Add (name3DESa, oid3DES);
oid.Add (name3DESb, oid3DES);
oid.Add (nameRC2a, oidRC2);
-#endif
// Add/modify the config as specified by machine.config
string config = Environment.GetMachineConfigPath ();
- LoadConfig (config);
+ LoadConfig (config, algorithms, oid);
+
+ // update
+ CryptoConfig.algorithms = algorithms;
+ CryptoConfig.unresolved_algorithms = unresolved_algorithms;
+ CryptoConfig.oids = oid;
}
[FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
- private static void LoadConfig (string filename)
+ private static void LoadConfig (string filename, IDictionary<string,Type> algorithms, IDictionary<string,string> oid)
{
if (!File.Exists (filename))
return;
- SecurityParser sp = new SecurityParser ();
- StreamReader sr = new StreamReader (filename);
try {
- sp.LoadXml (sr.ReadToEnd ());
- }
- finally {
- sr.Close ();
- }
-
- try {
- SecurityElement root = sp.ToXml ();
- SecurityElement mscorlib = root.SearchForChildByTag ("mscorlib");
- if (mscorlib == null)
- return;
- SecurityElement cryptographySettings = mscorlib.SearchForChildByTag ("cryptographySettings");
- if (cryptographySettings == null)
- return;
-
- // algorithms
- SecurityElement cryptoNameMapping = cryptographySettings.SearchForChildByTag ("cryptoNameMapping");
- if (cryptoNameMapping != null) {
- SecurityElement cryptoClasses = cryptoNameMapping.SearchForChildByTag ("cryptoClasses");
- if (cryptoClasses != null) {
- foreach (SecurityElement nameEntry in cryptoNameMapping.Children) {
- if (nameEntry.Tag == "nameEntry") {
- string name = (string) nameEntry.Attributes ["name"];
- string clas = (string) nameEntry.Attributes ["class"];
- foreach (SecurityElement cryptoClass in cryptoClasses.Children) {
- string fullname = (string) cryptoClass.Attributes [clas];
- if (fullname != null) {
- if (algorithms.ContainsKey (name))
- algorithms.Remove (name);
- algorithms.Add (name, fullname);
- break;
- }
- }
- }
- }
- }
- }
-
- // oid
- SecurityElement oidMap = cryptographySettings.SearchForChildByTag ("oidMap");
- if (oidMap == null)
- return;
- foreach (SecurityElement oidEntry in oidMap.Children) {
- if (oidEntry.Tag == "oidEntry") {
- string oids = (string) oidEntry.Attributes ["OID"];
- if (oid.ContainsKey (oids))
- oid.Remove (oids);
- oid.Add (oids, oidEntry.Attributes ["name"]);
- }
+ using (TextReader reader = new StreamReader (filename)) {
+ CryptoHandler handler = new CryptoHandler (algorithms, oid);
+ SmallXmlParser parser = new SmallXmlParser ();
+ parser.Parse (reader, handler);
}
}
catch {
- // there's no error/warning in case the machine.config contains bad entries
}
}
}
[PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)]
- public static object CreateFromName (string name, object[] args)
+ public static object CreateFromName (string name, params object[] args)
{
if (name == null)
throw new ArgumentNullException ("name");
- if (algorithms == null) {
- lock (lockObject) {
+ lock (lockObject) {
+ if (algorithms == null) {
Initialize ();
}
}
try {
Type algoClass = null;
- string algo = (string) algorithms [name];
- // do we have an entry
- if (algo == null)
- algo = name;
- algoClass = Type.GetType (algo);
+ if (!algorithms.TryGetValue (name, out algoClass)) {
+ string algo = null;
+ if (!unresolved_algorithms.TryGetValue (name, out algo))
+ algo = name;
+ algoClass = Type.GetType (algo);
+ }
+ if (algoClass == null)
+ return null;
// call the constructor for the type
return Activator.CreateInstance (algoClass, args);
}
}
}
- // encode (7bits array) number greater than 127
- private static byte[] EncodeLongNumber (long x)
+ public static string MapNameToOID (string name)
{
- // for MS BCL compatibility
- // comment next two lines to remove restriction
- if ((x > Int32.MaxValue) || (x < Int32.MinValue))
- throw new OverflowException (Locale.GetText ("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++;
+ if (name == null)
+ throw new ArgumentNullException ("name");
+
+ lock (lockObject) {
+ if (oids == null) {
+ Initialize ();
+ }
}
- 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);
+
+ string result = null;
+ oids.TryGetValue (name, out result);
+ return result;
+ }
+
+#if NET_4_0
+ [MonoLimitation ("nothing is FIPS certified so it never make sense to restrict to this (empty) subset")]
+ public static bool AllowOnlyFipsAlgorithms {
+ get { return false; }
+ }
+
+ public static void AddAlgorithm (Type algorithm, params string[] names)
+ {
+ if (algorithm == null)
+ throw new ArgumentNullException ("algorithm");
+ if (names == null)
+ throw new ArgumentNullException ("names");
+
+ foreach (string name in names) {
+ if (String.IsNullOrWhiteSpace (name))
+ throw new ArithmeticException ("names");
+ algorithms [name] = algorithm;
}
- return num;
}
- public static byte[] EncodeOID (string str)
+ public static void AddOID (string oid, params string[] names)
{
- char[] delim = { '.' };
- string[] parts = str.Split (delim);
- // according to X.208 n is always at least 2
- if (parts.Length < 2) {
- throw new CryptographicUnexpectedOperationException (
- Locale.GetText ("OID must have at least two parts"));
+ if (oid == null)
+ throw new ArgumentNullException ("oid");
+ if (names == null)
+ throw new ArgumentNullException ("names");
+
+ foreach (string name in names) {
+ if (String.IsNullOrWhiteSpace (name))
+ throw new ArithmeticException ("names");
+ oids [oid] = name;
}
+ }
+#endif
- // 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);
+ class CryptoHandler: SmallXmlParser.IContentHandler {
+
+ IDictionary<string,Type> algorithms;
+ IDictionary<string,string> oid;
+ Dictionary<string,string> names;
+ Dictionary<string,string> classnames;
+ int level;
+
+ public CryptoHandler (IDictionary<string,Type> algorithms, IDictionary<string,string> oid)
+ {
+ this.algorithms = algorithms;
+ this.oid = oid;
+ // temporary tables to reconstruct algorithms
+ names = new Dictionary<string,string> ();
+ classnames = new Dictionary<string,string> ();
}
- catch {
- throw new CryptographicUnexpectedOperationException (
- Locale.GetText ("Invalid OID"));
+
+ public void OnStartParsing (SmallXmlParser parser)
+ {
+ // don't care
}
- int j = 3;
- for (int i = 2; i < parts.Length; i++) {
- long x = Convert.ToInt64 (parts [i]);
- if (x > 0x7F) {
- byte[] num = EncodeLongNumber (x);
- Buffer.BlockCopy (num, 0, oid, j, num.Length);
- j += num.Length;
+
+ public void OnEndParsing (SmallXmlParser parser)
+ {
+ foreach (var kpv in names) {
+ try {
+ algorithms [kpv.Key] = Type.GetType (classnames [kpv.Value]);
+ }
+ catch {
+ }
}
- else
- oid[j++] = Convert.ToByte (x);
+ // matching is done, data no more required
+ names.Clear ();
+ classnames.Clear ();
}
- 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 (
- Locale.GetText ("OID > 127 bytes"));
- // comment exception and uncomment next 3 lines to remove restriction
- //byte[] num = EncodeLongNumber (j);
- //Buffer.BlockCopy (num, 0, oid, j, num.Length);
- //k = num.Length + 1;
+ private string Get (SmallXmlParser.IAttrList attrs, string name)
+ {
+ for (int i = 0; i < attrs.Names.Length; i++) {
+ if (attrs.Names[i] == name)
+ return attrs.Values[i];
+ }
+ return String.Empty;
}
- else
- oid2 [1] = Convert.ToByte (j - 2);
-
- Buffer.BlockCopy (oid, k, oid2, k, j - k);
- return oid2;
- }
- public static string MapNameToOID (string name)
- {
- if (name == null)
- throw new ArgumentNullException ("name");
+ public void OnStartElement (string name, SmallXmlParser.IAttrList attrs)
+ {
+ switch (level) {
+ case 0:
+ if (name == "configuration")
+ level++;
+ break;
+ case 1:
+ if (name == "mscorlib")
+ level++;
+ break;
+ case 2:
+ if (name == "cryptographySettings")
+ level++;
+ break;
+ case 3:
+ if (name == "oidMap")
+ level++;
+ else if (name == "cryptoNameMapping")
+ level++;
+ break;
+ case 4:
+ if (name == "oidEntry") {
+ oid [Get (attrs, "name")] = Get (attrs, "OID");
+ } else if (name == "nameEntry") {
+ names [Get (attrs, "name")] = Get (attrs, "class");
+ } else if (name == "cryptoClasses") {
+ level++;
+ }
+ break;
+ case 5:
+ if (name == "cryptoClass")
+ classnames [attrs.Names[0]] = attrs.Values[0];
+ break;
+ }
+ }
- if (oid == null) {
- lock (lockObject) {
- Initialize ();
+ public void OnEndElement (string name)
+ {
+ // parser will make sure the XML structure is respected
+ switch (level) {
+ case 1:
+ if (name == "configuration")
+ level--;
+ break;
+ case 2:
+ if (name == "mscorlib")
+ level--;
+ break;
+ case 3:
+ if (name == "cryptographySettings")
+ level--;
+ break;
+ case 4:
+ if ((name == "oidMap") || (name == "cryptoNameMapping"))
+ level--;
+ break;
+ case 5:
+ if (name == "cryptoClasses")
+ level--;
+ break;
}
}
- return (string)oid [name];
+ public void OnProcessingInstruction (string name, string text)
+ {
+ // don't care
+ }
+
+ public void OnChars (string text)
+ {
+ // don't care
+ }
+
+ public void OnIgnorableWhitespace (string text)
+ {
+ // don't care
+ }
}
}
-
}
+
+#endif
+