CODE SIGNING GUIDE  |  CODESIGNINGSOLUTION.COM

What Is a Hash Algorithm?

Updated May 2026  |  Category: Cryptography / Hash Algorithms / SHA-256 / Code Signing / Authenticode  |  Reading time: 10 min

 

A hash algorithm is a mathematical function that takes any input (a file, a message, a password) and produces a fixed-length output called a hash value, digest, or checksum. No matter how large the input, the output is always the same size: SHA-256 always produces 256 bits (32 bytes), expressed as a 64-character hexadecimal string.

Hash algorithms are foundational to how code signing works. When signtool signs a Windows executable, it computes a cryptographic hash of the file’s content and signs that hash with the publisher’s private key. The hash is what makes verification possible: it lets anyone check that a file has not been modified since signing without needing to re-examine the entire file against the original.

 

What Makes a Hash Algorithm Cryptographically Secure

Not all hash functions are cryptographic hash functions. A simple checksum that adds up byte values produces a hash, but it provides no security guarantees. A cryptographic hash function must satisfy four properties:

 

Determinism

The same input always produces the same output. Every time SHA-256 hashes the text ‘hello world,’ it produces exactly the same 256-bit value. This determinism is what makes verification possible: if you hash a file and get value X, and later hash the same file and get value X again, you know the file has not changed.

 

Pre-image resistance (one-way)

Given a hash value, it is computationally infeasible to find the original input that produced it. You cannot reverse a hash function to recover the original data. This property is what makes hash functions suitable for password storage: a database can store SHA-256 hashes of passwords without storing the passwords themselves.

 

Collision resistance

It is computationally infeasible to find two different inputs that produce the same hash value. A collision means two different messages produce identical hashes. For code signing, collision resistance is critical: an attacker who can find collisions in the hash algorithm could potentially create a malicious file with the same hash as a legitimately signed file. If collision resistance fails, the entire signing system becomes unreliable.

 

Avalanche effect

A small change in the input produces a completely different output. Changing a single bit in a file produces a hash value that is entirely different from the original. This property ensures that you cannot make subtle modifications to a signed file while keeping the hash the same. The avalanche effect is what makes hashing useful for tamper detection.

 

The avalanche effect is why code signing can detect even tiny modifications to a signed file. If an attacker modifies a single byte in a signed executable, the SHA-256 hash of the modified file is completely different from the hash recorded in the signature. Signature verification fails, and Windows reports the signature as invalid. Without this property, an attacker could make small changes to a signed binary while maintaining a valid signature.

 

How Hash Algorithms Work in Authenticode Code Signing

The Authenticode code signing process uses hash algorithms at multiple points. Understanding where each hash is used explains why the choice of hash algorithm matters.

 

Step 1: The file is hashed

When signtool signs a portable executable (PE) file, it computes a hash of specific parts of the file. PE files contain certain header fields that are expected to change during the signing process (notably the checksum field and the security directory location). These fields are excluded from the hash computation. Everything else in the file contributes to the hash.

The /fd flag in signtool specifies which hash algorithm to use for this file digest: /fd sha256 uses SHA-256 (the current standard), /fd sha1 uses SHA-1 (deprecated and should not be used for new signatures). The resulting hash value is a precise fingerprint of the signed file content.

 

Step 2: The hash is signed

The hash is then encrypted with the publisher’s private key using an asymmetric cryptographic algorithm (typically RSA). This produces the digital signature. The signature is the hash of the file, encrypted so that it can only be verified with the corresponding public key from the publisher’s code signing certificate.

The signature is not the file content encrypted: it is the hash of the file content encrypted. This is efficient: signing a small hash value is much faster than signing an entire large file, and the cryptographic security depends on the hash’s properties, not on the size of the original file.

 

Step 3: The signature is embedded

The signature (encrypted hash) and the publisher’s certificate chain are embedded in the PE file’s certificate table section, or placed in a catalog file that accompanies the executable. The file is now signed.

 

Step 4: Verification recomputes the hash

When Windows verifies an Authenticode signature, it recomputes the hash of the current file content using the same algorithm specified in the signature. It then decrypts the signature using the public key from the publisher’s certificate. If the recomputed hash matches the decrypted hash, the signature is valid: the file has not been modified since signing and was produced by the holder of the private key.

 

# The /fd flag specifies the file digest (hash) algorithm:

# SHA-256 is required for modern code signing:

signtool sign /fd sha256 /a /tr http://timestamp.digicert.com /td sha256 /v YourApp.exe

 

# The /td flag specifies the timestamp digest algorithm (should also be SHA-256):

# /fd sha256 = hash the file with SHA-256

# /td sha256 = hash the timestamp response with SHA-256

 

# Check which hash algorithm a signed file uses:

> Get-AuthenticodeSignature YourApp.exe | Select-Object -ExpandProperty SignerCertificate

# Or with certutil:

> certutil -verify -urlfetch YourApp.exe

# Look for: Hash algorithm = SHA256 (or sha1 for legacy signatures)

 

SHA-1 Deprecation: Why the Hash Algorithm Choice Matters

SHA-1 was the dominant code signing hash algorithm for many years. In February 2017, Google and CWI Amsterdam published a practical collision attack against SHA-1 called SHAttered. They demonstrated two different PDF files with identical SHA-1 hashes, proving that SHA-1 collision resistance had failed.

The SHAttered collision required approximately 6,500 CPU years of computation in 2017. That was already well within the reach of nation-state actors and large criminal organizations. As computing power increases and attack techniques improve, the cost decreases. SHA-1 cannot be considered collision-resistant for any security-relevant purpose.

