-
-
Save januszn/e42f91e23db3b977e9e41786aa9413d4 to your computer and use it in GitHub Desktop.
Source for CngLightup.cs from Microsoft source servers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==++== | |
// | |
// Copyright (c) Microsoft Corporation. All rights reserved. | |
// | |
// ==--== | |
// Supported preprocessor declarations: | |
// | |
// CNG_LIGHTUP_NO_SYSTEM_CORE | |
// Indicates that this file is being processed from a context that cannot access System.Core. | |
// * The assembly must be built with <GenerateAssemblyRefs>true</GenerateAssemblyRefs> | |
// * The ECDSA methods are not available | |
// There are cases where we have multiple assemblies that are going to import this file and | |
// if they are going to also have InternalsVisibleTo between them, there will be a compiler warning | |
// that the type is found both in the source and in a referenced assembly. The compiler will prefer | |
// the version of the type defined in the source | |
// | |
// In order to disable the warning for this type we are disabling this warning for this entire file. | |
#pragma warning disable 436 | |
using System.Diagnostics; | |
using System.Reflection; | |
using System.Security.Cryptography.X509Certificates; | |
namespace System.Security.Cryptography | |
{ | |
internal static partial class CngLightup | |
{ | |
private const string DsaOid = "1.2.840.10040.4.1"; | |
private const string RsaOid = "1.2.840.113549.1.1.1"; | |
private const string HashAlgorithmNameTypeName = "System.Security.Cryptography.HashAlgorithmName"; | |
private const string RSASignaturePaddingTypeName = "System.Security.Cryptography.RSASignaturePadding"; | |
private const string RSAEncryptionPaddingTypeName = "System.Security.Cryptography.RSAEncryptionPadding"; | |
private const string RSACngTypeName = "System.Security.Cryptography.RSACng"; | |
private const string DSACngTypeName = "System.Security.Cryptography.DSACng"; | |
// If 4.6 is guaranteed as a baseline, then these field references should become typeof() | |
// expressions, and the methods that consume them can get significantly easier. | |
private static readonly Type s_hashAlgorithmNameType = | |
typeof(object).Assembly.GetType(HashAlgorithmNameTypeName, false); | |
private static readonly Type s_rsaSignaturePaddingType = | |
typeof(object).Assembly.GetType(RSASignaturePaddingTypeName, false); | |
private static readonly Type s_rsaEncryptionPaddingType = | |
typeof(object).Assembly.GetType(RSAEncryptionPaddingTypeName, false); | |
private static readonly object s_pkcs1SignaturePadding = | |
s_rsaSignaturePaddingType == null ? null : | |
s_rsaSignaturePaddingType.GetProperty("Pkcs1", BindingFlags.Static | BindingFlags.Public).GetValue(null); | |
private static readonly object s_pkcs1EncryptionPadding = | |
s_rsaEncryptionPaddingType == null ? null : | |
s_rsaEncryptionPaddingType.GetProperty("Pkcs1", BindingFlags.Static | BindingFlags.Public).GetValue(null); | |
private static readonly object s_oaepSha1EncryptionPadding = | |
s_rsaEncryptionPaddingType == null ? null : | |
s_rsaEncryptionPaddingType.GetProperty("OaepSHA1", BindingFlags.Static | BindingFlags.Public).GetValue(null); | |
private static readonly Lazy<bool> s_preferRsaCng = new Lazy<bool>(DetectRsaCngSupport); | |
private static volatile Func<X509Certificate2, DSA> s_getDsaPublicKey; | |
private static volatile Func<X509Certificate2, DSA> s_getDsaPrivateKey; | |
private static volatile Func<X509Certificate2, RSA> s_getRsaPublicKey; | |
private static volatile Func<X509Certificate2, RSA> s_getRsaPrivateKey; | |
private static volatile Func<RSA, byte[], string, byte[]> s_rsaPkcs1SignMethod; | |
private static volatile Func<RSA, byte[], byte[], string, bool> s_rsaPkcs1VerifyMethod; | |
private static volatile Func<RSA, byte[], byte[]> s_rsaPkcs1EncryptMethod; | |
private static volatile Func<RSA, byte[], byte[]> s_rsaPkcs1DecryptMethod; | |
private static volatile Func<RSA, byte[], byte[]> s_rsaOaepSha1EncryptMethod; | |
private static volatile Func<RSA, byte[], byte[]> s_rsaOaepSha1DecryptMethod; | |
#if !CNG_LIGHTUP_NO_SYSTEM_CORE | |
private static volatile Func<X509Certificate2, ECDsa> s_getECDsaPublicKey; | |
private static volatile Func<X509Certificate2, ECDsa> s_getECDsaPrivateKey; | |
#endif | |
internal static RSA GetRSAPublicKey(X509Certificate2 cert) | |
{ | |
if (s_getRsaPublicKey == null) | |
{ | |
if (s_preferRsaCng.Value) | |
{ | |
s_getRsaPublicKey = | |
BindCoreDelegate<RSA>("RSA", isPublic: true) ?? | |
BindGetCapiPublicKey<RSA, RSACryptoServiceProvider>(RsaOid); | |
} | |
else | |
{ | |
s_getRsaPublicKey = BindGetCapiPublicKey<RSA, RSACryptoServiceProvider>(RsaOid); | |
} | |
} | |
return s_getRsaPublicKey(cert); | |
} | |
internal static RSA GetRSAPrivateKey(X509Certificate2 cert) | |
{ | |
if (s_getRsaPrivateKey == null) | |
{ | |
if (s_preferRsaCng.Value) | |
{ | |
s_getRsaPrivateKey = | |
BindCoreDelegate<RSA>("RSA", isPublic: false) ?? | |
BindGetCapiPrivateKey<RSA>(RsaOid, csp => new RSACryptoServiceProvider(csp)); | |
} | |
else | |
{ | |
s_getRsaPrivateKey = BindGetCapiPrivateKey<RSA>(RsaOid, csp => new RSACryptoServiceProvider(csp)); | |
} | |
} | |
return s_getRsaPrivateKey(cert); | |
} | |
internal static DSA GetDSAPublicKey(X509Certificate2 cert) | |
{ | |
if (s_getDsaPublicKey == null) | |
{ | |
s_getDsaPublicKey = | |
BindCoreDelegate<DSA>("DSA", isPublic: true) ?? | |
BindGetCapiPublicKey<DSA, DSACryptoServiceProvider>(DsaOid); | |
} | |
return s_getDsaPublicKey(cert); | |
} | |
internal static DSA GetDSAPrivateKey(X509Certificate2 cert) | |
{ | |
if (s_getDsaPrivateKey == null) | |
{ | |
s_getDsaPrivateKey = | |
BindCoreDelegate<DSA>("DSA", isPublic: false) ?? | |
BindGetCapiPrivateKey<DSA>(DsaOid, csp => new DSACryptoServiceProvider(csp)); | |
} | |
return s_getDsaPrivateKey(cert); | |
} | |
#if !CNG_LIGHTUP_NO_SYSTEM_CORE | |
internal static ECDsa GetECDsaPublicKey(X509Certificate2 cert) | |
{ | |
// ECDsa has no fallback mode, it was only available via the System.Core extension method. | |
// With this lightup path, GetECDsaPublicKey can return null for an ECDSA certificate, just because | |
// System.Core is too old. | |
if (s_getECDsaPublicKey == null) | |
{ | |
s_getECDsaPublicKey = BindCoreDelegate<ECDsa>("ECDsa", isPublic: true) ?? (c => null); | |
} | |
return s_getECDsaPublicKey(cert); | |
} | |
internal static ECDsa GetECDsaPrivateKey(X509Certificate2 cert) | |
{ | |
// ECDsa has no fallback mode, it was only available via the System.Core extension method. | |
// With this lightup path, GetECDsaPrivateKey can return null for an ECDSA certificate, just because | |
// System.Core is too old. | |
if (s_getECDsaPrivateKey == null) | |
{ | |
s_getECDsaPrivateKey = BindCoreDelegate<ECDsa>("ECDsa", isPublic: false) ?? (c => null); | |
} | |
return s_getECDsaPrivateKey(cert); | |
} | |
#endif | |
// When 4.6 is guaranteed as the minimum patch baseline, this method should be moved to a direct | |
// call to RSA.SignData. Or, even better, removed and just used inline. | |
internal static byte[] Pkcs1SignData(RSA rsa, byte[] data, string hashAlgorithmName) | |
{ | |
// Because RSACryptoServiceProvider existed in 4.5, but RSACng didn't, and RSA's SignData | |
// method requires types that aren't in 4.5, try RSACryptoServiceProvider's way first. | |
RSACryptoServiceProvider rsaCsp = rsa as RSACryptoServiceProvider; | |
if (rsaCsp != null) | |
{ | |
return rsaCsp.SignData(data, hashAlgorithmName); | |
} | |
if (s_rsaPkcs1SignMethod == null) | |
{ | |
// [X] SignData(byte[] data, HashAlgorithmName hashAlgorithmName, RSASignaturePadding padding) | |
// [ ] SignData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithmName, RSASignaturePadding padding) | |
// [ ] SignData(Stream data, HashAlgorithmName hashAlgorithmName, RSASignaturePadding padding) | |
Debug.Assert(s_hashAlgorithmNameType != null); | |
Debug.Assert(s_rsaSignaturePaddingType != null); | |
Debug.Assert(s_pkcs1SignaturePadding != null); | |
Type[] signatureTypes = { typeof(byte[]), s_hashAlgorithmNameType, s_rsaSignaturePaddingType }; | |
MethodInfo signDataMethod = typeof(RSA).GetMethod( | |
"SignData", | |
BindingFlags.Public | BindingFlags.Instance, | |
null, | |
signatureTypes, | |
null); | |
Debug.Assert(signDataMethod != null, "Cannot find RSA.SignData(byte[], HashAlgorithmName, RSASignaturePadding)"); | |
// Because the HashAlgorithmName and RSASignaturePadding types aren't guaranteed available at | |
// assembly time (though they really need to be if the runtime makes it here...) the delegate binding | |
// is a bit harder than normal. | |
Type delegateType = typeof(Func<,,,,>).MakeGenericType( | |
typeof(RSA), | |
typeof(byte[]), | |
s_hashAlgorithmNameType, | |
s_rsaSignaturePaddingType, | |
typeof(byte[])); | |
Delegate openDelegate = Delegate.CreateDelegate(delegateType, signDataMethod); | |
s_rsaPkcs1SignMethod = | |
(delegateRsa, delegateData, delegateAlgorithm) => | |
{ | |
object hashAlgorithmNameObject = Activator.CreateInstance(s_hashAlgorithmNameType, delegateAlgorithm); | |
object[] args = { delegateRsa, delegateData, hashAlgorithmNameObject, s_pkcs1SignaturePadding }; | |
return (byte[])openDelegate.DynamicInvoke(args); | |
}; | |
} | |
Debug.Assert(s_rsaPkcs1SignMethod != null); | |
return s_rsaPkcs1SignMethod(rsa, data, hashAlgorithmName); | |
} | |
internal static bool Pkcs1VerifyData(RSA rsa, byte[] data, byte[] signature, string hashAlgorithmName) | |
{ | |
// Because RSACryptoServiceProvider existed in 4.5, but RSACng didn't, and RSA's SignData | |
// method requires types that aren't in 4.5, try RSACryptoServiceProvider's way first. | |
RSACryptoServiceProvider rsaCsp = rsa as RSACryptoServiceProvider; | |
if (rsaCsp != null) | |
{ | |
return rsaCsp.VerifyData(data, hashAlgorithmName, signature); | |
} | |
if (s_rsaPkcs1VerifyMethod == null) | |
{ | |
// [X] VerifyData(byte[] data, byte[] signature, HashAlgorithmName hashAlgorithmName, RSASignaturePadding padding) | |
// [ ] VerifyData(byte[] data, int offset, int count, byte[] signature, HashAlgorithmName hashAlgorithmName, RSASignaturePadding padding) | |
// [ ] VerifyData(Stream data, byte[] signature, HashAlgorithmName hashAlgorithmName, RSASignaturePadding padding) | |
Debug.Assert(s_hashAlgorithmNameType != null); | |
Debug.Assert(s_rsaSignaturePaddingType != null); | |
Debug.Assert(s_pkcs1SignaturePadding != null); | |
Type[] signatureTypes = { typeof(byte[]), typeof(byte[]), s_hashAlgorithmNameType, s_rsaSignaturePaddingType }; | |
MethodInfo verifyDataMethod = typeof(RSA).GetMethod( | |
"VerifyData", | |
BindingFlags.Public | BindingFlags.Instance, | |
null, | |
signatureTypes, | |
null); | |
Debug.Assert( | |
verifyDataMethod != null, | |
"Cannot find RSA.VerifyData(byte[], byte[], HashAlgorithmName, RSASignaturePadding)"); | |
// Because the HashAlgorithmName and RSASignaturePadding types aren't guaranteed available at | |
// assembly time (though they really need to be if the runtime makes it here...) the delegate binding | |
// is a bit harder than normal. | |
Type delegateType = typeof(Func<,,,,,>).MakeGenericType( | |
typeof(RSA), | |
typeof(byte[]), | |
typeof(byte[]), | |
s_hashAlgorithmNameType, | |
s_rsaSignaturePaddingType, | |
typeof(bool)); | |
Delegate openDelegate = Delegate.CreateDelegate(delegateType, verifyDataMethod); | |
s_rsaPkcs1VerifyMethod = | |
(delegateRsa, delegateData, delegateSignature, delegateAlgorithm) => | |
{ | |
object hashAlgorithmNameObject = Activator.CreateInstance(s_hashAlgorithmNameType, delegateAlgorithm); | |
object[] args = | |
{ | |
delegateRsa, | |
delegateData, | |
delegateSignature, | |
hashAlgorithmNameObject, | |
s_pkcs1SignaturePadding | |
}; | |
return (bool)openDelegate.DynamicInvoke(args); | |
}; | |
} | |
Debug.Assert(s_rsaPkcs1VerifyMethod != null); | |
return s_rsaPkcs1VerifyMethod(rsa, data, signature, hashAlgorithmName); | |
} | |
internal static byte[] Pkcs1Encrypt(RSA rsa, byte[] data) | |
{ | |
// Because RSACryptoServiceProvider existed in 4.5, but RSACng didn't, and RSA's Encrypt | |
// method requires types that aren't in 4.5, try RSACryptoServiceProvider's way first. | |
RSACryptoServiceProvider rsaCsp = rsa as RSACryptoServiceProvider; | |
if (rsaCsp != null) | |
{ | |
return rsaCsp.Encrypt(data, false); | |
} | |
if (s_rsaPkcs1EncryptMethod == null) | |
{ | |
Debug.Assert(s_pkcs1EncryptionPadding != null); | |
Delegate openDelegate = BindRsaCryptMethod("Encrypt"); | |
s_rsaPkcs1EncryptMethod = | |
(delegateRsa, delegateData) => | |
{ | |
return (byte[])openDelegate.DynamicInvoke(delegateRsa, delegateData, s_pkcs1EncryptionPadding); | |
}; | |
} | |
Debug.Assert(s_rsaPkcs1EncryptMethod != null); | |
return s_rsaPkcs1EncryptMethod(rsa, data); | |
} | |
internal static byte[] Pkcs1Decrypt(RSA rsa, byte[] data) | |
{ | |
// Because RSACryptoServiceProvider existed in 4.5, but RSACng didn't, and RSA's Decrypt | |
// method requires types that aren't in 4.5, try RSACryptoServiceProvider's way first. | |
RSACryptoServiceProvider rsaCsp = rsa as RSACryptoServiceProvider; | |
if (rsaCsp != null) | |
{ | |
return rsaCsp.Decrypt(data, false); | |
} | |
if (s_rsaPkcs1DecryptMethod == null) | |
{ | |
Debug.Assert(s_pkcs1EncryptionPadding != null); | |
Delegate openDelegate = BindRsaCryptMethod("Decrypt"); | |
s_rsaPkcs1DecryptMethod = | |
(delegateRsa, delegateData) => | |
{ | |
return (byte[])openDelegate.DynamicInvoke(delegateRsa, delegateData, s_pkcs1EncryptionPadding); | |
}; | |
} | |
Debug.Assert(s_rsaPkcs1DecryptMethod != null); | |
return s_rsaPkcs1DecryptMethod(rsa, data); | |
} | |
internal static byte[] OaepSha1Encrypt(RSA rsa, byte[] data) | |
{ | |
// Because RSACryptoServiceProvider existed in 4.5, but RSACng didn't, and RSA's Encrypt | |
// method requires types that aren't in 4.5, try RSACryptoServiceProvider's way first. | |
RSACryptoServiceProvider rsaCsp = rsa as RSACryptoServiceProvider; | |
if (rsaCsp != null) | |
{ | |
return rsaCsp.Encrypt(data, true); | |
} | |
if (s_rsaOaepSha1EncryptMethod == null) | |
{ | |
Debug.Assert(s_oaepSha1EncryptionPadding != null); | |
Delegate openDelegate = BindRsaCryptMethod("Encrypt"); | |
s_rsaOaepSha1EncryptMethod = | |
(delegateRsa, delegateData) => | |
{ | |
return (byte[])openDelegate.DynamicInvoke(delegateRsa, delegateData, s_oaepSha1EncryptionPadding); | |
}; | |
} | |
Debug.Assert(s_rsaOaepSha1EncryptMethod != null); | |
return s_rsaOaepSha1EncryptMethod(rsa, data); | |
} | |
internal static byte[] OaepSha1Decrypt(RSA rsa, byte[] data) | |
{ | |
// Because RSACryptoServiceProvider existed in 4.5, but RSACng didn't, and RSA's Decrypt | |
// method requires types that aren't in 4.5, try RSACryptoServiceProvider's way first. | |
RSACryptoServiceProvider rsaCsp = rsa as RSACryptoServiceProvider; | |
if (rsaCsp != null) | |
{ | |
return rsaCsp.Decrypt(data, true); | |
} | |
if (s_rsaOaepSha1DecryptMethod == null) | |
{ | |
Debug.Assert(s_oaepSha1EncryptionPadding != null); | |
Delegate openDelegate = BindRsaCryptMethod("Decrypt"); | |
s_rsaOaepSha1DecryptMethod = | |
(delegateRsa, delegateData) => | |
{ | |
return (byte[])openDelegate.DynamicInvoke(delegateRsa, delegateData, s_oaepSha1EncryptionPadding); | |
}; | |
} | |
Debug.Assert(s_rsaOaepSha1DecryptMethod != null); | |
return s_rsaOaepSha1DecryptMethod(rsa, data); | |
} | |
private static Delegate BindRsaCryptMethod(string methodName) | |
{ | |
Debug.Assert(s_rsaEncryptionPaddingType != null); | |
Type[] signatureTypes = { typeof(byte[]), s_rsaEncryptionPaddingType }; | |
MethodInfo cryptMethod = typeof(RSA).GetMethod( | |
methodName, | |
BindingFlags.Public | BindingFlags.Instance, | |
null, | |
signatureTypes, | |
null); | |
Debug.Assert(cryptMethod != null, "Cannot find RSA." + methodName + "(byte[], RSAEncryptionPadding)"); | |
// Because the RSAEncryptionPadding type isn't guaranteed available at assembly time | |
// (though they really need to be if the runtime makes it here...) the delegate binding | |
// is a bit harder than normal. | |
Type delegateType = typeof(Func<,,,>).MakeGenericType( | |
typeof(RSA), | |
typeof(byte[]), | |
s_rsaEncryptionPaddingType, | |
typeof(byte[])); | |
return Delegate.CreateDelegate(delegateType, cryptMethod); | |
} | |
private static bool DetectRsaCngSupport() | |
{ | |
Type rsaCng = GetSystemCoreType(RSACngTypeName, throwOnError: false); | |
// If the type doesn't exist, there can't be good support for it. | |
// (System.Core < 4.6) | |
if (rsaCng == null) | |
{ | |
return false; | |
} | |
Type dsaCng = GetSystemCoreType(DSACngTypeName, throwOnError: false); | |
// The original implementation of RSACng returned shared objects in the CAPI fallback | |
// pathway. That behavior is hard to test for, since CNG can load all CAPI software keys. | |
// But, since DSACng was added in 4.6.2, and RSACng better guarantees uniqueness in 4.6.2 | |
// use that coincidence as a compatibility test. | |
// | |
// If DSACng is missing, RSACng usage might lead to attempting to use Disposed objects | |
// (System.Core < 4.6.2) | |
if (dsaCng == null) | |
{ | |
return false; | |
} | |
// Create an RSACng instance and send it to RSAPKCS1KeyExchangeFormatter. It was adjusted to | |
// be CNG-capable for 4.6.2; and other types in that library also are up-to-date. | |
// | |
// If mscorlib can't handle it properly, then other libraries probably can't, so we'll keep | |
// preferring RSACryptoServiceProvider. | |
RSA rsa = (RSA)Activator.CreateInstance(rsaCng); | |
try | |
{ | |
RSAPKCS1KeyExchangeFormatter formatter = new RSAPKCS1KeyExchangeFormatter(rsa); | |
formatter.CreateKeyExchange(new byte[1]); | |
} | |
catch (NotSupportedException) | |
{ | |
// (mscorlib < 4.6.2) | |
return false; | |
} | |
return true; | |
} | |
private static Func<X509Certificate2, T> BindGetCapiPublicKey<T, TCryptoServiceProvider>(string algorithmOid) | |
where T : AsymmetricAlgorithm | |
where TCryptoServiceProvider : T, ICspAsymmetricAlgorithm, new() | |
{ | |
return cert => | |
{ | |
PublicKey publicKeyInfo = cert.PublicKey; | |
if (publicKeyInfo.Oid.Value != algorithmOid) | |
{ | |
return null; | |
} | |
AsymmetricAlgorithm publicKey = publicKeyInfo.Key; | |
Debug.Assert(publicKey != null); | |
Debug.Assert(publicKey is T); | |
Debug.Assert(publicKey is ICspAsymmetricAlgorithm); | |
ICspAsymmetricAlgorithm sharedCspKey = (ICspAsymmetricAlgorithm)publicKey; | |
byte[] publicKeyBlob = sharedCspKey.ExportCspBlob(false); | |
TCryptoServiceProvider uniqueCspKey = new TCryptoServiceProvider(); | |
uniqueCspKey.ImportCspBlob(publicKeyBlob); | |
return uniqueCspKey; | |
}; | |
} | |
private static Func<X509Certificate2, T> BindGetCapiPrivateKey<T>( | |
string algorithmOid, | |
Func<CspParameters, T> instanceFactory) | |
where T : AsymmetricAlgorithm | |
{ | |
return cert => | |
{ | |
if (!cert.HasPrivateKey) | |
{ | |
return null; | |
} | |
PublicKey publicKeyInfo = cert.PublicKey; | |
if (publicKeyInfo.Oid.Value != algorithmOid) | |
{ | |
return null; | |
} | |
AsymmetricAlgorithm privateKey = cert.PrivateKey; | |
Debug.Assert(privateKey != null); | |
Debug.Assert(privateKey is T); | |
Debug.Assert(privateKey is ICspAsymmetricAlgorithm); | |
ICspAsymmetricAlgorithm cspKey = (ICspAsymmetricAlgorithm)privateKey; | |
CspParameters cspParameters = CopyCspParameters(cspKey); | |
return instanceFactory(cspParameters); | |
}; | |
} | |
private static Func<X509Certificate2, T> BindCoreDelegate<T>(string algorithmName, bool isPublic) | |
{ | |
Debug.Assert(typeof(T).Name == algorithmName); | |
// Load System.Core.dll and load the appropriate extension class | |
// (one of | |
// System.Security.Cryptography.X509Certificates.RSACertificateExtensions | |
// System.Security.Cryptography.X509Certificates.DSACertificateExtensions | |
// System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions | |
// ) | |
string typeName = "System.Security.Cryptography.X509Certificates." + algorithmName + "CertificateExtensions"; | |
Type type = GetSystemCoreType(typeName, throwOnError: false); | |
// If the type exists, it will have the GetPublic/GetPrivate methods available. | |
// But it can end up not existing in scenarios where this assembly has been patched onto | |
// a machine which doesn't have the equivalent baseline. | |
if (type == null) | |
{ | |
return null; | |
} | |
// Now, find the api we want to call: | |
// | |
// (one of | |
// GetRSAPublicKey(this X509Certificate2 c) | |
// GetRSAPrivateKey(this X509Certificate2 c) | |
// GetDSAPublicKey(this X509Certificate2 c) | |
// GetDSAPrivateKey(this X509Certificate2 c) | |
// GetECDsaPublicKey(this X509Certificate2 c) | |
// GetECDsaPrivateKey(this X509Certificate2 c) | |
// ) | |
string methodName = "Get" + algorithmName + (isPublic ? "Public" : "Private") + "Key"; | |
MethodInfo api = type.GetMethod( | |
methodName, | |
BindingFlags.Public | BindingFlags.Static, | |
null, | |
new[] { typeof(X509Certificate2) }, | |
null); | |
Debug.Assert(api != null, "Method '" + methodName + "(X509Certificate2 c)' not found on type '" + type + "'"); | |
return (Func<X509Certificate2, T>)api.CreateDelegate(typeof(Func<X509Certificate2, T>)); | |
} | |
private static CspParameters CopyCspParameters(ICspAsymmetricAlgorithm cspAlgorithm) | |
{ | |
CspKeyContainerInfo cspInfo = cspAlgorithm.CspKeyContainerInfo; | |
CspParameters cspParameters = new CspParameters(cspInfo.ProviderType, cspInfo.ProviderName, cspInfo.KeyContainerName) | |
{ | |
Flags = CspProviderFlags.UseExistingKey, | |
KeyNumber = (int)cspInfo.KeyNumber, | |
}; | |
if (cspInfo.MachineKeyStore) | |
{ | |
cspParameters.Flags |= CspProviderFlags.UseMachineKeyStore; | |
} | |
return cspParameters; | |
} | |
private static Type GetSystemCoreType(string namespaceQualifiedTypeName, bool throwOnError=true) | |
{ | |
#if CNG_LIGHTUP_NO_SYSTEM_CORE | |
string assemblyQualifiedTypeName = namespaceQualifiedTypeName + ", " + AssemblyRef.SystemCore; | |
return Type.GetType(assemblyQualifiedTypeName, throwOnError: false, ignoreCase: false); | |
#else | |
Assembly systemCore = typeof(CngKey).Assembly; | |
Debug.Assert(systemCore.GetName().Name == "System.Core"); | |
return systemCore.GetType(namespaceQualifiedTypeName, throwOnError); | |
#endif | |
} | |
} | |
} | |
#pragma warning restore 436 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment