What you’ll take away
- A plain SHA-256 match establishes consistency with an expected digest; authenticate the reference separately when publisher provenance matters.
- Hash the exact artifact using the named algorithm and compare the complete digest.
- Identical bytes under another filename keep their digest, while the demonstrated LF-to-CRLF change produces a different digest.
- An archive and its extracted members have different hashing boundaries, even when their payloads agree.
- Record signature trust, file-match results, and tool errors separately so “verified” has a precise meaning.
A matching number answers only part of the download question
You download a file, calculate its SHA-256 checksum, and find that it matches the number beside the download link. That is useful evidence: the bytes you checked are consistent with that reference value. But it leaves another question open: who supplied the reference, and why should you trust it? A plain checksum does not contain a publisher’s identity or a signature. GnuPG’s download guidance explains the weakness of obtaining a file and its checksum through a source that could change both. Ubuntu’s verification tutorial separates checking a signed checksum file from comparing the downloaded image with the checksum. Those are two connected checks, not one. [3][4]
This distinction is useful for software downloads, shared archives, and files copied between storage locations. Sometimes the goal is simply to detect an incomplete copy. Sometimes it is to establish that the file agrees with a particular publisher’s release. The required reference evidence differs. We will follow both questions and use a small local experiment with invented text and ZIP files to show exactly what changes a file digest. No software release is being certified by that experiment. The central habit is to keep the measured byte comparison and the reason for trusting its expected value together in the record.
A successful SHA-256 comparison establishes agreement between a computed digest and an expected digest under the selected algorithm. Its practical integrity value depends on the reference and the cryptographic assumptions, while its provenance value depends on how that reference was authenticated. An unkeyed file hash does not independently authenticate a publisher. GnuPG’s integrity guidance explicitly identifies the problem of an adversary modifying both a downloadable file and the checksum shown with it; Ubuntu demonstrates a workflow that authenticates a checksum manifest before checking an image against its entry. The integrity comparison and reference authentication have different roles. [1][3][4]
The article distinguishes byte identity evidence, release selection, and publisher authentication rather than treating “verified” as one undefined status. Its only executed examples use explicitly specified local text bytes and two constructed ZIP containers. They test how those bytes and container metadata affect digests; they do not verify a third-party signature or establish software safety. The same boundary discipline applies when comparing a stored backup, a downloaded installer, or an archive rebuilt from extracted files. Before interpreting a match, identify the exact artifact, algorithm, expected value, and evidence connecting that value to the intended source.
SHA-256 summarizes bytes, not a filename or a promise
SHA-256 produces a 256-bit digest. Written in the usual hexadecimal form, that is 64 characters, because each hexadecimal character represents four bits. GNU’s SHA-2 documentation identifies the 256-bit output, and Microsoft’s Get-FileHash documentation explains that the calculation concerns file contents rather than the file’s name or extension. A file called invoice.pdf can therefore be renamed without changing its content hash. Conversely, keeping a familiar filename does not preserve the content that was originally inside it. The name helps you select a file; the digest is calculated from the bytes you actually read. [1][2]
A cryptographic hash is designed to make it computationally infeasible to find different inputs with the same digest. That is a practical security property, not a mathematical promise that every possible file has a unique number. There are more possible files than fixed-length digest values, so collisions must exist in principle. For ordinary SHA-256 verification, a full match is strong evidence of agreement with the expected bytes, provided the reference and calculation are trustworthy. It still does not tell you whether the file is useful, safe to run, or published by the person whose name appears next to the download. [1][2][3]
GNU documents SHA-256 as producing 256 bits. Its conventional hexadecimal representation has 256/4 = 64 digits, while the raw digest occupies 32 bytes. Microsoft describes Get-FileHash as computing a value from file or stream contents, with SHA256 as its default algorithm. Filesystem names and extensions are outside that content calculation. This distinction concerns the bytes passed into the function; metadata embedded inside a file or archive is part of those bytes and therefore inside the hashing boundary. Selecting a path and hashing the file reached by that path are related operations with different meanings. [1][2]
Fixed output length cannot provide a one-to-one mapping for the unbounded set of possible input files. The relevant cryptographic property is computational infeasibility of finding a collision, as Microsoft states in its algorithm description. A digest match should consequently be described as strong cryptographic consistency evidence, not a logical theorem that no other input could share the value. The trustworthiness of the expected digest is a separate requirement: an attacker who may replace the reference does not need to defeat collision resistance. They can choose different bytes and publish the ordinary digest of those bytes. This is the reference-authentication problem identified by GnuPG. [1][2][3]
The same visible word can have different file bytes
The local example starts with the five ASCII letters orbit followed by a line feed. Its six bytes, written in hexadecimal, are 6f 72 62 69 74 0a. A second file contains the same letters followed by carriage return and line feed: 6f 72 62 69 74 0d 0a, seven bytes. A third file has a different filename but exactly the same six bytes as the first. We calculated SHA-256 for all three. The first and third matched; the seven-byte file differed. These are actual calculations on deliberately tiny example files, with the complete inputs specified here.
The result explains why looking at the word in a text editor can miss a relevant difference. The editor may display both endings as a new line, but the hash reads different byte sequences. Meanwhile, a filename change alone does not enter the content digest, consistent with Microsoft’s documentation. If a downloaded text file has been resaved, transformed, or copied through a tool that changes its bytes, compare the resulting artifact with the appropriate reference. A checksum for the original downloaded bytes is not automatically a reference for an edited or transformed version, even when the text appears unchanged. [1]
The executed byte-level example used input A = 6f 72 62 69 74 0a, input B = 6f 72 62 69 74 0d 0a, and input C identical to A under another filesystem name. Python’s local SHA-256 computation produced equal digests for A and C and a different digest for B. A and C contain six bytes; B contains seven. The representation here specifies the full inputs rather than relying on a platform’s text-file creation defaults. The only demonstrated transformation between A and B is insertion of the carriage-return byte before the line feed.
This separates content-level differences from path labels. A text viewer’s treatment of line endings does not establish byte equality, while the external filename is not part of Get-FileHash’s documented content input. The same reasoning applies whenever a workflow changes an encoding, adds a marker, or rewrites a file: the reference must describe the resulting bytes if that is the artifact being verified. No claim is needed that every transformation is malicious or that a hash identifies which transformation occurred. The digest comparison reports agreement or disagreement; identifying the specific difference requires inspecting the files or the transformation history. [1]
Match the algorithm and the exact release artifact first
A release page may list several downloads: different operating systems, processor types, packaging formats, or versions. Choose the checksum entry for the exact artifact you intended to download. Ubuntu’s tutorial makes this concrete with a SHA256SUMS file containing entries for available images and a separate signature for that file. Selecting a checksum from the wrong release creates a mismatch even if both downloads are legitimate. Keep the filename, release identity, algorithm, and expected digest together rather than copying a number away from the context that explains what it describes. [1][4]
Compare the complete digest using the named algorithm. The first few characters are only a prefix, not a substitute for the full SHA-256 value. Uppercase and lowercase hexadecimal letters represent the same digits, but a different algorithm is not a different spelling of the same calculation. Microsoft’s tool can calculate several algorithms and reports which one it used, while GNU provides separate SHA-2 utilities for different digest lengths. A screenshot showing only part of a hash or omitting the algorithm leaves a weaker verification record. File size is useful context too, but equal size does not establish equal contents. [1][2]
The reference must bind the intended artifact to a specified digest algorithm and value. A checksum manifest often associates multiple filenames with digests; Ubuntu’s documented SHA256SUMS workflow is a concrete example. Selecting the correct release, architecture, and packaging variant is a separate step from computing the local digest. A correctly calculated mismatch against the wrong entry is still the wrong comparison. Preserve the manifest entry or release record with the result so that the expected value can be traced back to the artifact definition rather than treated as an unexplained hexadecimal string. [1][4]
For hexadecimal SHA-256 output, compare all 64 digits after accounting for equivalent letter case and the tool’s documented representation. Prefix agreement discards most of the digest and does not establish full agreement. Microsoft’s returned object includes the path, algorithm, and hash; GNU’s SHA-2 family includes different algorithms with different output lengths. Those fields should not be collapsed into one unlabeled “checksum.” The file length may help identify an incomplete or mistaken artifact, but many different byte strings share the same length. It is therefore supplementary evidence, not a replacement for the intended full-digest comparison. [1][2]
A mismatch is a finding, not yet an explanation
When the correctly selected SHA-256 values differ, the file does not pass that comparison. Check the straightforward causes before assigning a story: the wrong release entry, an incomplete download, a file changed after downloading, or a transformation such as the line-ending change in our example. Ubuntu lists alteration and incorrect downloading among reasons an image can fail its checksum comparison. The digest does not distinguish those causes by itself. It also does not tell you how many bytes differ or where they are. It answers whether the computed value agrees with the expected one. [1][4]
Keep the actual values and artifact details so the mismatch can be investigated. If the file is meant to be installed or executed, resolve the failed comparison before treating it as the verified release. A fresh copy obtained through the publisher’s established distribution route can help check whether the earlier copy was incomplete, but changing the expected value just to match the file proves nothing about the intended release. A missing file, unreadable path, or tool error is a different result again: the check may not have completed at all. Successful verification requires a successful computation and the intended comparison, not merely the absence of a visible complaint. [1][4]
For a correctly selected algorithm and reference, differing digests establish failure of the expected byte-consistency check. They do not classify the cause as corruption, tampering, version mismatch, or text conversion. Ubuntu’s guidance explicitly identifies alteration or incorrect downloading as possible causes, while the local LF/CRLF example supplies another fully specified transformation. The digest has no built-in explanation field. To locate or explain a difference, use artifact metadata, byte comparison, transfer history, or another appropriately scoped observation rather than inferring an attack from the checksum result alone. [1][4]
The diagnostic record should retain the computed value, expected value, algorithm, artifact identity, and whether the operation completed successfully. A path failure or unreadable file is not a cryptographic mismatch, and a comparison against the wrong release does not test the intended release. Recomputing an expected digest from the suspect artifact changes the question to self-consistency and discards the original reference. For an installation workflow, preserve the unresolved state until the intended reference comparison succeeds. That keeps the operational decision tied to the evidence already requested, rather than treating an arbitrary recalculated value as publisher approval. [1][4]
A replacement reference can make a replacement file match
Imagine that the intended release is file A and its published checksum is H(A). Someone changes the download to file B and also replaces the displayed checksum with H(B). Your calculator can work perfectly and report a match for B. No special weakness in SHA-256 is required: the replacement reference describes the replacement bytes. GnuPG’s integrity page warns about this same dependence when the download and the displayed checksum can both be modified. The problem is the authority of the expected value, not a failure to calculate it correctly. [3]
For a simple copy check, you might already possess a trusted original and calculate its digest before moving it. For a software release, you need a reference connected to the publisher’s established distribution process. A signed checksum manifest is one method, provided you verify it using the correct authenticated signing key. Ubuntu demonstrates that two-stage arrangement. The label “official checksum” written on an arbitrary page cannot supply the missing connection by itself. Ask where the expected value came from and what evidence makes it the right reference for this particular release. [3][4]
Let an intended artifact A have expected digest H(A). If an adversary can replace both the artifact and its reference, they can publish B together with H(B). A local implementation computes H(B) and correctly finds equality. This construction requires no collision between H(A) and H(B), no recovery of A from its digest, and no attack on the hash function. It changes the authenticated-reference problem while leaving the digest algorithm intact. GnuPG explicitly describes the ease of modifying a checksum alongside a modified download as the limitation of relying on that shared distribution path. [3]
The necessary reference evidence depends on the task. An independently retained digest of a trusted original can support later byte-consistency checks. For publisher provenance, the reference must instead be bound to the intended release authority, for example through a correctly authenticated signature over a checksum manifest. Ubuntu’s workflow separates that authentication from the subsequent image-digest comparison. A match against an unauthenticated manifest establishes consistency with that manifest; it does not upgrade the manifest’s trust status. Keeping those conclusions separate prevents successful arithmetic from being mistaken for successful source authentication. [3][4]
A signature needs the right key, not just a reassuring label
A signed manifest adds another object to check. In Ubuntu’s example, SHA256SUMS contains image checksums and SHA256SUMS.gpg supplies the signature for that checksum file. The verifier checks the signature, then the image is compared with the appropriate entry. This lets the download’s byte check depend on an authenticated statement about the expected bytes. The workflow still needs the correct signing key and the correct release entry. A file bearing the expected signature filename is not enough; its signature must actually verify under the intended key. [3][4]
GnuPG distinguishes a valid signature from confidence that the key belongs to the intended signer. Its guidance explains why a “Good signature” message can appear alongside a warning that the key’s identity has not been established, and recommends comparing fingerprints through trusted evidence. Do not replace that step with a familiar-looking name attached to a key. Use the publisher’s current verification instructions and an already trusted verification tool; the historical key identifiers shown in tutorials are examples, not instructions to trust those identifiers forever. A correctly authenticated signature supports provenance, while the separate digest comparison checks the selected downloaded artifact. [3][4]
In the documented Ubuntu arrangement, the detached signature authenticates the SHA256SUMS manifest, which in turn supplies the digest for an image. Verification therefore has two bindings: the signed bytes must validate under the intended authenticated signing key, and the downloaded artifact must match its selected manifest entry. Neither operation replaces the other. A valid signature over a different release manifest does not select the intended artifact, while an artifact digest matching an unsigned replacement manifest does not authenticate the publisher. The file and signature names are input selection aids, not proofs of those bindings. [3][4]
GnuPG’s guidance separates cryptographic signature validity from key identity and trust. A valid signature under an unestablished key can still produce a warning, so a successful signature calculation does not by itself certify the displayed user identity. The relevant fingerprint must be authenticated through an appropriate trusted source or established trust arrangement. GnuPG also recommends using an existing trusted verifier instead of the newly downloaded program to verify that program. The examples in the cited pages include historical keys and releases; the article uses their trust distinctions, leaving current publisher-specific key selection to current official verification instructions. [3]
An archive hash and its extracted-file hash cover different bytes
The second local experiment created two ZIP archives. Each contained one member called note.txt with the same six bytes used earlier: orbit followed by a line feed. Both archives were 120 bytes long and used stored, uncompressed content. The first recorded an entry timestamp of 1 January 2000; the second recorded 2 January 2000. Their outer SHA-256 values differed. Reading note.txt from each archive produced identical bytes and matching payload digests. Python’s ZIP documentation identifies member timestamps as archive metadata and provides separate operations for writing an archive and reading a member’s bytes. [5]
This shows why two archives can carry the same text without being the same downloadable file. Their metadata belongs to the archive’s byte sequence. Renaming the outer archive on disk leaves that sequence alone, while rebuilding the archive or changing information stored inside it can change the sequence. If a publisher supplies a checksum for the ZIP download, hash that ZIP. Hashing only an extracted member answers a narrower question about that member. Likewise, a checksum for an unpacked file is not interchangeable with a checksum for its containing archive, even when both values were calculated correctly. [1][5]
The executed container example used Python 3.12.14 to create two ZIP_STORED archives, each containing note.txt with payload 6f 72 62 69 74 0a. The only deliberately changed member attribute was its date_time tuple: (2000, 1, 1, 0, 0, 0) versus (2000, 1, 2, 0, 0, 0). Both outer files were 120 bytes, but their SHA-256 digests differed. Reading the member from both returned the same six payload bytes and equal payload digests. Python documents the member timestamp field and the read/write interfaces used to construct and inspect this case. [5]
The hashing boundary explains the result. Archive headers and directory metadata are part of the outer file’s input bytes, whereas a hash over a returned member payload excludes the surrounding container representation. Filesystem renaming outside the archive does not change those stored bytes; an internal member-name or timestamp change can. The appropriate comparison must therefore state whether it covers the release container, a particular extracted member, or another explicitly defined artifact. Agreement at one boundary should not be reported as agreement at a broader boundary that was never compared. This is especially relevant when someone rebuilds a package and expects its original download checksum to remain applicable. [1][5]
Use the tool’s result, including errors and the named file
For a local file in PowerShell, an explicit example is Get-FileHash -LiteralPath './download.bin' -Algorithm SHA256. Replace that example path with the intended file. Microsoft documents LiteralPath as using the supplied path without wildcard interpretation, and the returned object includes the algorithm, hash, and path. GNU’s sha256sum download.bin similarly calculates the SHA-256 digest for the named file. These examples read and hash files; a downloaded executable does not need to be run to calculate its checksum. Compare the result with the complete expected value for that artifact. [1][2]
When checking a compatible manifest with GNU’s sha256sum --check SHA256SUMS, read the named-file results and any errors. The documented common options distinguish successful matches, mismatches, unreadable files, and invalid input. A quiet mode can suppress successful messages, while other options affect which missing files are reported, so silence alone is not a reliable interpretation. An automated workflow should use the documented completion status and ensure the intended artifact was actually included. A copied “OK” line for a different file does not verify the file you planned to use. [2][6]
The PowerShell expression Get-FileHash -LiteralPath './download.bin' -Algorithm SHA256 makes both the target and algorithm explicit. LiteralPath avoids treating path characters as wildcards; the returned object identifies the path, algorithm, and computed value. GNU’s sha256sum names the SHA-256 algorithm directly and accepts a file argument. These are content-reading operations, so checksum computation is independent of executing the file’s payload. For a reproducible record, preserve the resolved artifact and the tool’s successful result rather than copying the digest into a context-free note. [1][2]
GNU’s documented --check behavior reads filenames and expected checksums from a manifest and compares the named files. Its common options describe failures for unreadable files, inconsistent digests, or no valid input, along with output-suppression and malformed-line controls. Interpret the completion status according to the actual options, and verify that the intended entry was processed. Filtering output down to a success word can discard failures elsewhere in a multi-file manifest. Conversely, an intentionally quiet successful run can produce little output. The evidence is the completed, correctly scoped check, not the presence or absence of one reassuring console string. [2][6]
Make the final conclusion as specific as the evidence
A useful verification record answers five questions: which artifact was checked, which algorithm was used, where the expected value came from, whether that reference was authenticated as needed, and whether the complete comparison succeeded. If a signature was involved, keep its outcome and the basis for trusting the signing key separate from the file’s checksum result. If only one member of an archive was hashed, say so. These details make “verified” understandable to someone who did not watch the check happen, and they make a later mismatch easier to investigate. [1][3][4][6]
Then keep the conclusion at that boundary. A match against a trusted release reference supports that the checked bytes agree with that release. It does not review the program’s behavior, establish that the release is the newest one, or promise that the file will remain unchanged afterward. Our small experiments show why the byte boundary matters: an external filename can change without changing the digest, a line ending can change it, and archive metadata can change the outer digest while preserving an inner file. The value of the checksum comes from combining that precise comparison with the right reference, not from the impressive length of the number. [1][3][4][5]
A complete record preserves artifact identity and scope, digest algorithm and representation, expected-value provenance, authentication result where required, and the completed comparison outcome. For signed manifests, retain the distinction between signature validity under a key and authentication of that key as the release authority. For container or transformed-file workflows, state which byte sequence the expected digest describes. Those fields allow the verification to be reproduced or audited at the same boundary and prevent a narrow successful check from silently becoming a broader claim. The framework follows the documented separation of content hashing, manifest checking, and signature trust. [1][3][4][5][6]
The defensible result is time- and artifact-specific: the bytes read for the calculation agreed with the intended reference under the selected algorithm and stated trust assumptions. The digest does not analyze executable semantics, determine release freshness, or bind a path forever to those bytes. Those are separate questions. The executed examples isolate three consequences of the byte model—external-name independence, line-ending sensitivity for the stated inputs, and container-versus-member scope—while the signed-manifest workflow supplies the missing provenance mechanism. Together they explain why a full checksum match is valuable and why its expected value must remain attached to a credible source. [1][2][3][4][5]
Sources & further reading
Explore the references behind this guide. External pages may change after our review.
- Get-FileHash (Microsoft.PowerShell.Utility) - PowerShell | Microsoft LearnMicrosoft · Accessed 6 Nov 2026
- sha2 utilities (GNU Coreutils 9.12)GNU Project · Accessed 6 Nov 2026
- GnuPG - Integrity CheckGnuPG · Accessed 6 Nov 2026
- How to verify your Ubuntu download | UbuntuCanonical · Accessed 6 Nov 2026
- zipfile — Work with ZIP archives — Python 3.15.2 documentationPython Software Foundation · Accessed 6 Nov 2026
- cksum common options (GNU Coreutils 9.12)GNU Project · Accessed 6 Nov 2026
Article updated 6 Nov 2026.
Found something we should revisit?
Good explanations get better with thoughtful feedback.