Пример #1
0
		/// <summary>
		/// Hash data
		/// </summary>
		/// <remarks>If <paramref name="hashAlgo"/> is an unsupported hash algorithm, then
		/// <see cref="AssemblyHashAlgorithm.SHA1"/> will be used as the hash algorithm.</remarks>
		/// <param name="data">The data</param>
		/// <param name="hashAlgo">The algorithm to use</param>
		/// <returns>Hashed data or null if <paramref name="data"/> was <c>null</c></returns>
		public static byte[] Hash(byte[] data, AssemblyHashAlgorithm hashAlgo) {
			if (data == null)
				return null;

			using (var asmHash = new AssemblyHash(hashAlgo)) {
				asmHash.Hash(data);
				return asmHash.ComputeHash();
			}
		}
Пример #2
0
        /// <summary>
        /// Hash data
        /// </summary>
        /// <remarks>If <paramref name="hashAlgo"/> is an unsupported hash algorithm, then
        /// <see cref="AssemblyHashAlgorithm.SHA1"/> will be used as the hash algorithm.</remarks>
        /// <param name="data">The data</param>
        /// <param name="hashAlgo">The algorithm to use</param>
        /// <returns>Hashed data or null if <paramref name="data"/> was <c>null</c></returns>
        public static byte[] Hash(byte[] data, AssemblyHashAlgorithm hashAlgo)
        {
            if (data == null)
            {
                return(null);
            }

            using (var asmHash = new AssemblyHash(hashAlgo)) {
                asmHash.Hash(data);
                return(asmHash.ComputeHash());
            }
        }
Пример #3
0
        /// <summary>
        /// Creates a counter signature, just like
        /// <c>sn -a IdentityPubKey.snk IdentityKey.snk SignaturePubKey.snk</c> can do.
        /// The public key <c>sn</c> prints is <paramref name="signaturePubKey"/>'s value.
        /// </summary>
        /// <param name="identityPubKey">Identity public key</param>
        /// <param name="identityKey">Identity strong name key pair</param>
        /// <param name="signaturePubKey">Signature public key</param>
        /// <returns>The counter signature</returns>
        public static byte[] CreateCounterSignature(StrongNamePublicKey identityPubKey, StrongNameKey identityKey, StrongNamePublicKey signaturePubKey)
        {
            var hash = AssemblyHash.Hash(signaturePubKey.CreatePublicKey(), identityPubKey.HashAlgorithm);

            using (var rsa = identityKey.CreateRSA()) {
                var rsaFmt      = new RSAPKCS1SignatureFormatter(rsa);
                string hashName = identityPubKey.HashAlgorithm.GetName();
                rsaFmt.SetHashAlgorithm(hashName);
                var snSig = rsaFmt.CreateSignature(hash);
                Array.Reverse(snSig);
                return(snSig);
            }
        }
Пример #4
0
        /// <summary>
        /// Strong name hashes the .NET file
        /// </summary>
        /// <param name="hashAlg">Hash algorithm</param>
        /// <param name="snSigOffset">Strong name sig offset (relative to start of .NET PE file)</param>
        /// <param name="snSigSize">Size of strong name signature</param>
        /// <returns>The strong name hash of the .NET file</returns>
        byte[] StrongNameHashData(AssemblyHashAlgorithm hashAlg, long snSigOffset, uint snSigSize)
        {
            var reader = new BinaryReader(stream);

            snSigOffset += baseOffset;
            long snSigOffsetEnd = snSigOffset + snSigSize;

            using var hasher = new AssemblyHash(hashAlg);
            var buffer = new byte[0x8000];

            // Hash the DOS header. It's defined to be all data from the start of
            // the file up to the NT headers.
            stream.Position = baseOffset + 0x3C;
            uint ntHeadersOffs = reader.ReadUInt32();

            stream.Position = baseOffset;
            hasher.Hash(stream, ntHeadersOffs, buffer);

            // Hash NT headers, but hash authenticode + checksum as 0s
            stream.Position += 6;
            int numSections = reader.ReadUInt16();

            stream.Position -= 8;
            hasher.Hash(stream, 0x18, buffer);              // magic + FileHeader

            bool is32bit = reader.ReadUInt16() == 0x010B;

            stream.Position -= 2;
            int optHeaderSize = is32bit ? 0x60 : 0x70;

            if (stream.Read(buffer, 0, optHeaderSize) != optHeaderSize)
            {
                throw new IOException("Could not read data");
            }
            // Clear checksum
            for (int i = 0; i < 4; i++)
            {
                buffer[0x40 + i] = 0;
            }
            hasher.Hash(buffer, 0, optHeaderSize);

            const int imageDirsSize = 16 * 8;

            if (stream.Read(buffer, 0, imageDirsSize) != imageDirsSize)
            {
                throw new IOException("Could not read data");
            }
            // Clear authenticode data dir
            for (int i = 0; i < 8; i++)
            {
                buffer[(4 * 8) + i] = 0;
            }
            hasher.Hash(buffer, 0, imageDirsSize);

            // Hash section headers
            long sectHeadersOffs = stream.Position;

            hasher.Hash(stream, (uint)numSections * 0x28, buffer);

            // Hash all raw section data but make sure we don't hash the location
            // where the strong name signature will be stored.
            for (int i = 0; i < numSections; i++)
            {
                stream.Position = sectHeadersOffs + (i * 0x28) + 0x10;
                uint sizeOfRawData    = reader.ReadUInt32();
                uint pointerToRawData = reader.ReadUInt32();

                stream.Position = baseOffset + pointerToRawData;
                while (sizeOfRawData > 0)
                {
                    var pos = stream.Position;

                    if (snSigOffset <= pos && pos < snSigOffsetEnd)
                    {
                        uint skipSize = (uint)(snSigOffsetEnd - pos);
                        if (skipSize >= sizeOfRawData)
                        {
                            break;
                        }
                        sizeOfRawData   -= skipSize;
                        stream.Position += skipSize;
                        continue;
                    }

                    if (pos >= snSigOffsetEnd)
                    {
                        hasher.Hash(stream, sizeOfRawData, buffer);
                        break;
                    }

                    uint maxLen = (uint)Math.Min(snSigOffset - pos, sizeOfRawData);
                    hasher.Hash(stream, maxLen, buffer);
                    sizeOfRawData -= maxLen;
                }
            }

            return(hasher.ComputeHash());
        }
