CodeRigor

LESSON

Use a checksum without mistaking it for authentication

Calculate the complete SHA-256 digest and distinguish a trusted expected checksum from an attacker-supplied replacement.

A checksum answers whether bytes match an expected digest. The source of that expected value is part of the trust boundary.

This exercise supplies the SHA-256 calculation and asks you to complete the full comparison. It also demonstrates the limit: an attacker who can change a message and its advertised unkeyed checksum can keep that pair consistent.

A trusted expected value matters
start / 3
Exact payload bytes produce a digest. Comparison is useful only within the intended trust boundary for the expected digest.
A trusted expected value matters
Exact payload bytes produce a digest. Comparison is useful only within the intended trust boundary for the expected digest.

Hash the exact bytes, not a display string that has been trimmed, re-encoded or truncated. Return the complete SHA-256 result as lowercase hex. A prefix comparison or a shortened digest does not implement this contract.

Empty data is valid input and has a well-defined digest. Binary data does not need to be UTF-8 before hashing.

Go
package main
import ("fmt";"crypto/sha256";"encoding/hex")
func main(){
data:=[]byte{0,1,0,255};sum:=sha256.Sum256(data);fmt.Println(len(sum),len(hex.EncodeToString(sum[:])))
}

Suppose a trusted release channel gives you a checksum, and a separate download yields the bytes. Comparing them detects a mismatch against that trusted value. If an attacker controls both the download and its checksum source, the attacker can compute a replacement digest.

The same distinction applies to record payloads. A rolling hash, hash-table function or ordinary SHA-256 digest is not a keyed integrity scheme. Do not attempt to fix that by inventing a secret-prefix construction; use a standard MAC.

This checksum exercise does not claim to validate release signing, certificate trust, freshness or a human identity. The next lesson adds the missing shared secret for message authentication.

A forged checksum pair can still match
start / 3
An attacker changes the message and computes its new unkeyed digest. The pair verifies, but no secret or trusted origin was established.
A forged checksum pair can still match
An attacker changes the message and computes its new unkeyed digest. The pair verifies, but no secret or trusted origin was established.
Go
package main
import ("fmt";"crypto/sha256")
func main(){
altered:=[]byte("amount=99");advertised:=sha256.Sum256(altered);checked:=sha256.Sum256(altered);fmt.Println(advertised==checked)
}

Complete the comparison and test the published empty/abc digests, binary bytes and a changed payload. Explain why a recomputed checksum can pass without being an authentication failure in the checksum algorithm itself.

Next we use standard-library HMAC and its comparison function.

Actual Go verifier results · Public fixture key

A checksum can match while the record is rejected.

Choose an original or altered fixture. The replay recomputes an ordinary checksum of the shown payload, then runs the actual record verifier with its key, version and expected-context gates. This uses an intentionally public test key, never an application secret.

Payload bytes shown as textamount=99Caller expects lab.notes

Unkeyed checksum

Consistent

The advertised digest was computed from these bytes. This needs no secret and does not establish trusted origin.

Text
264c0e0d03dec862da5298c837428b4e1e5f6940f23234a51f7f371f062c06d6

Authenticated record

Rejected

The checksum matches the changed bytes, but the original HMAC no longer authenticates them.

Accepted payload outputNone — verification failed
Inspect the actual record fields
JSON
{
  "version": 1,
  "context": "lab.notes",
  "message": "YW1vdW50PTk5",
  "tag": "186780a104a57a54b70ce2db7f88b9e310874ecdd184a071e1af14fabde64b7e"
}

The record’s Base64 message remains readable. Acceptance means the complete format/context/MAC contract passed; rejection can occur before MAC comparison. This replay does not claim encryption, unique-sender identity or replay protection.

Download the CLI, published vectors and corruption tests →

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Optional expert discussion of how Go cryptography is engineered and tested. It supports the choice of maintained libraries; the course itself supplies the introductory explanations, vectors and complete lab.