Mono.Security.StrongName.StrongHash C# (CSharp) Method

StrongHash() private method

private StrongHash ( Stream stream, StrongNameOptions options ) : StrongNameSignature
stream Stream
options StrongNameOptions
return StrongNameSignature
		internal StrongNameSignature StrongHash (Stream stream, StrongNameOptions options)
		{
			StrongNameSignature info = new StrongNameSignature ();

			HashAlgorithm hash = HashAlgorithm.Create (TokenAlgorithm);
			CryptoStream cs = new CryptoStream (Stream.Null, hash, CryptoStreamMode.Write);

			// MS-DOS Header - always 128 bytes
			// ref: Section 24.2.1, Partition II Metadata
			byte[] mz = new byte [128];
			stream.Read (mz, 0, 128);
			if (BitConverterLE.ToUInt16 (mz, 0) != 0x5a4d)
				return null;
			UInt32 peHeader = BitConverterLE.ToUInt32 (mz, 60);
			cs.Write (mz, 0, 128);
			if (peHeader != 128) {
				byte[] mzextra = new byte [peHeader - 128];
				stream.Read (mzextra, 0, mzextra.Length);
				cs.Write (mzextra, 0, mzextra.Length);
			}

			// PE File Header - always 248 bytes
			// ref: Section 24.2.2, Partition II Metadata
			byte[] pe = new byte [248];
			stream.Read (pe, 0, 248);
			if (BitConverterLE.ToUInt32 (pe, 0) != 0x4550)
				return null;
			if (BitConverterLE.ToUInt16 (pe, 4) != 0x14c)
				return null;
			// MUST zeroize both CheckSum and Security Directory
			byte[] v = new byte [8];
			Buffer.BlockCopy (v, 0, pe, 88, 4);
			Buffer.BlockCopy (v, 0, pe, 152, 8);
			cs.Write (pe, 0, 248);

			UInt16 numSection = BitConverterLE.ToUInt16 (pe, 6);
			int sectionLength = (numSection * 40);
			byte[] sectionHeaders = new byte [sectionLength];
			stream.Read (sectionHeaders, 0, sectionLength);
			cs.Write (sectionHeaders, 0, sectionLength);

			UInt32 cliHeaderRVA = BitConverterLE.ToUInt32 (pe, 232);
			UInt32 cliHeaderPos = RVAtoPosition (cliHeaderRVA, numSection, sectionHeaders);
			int cliHeaderSiz = (int) BitConverterLE.ToUInt32 (pe, 236);

			// CLI Header
			// ref: Section 24.3.3, Partition II Metadata
			byte[] cli = new byte [cliHeaderSiz];
			stream.Position = cliHeaderPos;
			stream.Read (cli, 0, cliHeaderSiz);

			UInt32 strongNameSignatureRVA = BitConverterLE.ToUInt32 (cli, 32);
			info.SignaturePosition = RVAtoPosition (strongNameSignatureRVA, numSection, sectionHeaders);
			info.SignatureLength = BitConverterLE.ToUInt32 (cli, 36);

			UInt32 metadataRVA = BitConverterLE.ToUInt32 (cli, 8);
			info.MetadataPosition = RVAtoPosition (metadataRVA, numSection, sectionHeaders);
			info.MetadataLength = BitConverterLE.ToUInt32 (cli, 12);

			if (options == StrongNameOptions.Metadata) {
				cs.Close ();
				hash.Initialize ();
				byte[] metadata = new byte [info.MetadataLength];
				stream.Position = info.MetadataPosition;
				stream.Read (metadata, 0, metadata.Length);
				info.Hash = hash.ComputeHash (metadata);
				return info;
			}

			// now we hash every section EXCEPT the signature block
			for (int i=0; i < numSection; i++) {
				UInt32 start = BitConverterLE.ToUInt32 (sectionHeaders, i * 40 + 20);
				int length = (int) BitConverterLE.ToUInt32 (sectionHeaders, i * 40 + 16);
				byte[] section = new byte [length];
				stream.Position = start;
				stream.Read (section, 0, length);
				if ((start <= info.SignaturePosition) && (info.SignaturePosition < start + length)) {
					// hash before the signature
					int before = (int)(info.SignaturePosition - start);
					if (before > 0) {
						cs.Write (section, 0, before);
					}
					// copy signature
					info.Signature = new byte [info.SignatureLength];
					Buffer.BlockCopy (section, before, info.Signature, 0, (int)info.SignatureLength);
					Array.Reverse (info.Signature);
					// hash after the signature
					int s = (int)(before + info.SignatureLength);
					int after = (int)(length - s);
					if (after > 0) {
						cs.Write (section, s, after);
					}
				}
				else
					cs.Write (section, 0, length);
			}

			cs.Close ();
			info.Hash = hash.Hash;
			return info;
		}