Пример #5
0
		/// <summary>
		/// Strong name hashes the .NET file
		/// </summary>
		/// <param name="hashAlg">Hash algorithm</param>
		/// <param name="snSigOffset">Strong name sig offset (relative to start of .NET PE file)</param>
		/// <param name="snSigSize">Size of strong name signature</param>
		/// <returns>The strong name hash of the .NET file</returns>
		byte[] StrongNameHashData(AssemblyHashAlgorithm hashAlg, long snSigOffset, uint snSigSize) {
			var reader = new BinaryReader(stream);

			snSigOffset += baseOffset;
			long snSigOffsetEnd = snSigOffset + snSigSize;

			using (var hasher = new AssemblyHash(hashAlg)) {
				byte[] buffer = new byte[0x8000];

				// Hash the DOS header. It's defined to be all data from the start of
				// the file up to the NT headers.
				stream.Position = baseOffset + 0x3C;
				uint ntHeadersOffs = reader.ReadUInt32();
				stream.Position = baseOffset;
				hasher.Hash(stream, ntHeadersOffs, buffer);

				// Hash NT headers, but hash authenticode + checksum as 0s
				stream.Position += 6;
				int numSections = reader.ReadUInt16();
				stream.Position -= 8;
				hasher.Hash(stream, 0x18, buffer);	// magic + FileHeader

				bool is32bit = reader.ReadUInt16() == 0x010B;
				stream.Position -= 2;
				int optHeaderSize = is32bit ? 0x60 : 0x70;
				if (stream.Read(buffer, 0, optHeaderSize) != optHeaderSize)
					throw new IOException("Could not read data");
				// Clear checksum
				for (int i = 0; i < 4; i++)
					buffer[0x40 + i] = 0;
				hasher.Hash(buffer, 0, optHeaderSize);

				const int imageDirsSize = 16 * 8;
				if (stream.Read(buffer, 0, imageDirsSize) != imageDirsSize)
					throw new IOException("Could not read data");
				// Clear authenticode data dir
				for (int i = 0; i < 8; i++)
					buffer[4 * 8 + i] = 0;
				hasher.Hash(buffer, 0, imageDirsSize);

				// Hash section headers
				long sectHeadersOffs = stream.Position;
				hasher.Hash(stream, (uint)numSections * 0x28, buffer);

				// Hash all raw section data but make sure we don't hash the location
				// where the strong name signature will be stored.
				for (int i = 0; i < numSections; i++) {
					stream.Position = sectHeadersOffs + i * 0x28 + 0x10;
					uint sizeOfRawData = reader.ReadUInt32();
					uint pointerToRawData = reader.ReadUInt32();

					stream.Position = baseOffset + pointerToRawData;
					while (sizeOfRawData > 0) {
						var pos = stream.Position;

						if (snSigOffset <= pos && pos < snSigOffsetEnd) {
							uint skipSize = (uint)(snSigOffsetEnd - pos);
							if (skipSize >= sizeOfRawData)
								break;
							sizeOfRawData -= skipSize;
							stream.Position += skipSize;
							continue;
						}

						if (pos >= snSigOffsetEnd) {
							hasher.Hash(stream, sizeOfRawData, buffer);
							break;
						}

						uint maxLen = (uint)Math.Min(snSigOffset - pos, sizeOfRawData);
						hasher.Hash(stream, maxLen, buffer);
						sizeOfRawData -= maxLen;
					}
				}

				return hasher.ComputeHash();
			}
		}