public static object?CreateFromName(string name, params object?[]?args) { ArgumentNullException.ThrowIfNull(name); #if BROWSER switch (name) { #pragma warning disable SYSLIB0021 // Obsolete: derived cryptographic types // hardcode mapping for SHA* and HMAC* algorithm names from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=net-5.0#remarks case "SHA": case "SHA1": case "System.Security.Cryptography.SHA1": return(new SHA1Managed()); case "SHA256": case "SHA-256": case "System.Security.Cryptography.SHA256": return(new SHA256Managed()); case "SHA384": case "SHA-384": case "System.Security.Cryptography.SHA384": return(new SHA384Managed()); case "SHA512": case "SHA-512": case "System.Security.Cryptography.SHA512": return(new SHA512Managed()); #pragma warning restore SYSLIB0021 case "System.Security.Cryptography.HMAC": case "HMACSHA1": case "System.Security.Cryptography.HMACSHA1": case "System.Security.Cryptography.KeyedHashAlgorithm": return(new HMACSHA1()); case "HMACSHA256": case "System.Security.Cryptography.HMACSHA256": return(new HMACSHA256()); case "HMACSHA384": case "System.Security.Cryptography.HMACSHA384": return(new HMACSHA384()); case "HMACSHA512": case "System.Security.Cryptography.HMACSHA512": return(new HMACSHA512()); #pragma warning disable SYSLIB0021 // Obsolete: derived cryptographic types case "AES": case "System.Security.Cryptography.AesCryptoServiceProvider": return(new AesCryptoServiceProvider()); case "AesManaged": case "System.Security.Cryptography.AesManaged": return(new AesManaged()); case "Rijndael": case "System.Security.Cryptography.Rijndael": #pragma warning disable SYSLIB0022 // Rijndael types are obsolete return(new RijndaelManaged()); #pragma warning restore SYSLIB0022 #pragma warning restore SYSLIB0021 } return(null); #else // Check to see if we have an application defined mapping appNameHT.TryGetValue(name, out Type? retvalType); // We allow the default table to Types and Strings // Types get used for types in .Algorithms assembly. // strings get used for delay-loaded stuff in other assemblies such as .Csp. if (retvalType == null && DefaultNameHT.TryGetValue(name, out object?retvalObj)) { retvalType = retvalObj as Type; if (retvalType == null) { if (retvalObj is string retvalString) { retvalType = Type.GetType(retvalString, false, false); if (retvalType != null && !retvalType.IsVisible) { retvalType = null; } if (retvalType != null) { // Add entry to the appNameHT, which makes subsequent calls much faster. appNameHT[name] = retvalType; } } else { Debug.Fail("Unsupported Dictionary value:" + retvalObj.ToString()); } } } // Special case asking for "ECDsa" since the default map from .NET Framework uses // a Windows-only type. if (retvalType == null && (args == null || args.Length == 1) && name == ECDsaIdentifier) { return(ECDsa.Create()); } // Maybe they gave us a classname. if (retvalType == null) { retvalType = Type.GetType(name, false, false); if (retvalType != null && !retvalType.IsVisible) { retvalType = null; } } // Still null? Then we didn't find it. if (retvalType == null) { return(null); } // Locate all constructors. MethodBase[] cons = retvalType.GetConstructors(ConstructorDefault); if (cons == null) { return(null); } if (args == null) { args = Array.Empty <object>(); } List <MethodBase> candidates = new List <MethodBase>(); for (int i = 0; i < cons.Length; i++) { MethodBase con = cons[i]; if (con.GetParameters().Length == args.Length) { candidates.Add(con); } } if (candidates.Count == 0) { return(null); } cons = candidates.ToArray(); // Bind to matching ctor. ConstructorInfo?rci = Type.DefaultBinder.BindToMethod( ConstructorDefault, cons, ref args, null, null, null, out object?state) as ConstructorInfo; // Check for ctor we don't like (non-existent, delegate or decorated with declarative linktime demand). if (rci == null || typeof(Delegate).IsAssignableFrom(rci.DeclaringType)) { return(null); } // Ctor invoke and allocation. object retval = rci.Invoke(ConstructorDefault, Type.DefaultBinder, args, null); // Reset any parameter re-ordering performed by the binder. if (state != null) { Type.DefaultBinder.ReorderArgumentArray(ref args, state); } return(retval); #endif }
public static object?CreateFromName(string name, params object?[]?args) { if (name == null) { throw new ArgumentNullException(nameof(name)); } // Check to see if we have an application defined mapping appNameHT.TryGetValue(name, out Type? retvalType); // We allow the default table to Types and Strings // Types get used for types in .Algorithms assembly. // strings get used for delay-loaded stuff in other assemblies such as .Csp. if (retvalType == null && DefaultNameHT.TryGetValue(name, out object?retvalObj)) { retvalType = retvalObj as Type; if (retvalType == null) { if (retvalObj is string retvalString) { retvalType = Type.GetType(retvalString, false, false); if (retvalType != null && !retvalType.IsVisible) { retvalType = null; } if (retvalType != null) { // Add entry to the appNameHT, which makes subsequent calls much faster. appNameHT[name] = retvalType; } } else { Debug.Fail("Unsupported Dictionary value:" + retvalObj.ToString()); } } } // Special case asking for "ECDsa" since the default map from .NET Framework uses // a Windows-only type. if (retvalType == null && (args == null || args.Length == 1) && name == ECDsaIdentifier) { return(ECDsa.Create()); } // Maybe they gave us a classname. if (retvalType == null) { retvalType = Type.GetType(name, false, false); if (retvalType != null && !retvalType.IsVisible) { retvalType = null; } } // Still null? Then we didn't find it. if (retvalType == null) { return(null); } // Locate all constructors. MethodBase[] cons = retvalType.GetConstructors(ConstructorDefault); if (cons == null) { return(null); } if (args == null) { args = Array.Empty <object>(); } List <MethodBase> candidates = new List <MethodBase>(); for (int i = 0; i < cons.Length; i++) { MethodBase con = cons[i]; if (con.GetParameters().Length == args.Length) { candidates.Add(con); } } if (candidates.Count == 0) { return(null); } cons = candidates.ToArray(); // Bind to matching ctor. ConstructorInfo?rci = Type.DefaultBinder.BindToMethod( ConstructorDefault, cons, ref args, null, null, null, out object?state) as ConstructorInfo; // Check for ctor we don't like (non-existent, delegate or decorated with declarative linktime demand). if (rci == null || typeof(Delegate).IsAssignableFrom(rci.DeclaringType)) { return(null); } // Ctor invoke and allocation. object retval = rci.Invoke(ConstructorDefault, Type.DefaultBinder, args, null); // Reset any parameter re-ordering performed by the binder. if (state != null) { Type.DefaultBinder.ReorderArgumentArray(ref args, state); } return(retval); }
/// <summary> /// Read the x and y components of the public key /// </summary> private static void ReadPublicKey(XPathNavigator navigator, ref ECParameters parameters) { Contract.Requires(navigator != null); if (navigator.NamespaceURI != Namespace) { throw new ArgumentException(SR.GetString(SR.Cryptography_UnexpectedXmlNamespace, navigator.NamespaceURI, Namespace)); } if (navigator.Name != PublicKeyRoot) { throw new ArgumentException(SR.GetString(SR.Cryptography_MissingPublicKey)); } // First get the x parameter if (!navigator.MoveToFirstChild() || navigator.Name != XElement) { throw new ArgumentException(SR.GetString(SR.Cryptography_MissingPublicKey)); } if (!navigator.MoveToFirstAttribute() || navigator.Name != ValueAttribute || String.IsNullOrEmpty(navigator.Value)) { throw new ArgumentException(SR.GetString(SR.Cryptography_MissingPublicKey)); } BigInteger x = BigInteger.Parse(navigator.Value, CultureInfo.InvariantCulture); navigator.MoveToParent(); // Then the y parameter if (!navigator.MoveToNext(XPathNodeType.Element) || navigator.Name != YElement) { throw new ArgumentException(SR.GetString(SR.Cryptography_MissingPublicKey)); } if (!navigator.MoveToFirstAttribute() || navigator.Name != ValueAttribute || String.IsNullOrEmpty(navigator.Value)) { throw new ArgumentException(SR.GetString(SR.Cryptography_MissingPublicKey)); } BigInteger y = BigInteger.Parse(navigator.Value, CultureInfo.InvariantCulture); byte[] xBytes = x.ToByteArray(); byte[] yBytes = y.ToByteArray(); int xLen = xBytes.Length; int yLen = yBytes.Length; // If the last byte of X is 0x00 that's a padding byte by BigInteger to indicate X is // a positive number with the highest bit in the most significant byte set. We can't count // that in the length of the number. if (xLen > 0 && xBytes[xLen - 1] == 0) { xLen--; } // Ditto for Y. if (yLen > 0 && yBytes[yLen - 1] == 0) { yLen--; } // Q.X and Q.Y have to be the same length. They ultimately have to be the right length for the curve, // but that requires more knowledge than we have. So we'll ask the system. If it doesn't know, just make // them match each other. int requiredLength = Math.Max(xLen, yLen); try { using (ECDsa ecdsa = ECDsa.Create(parameters.Curve)) { // Convert the bit value of keysize to a byte value. // EC curves can have non-mod-8 keysizes (e.g. 521), so the +7 is really necessary. int curveLength = (ecdsa.KeySize + 7) / 8; // We could just use this answer, but if the user has formatted the input to be // too long, maybe they know something we don't. requiredLength = Math.Max(requiredLength, curveLength); } } catch (ArgumentException) { /* Curve had invalid data, like an empty OID */ } catch (CryptographicException) { /* The system failed to generate a key for the curve */ } catch (NotSupportedException) { /* An unknown curve type was requested */ } // There is a chance that the curve is known to Windows but not allowed for ECDH // (curve25519 is known to be in this state). Since RFC4050 is officially only // concerned with ECDSA, and the only known example of this problem does not have // an OID, it is not worth trying to generate the curve under ECDH as a fallback. // Since BigInteger does Little Endian and Array.Resize maintains indexes when growing, // just Array.Resize, then Array.Reverse. We could optimize this to be 1N instead of 2N, // but this isn't a very hot codepath, so use tried-and-true methods. Array.Resize(ref xBytes, requiredLength); Array.Resize(ref yBytes, requiredLength); Array.Reverse(xBytes); Array.Reverse(yBytes); parameters.Q.X = xBytes; parameters.Q.Y = yBytes; }