Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Security / Policy / Hash.cs / 1305376 / Hash.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //[....] // // // Hash // // Evidence corresponding to a hash of the assembly bits. // using System; using System.Diagnostics.Contracts; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Security.Util; using Microsoft.Win32.SafeHandles; namespace System.Security.Policy { [Serializable] [ComVisible(true)] public sealed class Hash : EvidenceBase, ISerializable { private RuntimeAssembly m_assembly; private Dictionarym_hashes; private WeakReference m_rawData; /// /// Deserialize a serialized hash evidence object /// [SecurityCritical] internal Hash(SerializationInfo info, StreamingContext context) { // // We have three serialization formats that we might be deserializing, the Whidbey format which // contains hash values directly, the Whidbey format which contains a pointer to a PEImage, and // the v4 format which contains a dictionary of calculated hashes. // // If we have the Whidbey version that has built in hash values, we can convert that, but we // cannot do anything with the PEImage format since that is a serialized pointer into another // runtime's VM. // Dictionaryhashes = info.GetValueNoThrow("Hashes", typeof(Dictionary )) as Dictionary ; if (hashes != null) { m_hashes = hashes; } else { // If there is no hash value dictionary, then check to see if we have the Whidbey multiple // hashes version of the evidence. m_hashes = new Dictionary (); byte[] md5 = info.GetValueNoThrow("Md5", typeof(byte[])) as byte[]; if (md5 != null) { m_hashes[typeof(MD5)] = md5; } byte[] sha1 = info.GetValueNoThrow("Sha1", typeof(byte[])) as byte[]; if (sha1 != null) { m_hashes[typeof(SHA1)] = sha1; } byte[] rawData = info.GetValueNoThrow("RawData", typeof(byte[])) as byte[]; if (rawData != null) { GenerateDefaultHashes(rawData); } } } /// /// Create hash evidence for the specified assembly /// public Hash(Assembly assembly) { if (assembly == null) throw new ArgumentNullException("assembly"); Contract.EndContractBlock(); if (assembly.IsDynamic) throw new ArgumentException(Environment.GetResourceString("Security_CannotGenerateHash"), "assembly"); m_hashes = new Dictionary(); m_assembly = assembly as RuntimeAssembly; if (m_assembly == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "assembly"); } /// /// Create a copy of some hash evidence /// private Hash(Hash hash) { Contract.Assert(hash != null); m_assembly = hash.m_assembly; m_rawData = hash.m_rawData; m_hashes = new Dictionary(hash.m_hashes); } /// /// Create a hash evidence prepopulated with a specific hash value /// private Hash(Type hashType, byte[] hashValue) { Contract.Assert(hashType != null); Contract.Assert(hashValue != null); m_hashes = new Dictionary(); byte[] hashClone = new byte[hashValue.Length]; Array.Copy(hashValue, hashClone, hashClone.Length); m_hashes[hashType] = hashValue; } /// /// Build a Hash evidence that contains the specific SHA-1 hash. The input hash is not validated, /// and the resulting Hash object cannot calculate additional hash values. /// public static Hash CreateSHA1(byte[] sha1) { if (sha1 == null) throw new ArgumentNullException("sha1"); Contract.EndContractBlock(); return new Hash(typeof(SHA1), sha1); } ////// Build a Hash evidence that contains the specific SHA-256 hash. The input hash is not /// validated, and the resulting Hash object cannot calculate additional hash values. /// public static Hash CreateSHA256(byte[] sha256) { if (sha256 == null) throw new ArgumentNullException("sha256"); Contract.EndContractBlock(); return new Hash(typeof(SHA256), sha256); } ////// Build a Hash evidence that contains the specific MD5 hash. The input hash is not validated, /// and the resulting Hash object cannot calculate additional hash values. /// public static Hash CreateMD5(byte[] md5) { if (md5 == null) throw new ArgumentNullException("md5"); Contract.EndContractBlock(); return new Hash(typeof(MD5), md5); } ////// Make a copy of this evidence object /// public override EvidenceBase Clone() { return new Hash(this); } ////// Prepare the hash evidence for serialization /// [OnSerializing] private void OnSerializing(StreamingContext ctx) { GenerateDefaultHashes(); } ////// Serialize the hash evidence /// [SecurityCritical] public void GetObjectData(SerializationInfo info, StreamingContext context) { GenerateDefaultHashes(); // // Backwards compatibility with Whidbey // byte[] sha1Hash; byte[] md5Hash; // Whidbey expects the MD5 and SHA1 hashes stored separately. if (m_hashes.TryGetValue(typeof(MD5), out md5Hash)) { info.AddValue("Md5", md5Hash); } if (m_hashes.TryGetValue(typeof(SHA1), out sha1Hash)) { info.AddValue("Sha1", sha1Hash); } // For perf, don't serialize the assembly binary content. // This has the side-effect that the Whidbey runtime will not be able to compute any // hashes besides the provided MD5 and SHA1. info.AddValue("RawData", null); // It doesn't make sense to serialize a memory pointer cross-runtime. info.AddValue("PEFile", IntPtr.Zero); // // Current implementation // // Add all the computed hashes. While this can duplicate the MD5 and SHA1 hashes, // it allows for a clean separation between legacy support and the current implementation. info.AddValue("Hashes", m_hashes); } ////// Get the SHA-1 hash value of the assembly /// public byte[] SHA1 { get { byte[] sha1 = null; if (!m_hashes.TryGetValue(typeof(SHA1), out sha1)) { sha1 = GenerateHash(GetDefaultHashImplementationOrFallback(typeof(SHA1), typeof(SHA1))); } byte[] returnHash = new byte[sha1.Length]; Array.Copy(sha1, returnHash, returnHash.Length); return returnHash; } } ////// Get the SHA-256 hash value of the assembly /// public byte[] SHA256 { get { byte[] sha256 = null; if (!m_hashes.TryGetValue(typeof(SHA256), out sha256)) { sha256 = GenerateHash(GetDefaultHashImplementationOrFallback(typeof(SHA256), typeof(SHA256))); } byte[] returnHash = new byte[sha256.Length]; Array.Copy(sha256, returnHash, returnHash.Length); return returnHash; } } ////// Get the MD5 hash value of the assembly /// public byte[] MD5 { get { byte[] md5 = null; if (!m_hashes.TryGetValue(typeof(MD5), out md5)) { md5 = GenerateHash(GetDefaultHashImplementationOrFallback(typeof(MD5), typeof(MD5))); } byte[] returnHash = new byte[md5.Length]; Array.Copy(md5, returnHash, returnHash.Length); return returnHash; } } ////// Get the hash value of the assembly when hashed with a specific algorithm. The actual hash /// algorithm object is not used, however the same type of object will be used. /// public byte[] GenerateHash(HashAlgorithm hashAlg) { if (hashAlg == null) throw new ArgumentNullException("hashAlg"); Contract.EndContractBlock(); byte[] hashValue = GenerateHash(hashAlg.GetType()); byte[] returnHash = new byte[hashValue.Length]; Array.Copy(hashValue, returnHash, returnHash.Length); return returnHash; } ////// Generate the hash value of an assembly when hashed with the specified algorithm. The result /// may be a direct reference to our internal table of hashes, so it should be copied before /// returning it to user code. /// private byte[] GenerateHash(Type hashType) { Contract.Assert(hashType != null && typeof(HashAlgorithm).IsAssignableFrom(hashType), "Expected a hash algorithm"); Type indexType = GetHashIndexType(hashType); byte[] hashValue = null; if (!m_hashes.TryGetValue(indexType, out hashValue)) { // If we're not attached to an assembly, then we cannot generate hashes on demand if (m_assembly == null) { throw new InvalidOperationException(Environment.GetResourceString("Security_CannotGenerateHash")); } hashValue = GenerateHash(hashType, GetRawData()); m_hashes[indexType] = hashValue; } return hashValue; } ////// Generate a hash of the given type for the assembly data /// private static byte[] GenerateHash(Type hashType, byte[] assemblyBytes) { Contract.Assert(hashType != null && typeof(HashAlgorithm).IsAssignableFrom(hashType), "Expected a hash algorithm"); Contract.Assert(assemblyBytes != null); using (HashAlgorithm hash = HashAlgorithm.Create(hashType.FullName)) { return hash.ComputeHash(assemblyBytes); } } ////// Build the default set of hash values that will be available for all assemblies /// private void GenerateDefaultHashes() { // We can't generate any hash values that we don't already have if there isn't an attached // assembly to get the hash value of. if (m_assembly != null) { GenerateDefaultHashes(GetRawData()); } } ////// Build the default set of hash values that will be available for all assemblies given the raw /// assembly data to hash. /// private void GenerateDefaultHashes(byte[] assemblyBytes) { Contract.Assert(assemblyBytes != null); Type[] defaultHashTypes = new Type[] { GetHashIndexType(typeof(SHA1)), GetHashIndexType(typeof(SHA256)), GetHashIndexType(typeof(MD5)) }; foreach (Type defaultHashType in defaultHashTypes) { Type hashImplementationType = GetDefaultHashImplementation(defaultHashType); if (hashImplementationType != null) { if (!m_hashes.ContainsKey(defaultHashType)) { m_hashes[defaultHashType] = GenerateHash(hashImplementationType, assemblyBytes); } } } } ////// Map a hash algorithm to the default implementation of that algorithm, falling back to a given /// implementation if no suitable default can be found. This option may be used for situations /// where it is better to throw an informative exception when trying to use an unsuitable hash /// algorithm than to just return null. (For instance, throwing a FIPS not supported exception /// when trying to get the MD5 hash evidence). /// private static Type GetDefaultHashImplementationOrFallback(Type hashAlgorithm, Type fallbackImplementation) { Contract.Assert(hashAlgorithm != null && typeof(HashAlgorithm).IsAssignableFrom(hashAlgorithm)); Contract.Assert(fallbackImplementation != null && GetHashIndexType(hashAlgorithm).IsAssignableFrom(fallbackImplementation)); Type defaultImplementation = GetDefaultHashImplementation(hashAlgorithm); return defaultImplementation != null ? defaultImplementation : fallbackImplementation; } ////// Map a hash algorithm to the default implementation of that algorithm to use for Hash /// evidence, taking into account things such as FIPS support. If there is no suitable /// implementation for the algorithm, GetDefaultHashImplementation returns null. /// private static Type GetDefaultHashImplementation(Type hashAlgorithm) { Contract.Assert(hashAlgorithm != null && typeof(HashAlgorithm).IsAssignableFrom(hashAlgorithm)); if (hashAlgorithm.IsAssignableFrom(typeof(MD5))) { // MD5 is not a FIPS compliant algorithm, so if we need to allow only FIPS implementations, // we have no way to create an MD5 hash. Otherwise, we can just use the standard CAPI // implementation since that is available on all operating systems we support. if (!CryptoConfig.AllowOnlyFipsAlgorithms) { return typeof(MD5CryptoServiceProvider); } else { return null; } } else if (hashAlgorithm.IsAssignableFrom(typeof(SHA256))) { // The managed SHA256 implementation is not a FIPS certified implementation, however on // Windows 2003 and higher we have a FIPS alternative. If we're on Windows 2003 or better, // use the CAPI implementation - otherwise, we fall back to the managed implementation if // FIPS is not enabled. Version osVersion = Environment.OSVersion.Version; bool isWin2k3OrHigher = Environment.RunningOnWinNT && (osVersion.Major > 5 || (osVersion.Major == 5 && osVersion.Minor >= 2)); if (isWin2k3OrHigher) { return Type.GetType("System.Security.Cryptography.SHA256CryptoServiceProvider, " + AssemblyRef.SystemCore); } else if (!CryptoConfig.AllowOnlyFipsAlgorithms) { return typeof(SHA256Managed); } else { return null; } } else { // Otherwise we don't have a better suggestion for the algorithm, so we can just fallback to // the input algorithm. return hashAlgorithm; } } ////// Get the type used to index into the saved hash value dictionary. We want this to be the /// class which immediately derives from HashAlgorithm so that we can reuse the same hash value /// if we're asked for (e.g.) SHA256Managed and SHA256CryptoServiceProvider /// private static Type GetHashIndexType(Type hashType) { Contract.Assert(hashType != null && typeof(HashAlgorithm).IsAssignableFrom(hashType)); Type currentType = hashType; // Walk up the inheritence hierarchy looking for the first class that derives from HashAlgorithm while (currentType != null && currentType.BaseType != typeof(HashAlgorithm)) { currentType = currentType.BaseType; } // If this is the degenerate case where we started out with HashAlgorithm, we won't find it // further up our inheritence tree. if (currentType == null) { BCLDebug.Assert(hashType == typeof(HashAlgorithm), "hashType == typeof(HashAlgorithm)"); currentType = typeof(HashAlgorithm); } return currentType; } ////// Raw bytes of the assembly being hashed /// private byte[] GetRawData() { byte[] rawData = null; // We can only generate hashes on demand if we're associated with an assembly if (m_assembly != null) { // See if we still hold a reference to the assembly data if (m_rawData != null) { rawData = m_rawData.Target as byte[]; } // If not, load the raw bytes up if (rawData == null) { rawData = m_assembly.GetRawBytes(); m_rawData = new WeakReference(rawData); } } return rawData; } private SecurityElement ToXml() { GenerateDefaultHashes(); SecurityElement root = new SecurityElement("System.Security.Policy.Hash"); // If you hit this assert then most likely you are trying to change the name of this class. // This is ok as long as you change the hard coded string above and change the assert below. BCLDebug.Assert(this.GetType().FullName.Equals("System.Security.Policy.Hash"), "Class name changed!"); root.AddAttribute("version", "2"); foreach (KeyValuePairhashValue in m_hashes) { SecurityElement hashElement = new SecurityElement("hash"); hashElement.AddAttribute("algorithm", hashValue.Key.Name); hashElement.AddAttribute("value", Hex.EncodeHexString(hashValue.Value)); root.AddChild(hashElement); } return root; } public override String ToString() { return ToXml().ToString(); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DbConnectionPool.cs
- Model3D.cs
- VirtualDirectoryMapping.cs
- SubMenuStyleCollectionEditor.cs
- regiisutil.cs
- QueryCacheEntry.cs
- GradientSpreadMethodValidation.cs
- WebScriptEnablingElement.cs
- DataSetFieldSchema.cs
- XmlCharacterData.cs
- EntityWrapperFactory.cs
- PageContent.cs
- Timer.cs
- MetadataPropertyAttribute.cs
- FilteredAttributeCollection.cs
- SystemNetworkInterface.cs
- ITextView.cs
- KoreanCalendar.cs
- OleDbSchemaGuid.cs
- IconConverter.cs
- JsonWriter.cs
- PageAsyncTaskManager.cs
- SmiRequestExecutor.cs
- XmlSchemaAnyAttribute.cs
- TextParagraphProperties.cs
- Decimal.cs
- OdbcParameter.cs
- WebPartManager.cs
- OleDbWrapper.cs
- MediaTimeline.cs
- ManualResetEvent.cs
- CommandTreeTypeHelper.cs
- Boolean.cs
- XmlSchemaSimpleContent.cs
- TCPListener.cs
- diagnosticsswitches.cs
- configsystem.cs
- AddInControllerImpl.cs
- EntryPointNotFoundException.cs
- ArrangedElement.cs
- SmtpMail.cs
- PropVariant.cs
- ColumnMapCopier.cs
- ScriptMethodAttribute.cs
- ControlAdapter.cs
- HMACSHA256.cs
- VectorConverter.cs
- PropertyGridView.cs
- PlanCompilerUtil.cs
- MissingSatelliteAssemblyException.cs
- CopyOnWriteList.cs
- Attributes.cs
- SafeNativeMethods.cs
- RunInstallerAttribute.cs
- HttpGetProtocolImporter.cs
- CompilerParameters.cs
- BitmapEditor.cs
- DataViewSettingCollection.cs
- CollectionType.cs
- CodeExpressionRuleDeclaration.cs
- GlyphCollection.cs
- Accessible.cs
- _UriTypeConverter.cs
- _ProxyChain.cs
- HttpCookieCollection.cs
- SymmetricKey.cs
- EntityViewContainer.cs
- Application.cs
- MimeMultiPart.cs
- ArcSegment.cs
- OpenTypeLayout.cs
- DocumentViewerConstants.cs
- BindingNavigator.cs
- UriExt.cs
- TreeNodeConverter.cs
- LookupNode.cs
- EllipseGeometry.cs
- StringUtil.cs
- EUCJPEncoding.cs
- DataGridViewRowContextMenuStripNeededEventArgs.cs
- TextTreeRootTextBlock.cs
- RangeBaseAutomationPeer.cs
- RoutedCommand.cs
- ScriptResourceAttribute.cs
- BindingMAnagerBase.cs
- TablePattern.cs
- WebConfigurationHostFileChange.cs
- FlowDocumentScrollViewerAutomationPeer.cs
- DataBoundControlAdapter.cs
- XmlCodeExporter.cs
- SeekStoryboard.cs
- DataTemplateKey.cs
- BooleanToVisibilityConverter.cs
- SqlDataRecord.cs
- LicenseException.cs
- embossbitmapeffect.cs
- WebPartMenu.cs
- DataError.cs
- DbConnectionStringCommon.cs
- StringValueSerializer.cs