提交 0f6769a3 编写于 作者: J Jared Parsons

Merge pull request #4249 from jaredpar/hash

Update portions of Crypto loading
......@@ -12,128 +12,44 @@ namespace Roslyn.Utilities
internal abstract class HashAlgorithm : IDisposable
{
private static readonly MethodInfo s_ComputeHash_bytes_Method;
private static readonly MethodInfo s_ComputeHash_bytesOffsetCount_Method;
private static readonly MethodInfo s_ComputeHash_stream_Method;
private static readonly MethodInfo s_TransformBlock_Method;
private static readonly MethodInfo s_TransformFinalBlock_Method;
private static readonly MethodInfo s_Hash_PropertyGetter;
private static readonly MethodInfo s_transformBlock = PortableShim.HashAlgorithm.Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(TransformBlock), new[] { typeof(byte[]), typeof(int), typeof(int), typeof(byte[]), typeof(int) });
private readonly IDisposable _hashInstance;
private const string MscorlibAssembly = "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
private const string HashingAssembly = "System.Security.Cryptography.Hashing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
private const string HashingAlgorithmsAssembly = "System.Security.Cryptography.Hashing.Algorithms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
static HashAlgorithm()
{
Type type = GetType("System.Security.Cryptography.HashAlgorithm", new[] { HashingAssembly, MscorlibAssembly });
Debug.Assert(type != null, "Could not find HashingAlgorithm");
if (type != null)
{
var methods = type.GetTypeInfo().GetDeclaredMethods("ComputeHash");
// https://msdn.microsoft.com/en-us/library/s02tk69a(v=vs.110).aspx
s_ComputeHash_bytes_Method = (from m in methods
let ps = m.GetParameters()
where ps.Length == 1 && ps[0].ParameterType == typeof(byte[])
select m).Single();
// https://msdn.microsoft.com/en-us/library/1e59xaaz(v=vs.110).aspx
s_ComputeHash_bytesOffsetCount_Method = (from m in methods
let ps = m.GetParameters()
where ps.Length == 3 && ps[0].ParameterType == typeof(byte[]) && ps[1].ParameterType == typeof(int) && ps[2].ParameterType == typeof(int)
select m).Single();
// https://msdn.microsoft.com/en-us/library/xa627k19(v=vs.110).aspx
s_ComputeHash_stream_Method = (from m in methods
let ps = m.GetParameters()
where ps.Length == 1 && ps[0].ParameterType == typeof(Stream)
select m).Single();
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.hashalgorithm.transformblock(v=vs.110).aspx
s_TransformBlock_Method = (from m in type.GetTypeInfo().GetDeclaredMethods("TransformBlock")
let ps = m.GetParameters()
where ps.Length == 5 && ps[0].ParameterType == typeof(byte[]) &&
ps[1].ParameterType == typeof(int) &&
ps[2].ParameterType == typeof(int) &&
ps[3].ParameterType == typeof(byte[]) &&
ps[4].ParameterType == typeof(int)
select m).SingleOrDefault();
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.hashalgorithm.transformblock(v=vs.110).aspx
s_TransformFinalBlock_Method = (from m in type.GetTypeInfo().GetDeclaredMethods("TransformFinalBlock")
let ps = m.GetParameters()
where ps.Length == 3 && ps[0].ParameterType == typeof(byte[]) &&
ps[1].ParameterType == typeof(int) &&
ps[2].ParameterType == typeof(int)
select m).SingleOrDefault();
// https://msdn.microsoft.com/en-us/library/system.security.cryptography.hashalgorithm.hash(v=vs.110).aspx
s_Hash_PropertyGetter = type.GetTypeInfo().GetDeclaredProperty("Hash")?.GetMethod;
}
}
protected static MethodInfo LoadAlgorithmCreate(string name)
{
Type t = GetType("System.Security.Cryptography." + name, new[] { HashingAlgorithmsAssembly, MscorlibAssembly });
if (t != null)
{
return (from m in t.GetTypeInfo().GetDeclaredMethods("Create")
where m.IsStatic && m.GetParameters().Length == 0
select m).Single();
}
private static readonly MethodInfo s_transformFinalBlock = PortableShim.HashAlgorithm.Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(TransformFinalBlock), new[] { typeof(byte[]), typeof(int), typeof(int) });
Debug.Assert(false, "Could not find algorithm " + name);
return null;
}
private static readonly PropertyInfo s_hash = PortableShim.HashAlgorithm.Type
.GetTypeInfo()
.GetDeclaredProperty(nameof(Hash));
private static Type GetType(string typeName, string[] assemblyNames)
{
foreach (string assemblyName in assemblyNames)
{
Type t;
try
{
t = Type.GetType(typeName + ", " + assemblyName, throwOnError: false);
}
catch
{
t = null;
}
if (t != null && t.GetTypeInfo().IsPublic)
{
return t;
}
}
return null;
}
private readonly IDisposable _hashInstance;
protected HashAlgorithm(IDisposable hashInstance)
{
_hashInstance = hashInstance;
}
public byte[] ComputeHash(byte[] bytes)
public byte[] ComputeHash(byte[] buffer)
{
return (byte[])s_ComputeHash_bytes_Method.Invoke(_hashInstance, new object[] { bytes });
return PortableShim.HashAlgorithm.ComputeHash(_hashInstance, buffer);
}
public byte[] ComputeHash(byte[] bytes, int offset, int count)
public byte[] ComputeHash(byte[] buffer, int offset, int count)
{
return (byte[])s_ComputeHash_bytesOffsetCount_Method.Invoke(_hashInstance, new object[] { bytes, offset, count });
return PortableShim.HashAlgorithm.ComputeHash(_hashInstance, buffer, offset, count);
}
public byte[] ComputeHash(Stream stream)
public byte[] ComputeHash(Stream inputStream)
{
return (byte[])s_ComputeHash_stream_Method.Invoke(_hashInstance, new object[] { stream });
return PortableShim.HashAlgorithm.ComputeHash(_hashInstance, inputStream);
}
public bool SupportsTransform =>
s_TransformBlock_Method != null &&
s_TransformFinalBlock_Method != null &&
s_Hash_PropertyGetter != null;
s_transformBlock != null &&
s_transformFinalBlock != null &&
s_hash != null;
/// <summary>
/// Invoke the underlying HashAlgorithm's TransformBlock operation on the provided data.
......@@ -142,7 +58,7 @@ public void TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount)
{
while (inputCount > 0)
{
int written = (int)s_TransformBlock_Method.Invoke(_hashInstance, new object[] { inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset });
int written = (int)s_transformBlock.Invoke(_hashInstance, new object[] { inputBuffer, inputOffset, inputCount, inputBuffer, inputOffset });
Debug.Assert(inputCount == written); // does the TransformBlock method always consume the complete data given to it?
inputCount -= written;
inputOffset += written;
......@@ -151,10 +67,10 @@ public void TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount)
public void TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
{
s_TransformFinalBlock_Method.Invoke(_hashInstance, new object[] { inputBuffer, inputOffset, inputCount });
s_transformFinalBlock.Invoke(_hashInstance, new object[] { inputBuffer, inputOffset, inputCount });
}
public byte[] Hash => (byte[])s_Hash_PropertyGetter.Invoke(_hashInstance, new object[] { });
public byte[] Hash => (byte[])s_hash.GetMethod.Invoke(_hashInstance, new object[] { });
public void Dispose()
{
......@@ -164,50 +80,40 @@ public void Dispose()
internal sealed class SHA1CryptoServiceProvider : HashAlgorithm
{
private static readonly MethodInfo s_create = LoadAlgorithmCreate("SHA1");
public SHA1CryptoServiceProvider()
: base((IDisposable)s_create.Invoke(null, null))
: base(PortableShim.SHA1.Create())
{
}
}
internal sealed class SHA256CryptoServiceProvider : HashAlgorithm
{
private static readonly MethodInfo s_create = LoadAlgorithmCreate("SHA256");
public SHA256CryptoServiceProvider()
: base((IDisposable)s_create.Invoke(null, null))
: base(PortableShim.SHA256.Create())
{
}
}
internal sealed class SHA384CryptoServiceProvider : HashAlgorithm
{
private static readonly MethodInfo s_create = LoadAlgorithmCreate("SHA384");
public SHA384CryptoServiceProvider()
: base((IDisposable)s_create.Invoke(null, null))
: base(PortableShim.SHA384.Create())
{
}
}
internal sealed class SHA512CryptoServiceProvider : HashAlgorithm
{
private static readonly MethodInfo s_create = LoadAlgorithmCreate("SHA512");
public SHA512CryptoServiceProvider()
: base((IDisposable)s_create.Invoke(null, null))
: base(PortableShim.SHA512.Create())
{
}
}
internal sealed class MD5CryptoServiceProvider : HashAlgorithm
{
private static readonly MethodInfo s_create = LoadAlgorithmCreate("MD5");
public MD5CryptoServiceProvider()
: base((IDisposable)s_create.Invoke(null, null))
: base(PortableShim.MD5.Create())
{
}
}
......
......@@ -58,6 +58,12 @@ internal static void Initialize()
Touch(SearchOption.Type);
Touch(Thread.Type);
Touch(XPath.Extensions.Type);
Touch(HashAlgorithm.Type);
Touch(SHA1.Type);
Touch(SHA256.Type);
Touch(SHA512.Type);
Touch(SHA384.Type);
Touch(MD5.Type);
}
private static void Touch(Type type)
......@@ -70,11 +76,13 @@ private static class CoreNames
internal const string System_Diagnostics_FileVersionInfo = "System.Diagnostics.FileVersionInfo, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_IO_FileSystem = "System.IO.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_IO_FileSystem_Primitives = "System.IO.FileSystem.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Reflection = "System.Reflection, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Runtime = "System.Runtime, Version=4.0.20.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Runtime_Extensions = "System.Runtime.Extensions, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Security_Cryptography_Primitives = "System.Security.Cryptography.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Security_Cryptography_Algorithms = "System.Security.Cryptography.Algorithms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Threading_Thread = "System.Threading.Thread, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Xml_XPath_XDocument = "System.Xml.XPath.XDocument, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
internal const string System_Reflection = "System.Reflection, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
}
private static class DesktopNames
......@@ -478,5 +486,111 @@ internal static class Assembly
.GetDeclaredMethod("GetType", typeof(string), typeof(bool), typeof(bool))
.CreateDelegate<Func<System.Reflection.Assembly, string, bool, bool, Type>>();
}
internal static class HashAlgorithm
{
private const string TypeName = "System.Security.Cryptography.HashAlgorithm";
internal static readonly Type Type = ReflectionUtilities.GetTypeFromEither(
contractName: $"{TypeName}, {CoreNames.System_Security_Cryptography_Primitives}",
desktopName: TypeName);
private static readonly MethodInfo s_computeHash_byte = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(ComputeHash), new[] { typeof(byte[]) });
private static readonly MethodInfo s_computeHash_byte_int_int = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(ComputeHash), new[] { typeof(byte[]), typeof(int), typeof(int) });
private static readonly MethodInfo s_computeHash_stream = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(ComputeHash), new[] { typeof(Stream) });
internal static byte[] ComputeHash(object hashInstance, byte[] buffer)
{
return (byte[])s_computeHash_byte.Invoke(hashInstance, new object[] { buffer });
}
internal static byte[] ComputeHash(object hashInstance, byte[] buffer, int offset, int count)
{
return (byte[])s_computeHash_byte_int_int.Invoke(hashInstance, new object[] { buffer, offset, count });
}
internal static byte[] ComputeHash(object hashInstance, Stream inputStream)
{
return (byte[])s_computeHash_stream.Invoke(hashInstance, new object[] { inputStream });
}
}
internal static class SHA1
{
private const string TypeName = "System.Security.Cryptography.SHA1";
internal static readonly Type Type = ReflectionUtilities.GetTypeFromEither(
contractName: $"{TypeName}, {CoreNames.System_Security_Cryptography_Algorithms}",
desktopName: TypeName);
internal static readonly Func<IDisposable> Create = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(Create), new Type[] { })
.CreateDelegate<Func<IDisposable>>();
}
internal static class SHA256
{
private const string TypeName = "System.Security.Cryptography.SHA256";
internal static readonly Type Type = ReflectionUtilities.GetTypeFromEither(
contractName: $"{TypeName}, {CoreNames.System_Security_Cryptography_Algorithms}",
desktopName: TypeName);
internal static readonly Func<IDisposable> Create = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(Create), new Type[] { })
.CreateDelegate<Func<IDisposable>>();
}
internal static class SHA384
{
private const string TypeName = "System.Security.Cryptography.SHA384";
internal static readonly Type Type = ReflectionUtilities.GetTypeFromEither(
contractName: $"{TypeName}, {CoreNames.System_Security_Cryptography_Algorithms}",
desktopName: TypeName);
internal static readonly Func<IDisposable> Create = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(Create), new Type[] { })
.CreateDelegate<Func<IDisposable>>();
}
internal static class SHA512
{
private const string TypeName = "System.Security.Cryptography.SHA512";
internal static readonly Type Type = ReflectionUtilities.GetTypeFromEither(
contractName: $"{TypeName}, {CoreNames.System_Security_Cryptography_Algorithms}",
desktopName: TypeName);
internal static readonly Func<IDisposable> Create = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(Create), new Type[] { })
.CreateDelegate<Func<IDisposable>>();
}
internal static class MD5
{
private const string TypeName = "System.Security.Cryptography.MD5";
internal static readonly Type Type = ReflectionUtilities.GetTypeFromEither(
contractName: $"{TypeName}, {CoreNames.System_Security_Cryptography_Algorithms}",
desktopName: TypeName);
internal static readonly Func<IDisposable> Create = Type
.GetTypeInfo()
.GetDeclaredMethod(nameof(Create), new Type[] { })
.CreateDelegate<Func<IDisposable>>();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册