The implications for code signing are direct: if an attacker can find two files with the same SHA-1 hash, they could potentially get a legitimate file signed, then substitute a file with the same hash. The signature would verify as valid against the malicious file. This attack is not trivially practical for arbitrary files but is a documented theoretical weakness that warrants using a stronger hash algorithm.

 

Microsoft’s SHA-1 deprecation timeline for Authenticode

Microsoft enforced SHA-1 deprecation for Authenticode in stages. Windows required SHA-256 signatures for code executed in Secure Boot-protected environments. Windows 10 and later versions show warnings for executables with SHA-1-only signatures. The specific enforcement depends on the Windows version and boot configuration, but the clear direction is that SHA-1 signatures are no longer acceptable.

Legacy software signed only with SHA-1 that still needs to run on modern Windows typically needs dual signing: a SHA-1 signature for backward compatibility with older Windows versions and a SHA-256 signature for modern Windows. The dual-signing approach uses signtool’s /as flag to append a second signature.

 

Hash Algorithms: Current Status for Code Signing

 

Algorithm Output size Status for code signing Notes
MD5 128 bits (32 hex chars) Broken: do not use Collision attacks demonstrated in 1994 and 2004. Never acceptable for code signing.
SHA-1 160 bits (40 hex chars) Deprecated: avoid for new signatures SHAttered collision attack (2017). Microsoft deprecated for Authenticode. May be needed for legacy compatibility only.
SHA-256 256 bits (64 hex chars) Current standard: use this Part of the SHA-2 family. No practical attack on collision resistance. Required by Microsoft for modern Authenticode.
SHA-384 384 bits (96 hex chars) Acceptable: stronger than required SHA-2 family. No practical attacks. Not typically required; SHA-256 provides sufficient security.
SHA-512 512 bits (128 hex chars) Acceptable: stronger than required SHA-2 family. No practical attacks. Larger output than necessary for most code signing contexts.
SHA-3 (Keccak) Variable (256/384/512 bits) Acceptable: not yet widely adopted in code signing NIST standardized 2015. Different internal structure from SHA-2. Not yet common in Authenticode workflows.

 

The Hash Algorithm in the Certificate Itself

Code signing certificates have their own signature hash algorithm, separate from the file digest algorithm. When a CA signs a certificate, it hashes the certificate’s contents and signs that hash with the CA’s private key. The hash algorithm used for this is recorded in the certificate’s Signature Algorithm field.

Modern code signing certificates use SHA-256 as their signature hash algorithm. Older certificates issued before 2014 or 2015 may have used SHA-1 as the certificate signature algorithm. This is a different question from the file digest algorithm: it affects how the certificate chain is verified, not how the file is hashed.

Windows evaluates both: the file digest algorithm (how the file was hashed for signing) and the certificate’s signature hash algorithm (how the certificate chain’s signatures are computed). A properly configured modern signature uses SHA-256 for both.

 

When checking a signed file’s hash algorithms, there are two separate places to look: the Digest Algorithm field in the file’s signature (which shows the /fd parameter used when signing) and the Signature Algorithm field in the signing certificate and the CA certificates in the chain. Both should show SHA-256 for a fully compliant modern Authenticode signature.

 

Using File Hashes for Manual Verification

Beyond Authenticode signing, hash algorithms are used directly by software publishers to provide checksums that users can verify before running downloaded software. Publishing SHA-256 checksums alongside download links allows security-conscious users to verify the file independently of the Authenticode signature.

# Compute the SHA-256 hash of a file (PowerShell):

> Get-FileHash .\Setup.exe -Algorithm SHA256

# Output: Algorithm  Hash                                                             Path

#         SHA256     A3B4C5D6E7F8… (64 hex characters)  .\Setup.exe

 

# Compute SHA-256 on Windows (certutil):

> certutil -hashfile Setup.exe SHA256

 

# Compute SHA-256 on Linux/macOS:

$ sha256sum Setup.exe

$ shasum -a 256 Setup.exe

 

Frequently Asked Questions

 

What is the difference between a hash and a checksum?

Checksum is a general term for any value computed from data that can detect changes. A simple checksum (like a sum of byte values) detects accidental corruption but is easy to forge: an attacker can modify a file and adjust other bytes to maintain the same checksum. A cryptographic hash function like SHA-256 is a specific type of checksum with security properties: pre-image resistance, collision resistance, and the avalanche effect. These properties make it resistant to intentional manipulation, not just accidental corruption.

 

Why does my signtool command need /fd sha256?

The /fd flag specifies the file digest algorithm: the hash algorithm used to hash the file’s content when creating the Authenticode signature. Without specifying /fd sha256, older versions of signtool default to SHA-1. Modern Windows requires SHA-256 signatures, and building with SHA-1 produces deprecated signatures that Windows may warn about or eventually refuse to validate. Always include /fd sha256 in signtool signing commands. Also include /td sha256 to specify that the timestamp response should also use SHA-256.

 

Can changing one bit in a signed file fool the hash verification?

No. The avalanche effect ensures that changing any part of a file produces a completely different hash value. If an attacker modifies even a single bit in a signed executable, the SHA-256 hash of the modified file is entirely different from the hash recorded in the signature. When Windows verifies the signature, it recomputes the hash from the current file content and compares it to the decrypted hash from the signature. The mismatch is detected immediately and the signature is marked invalid.


 

Published: Dec 2022   |   Last Reviewed: May 2026   |   Category: Cryptography / Hash Algorithms / SHA-256 / Code Signing / Authenticode

Previous Post
Next Post