Integrity, Hashing and Code Signing

5 minutes 5 Questions

Integrity, in the CSSLP Secure Software Concepts domain, is one of the core security tenets (alongside confidentiality and availability) and refers to the assurance that data, code, and systems remain accurate, complete, and unaltered except by authorized parties through authorized means. For software, integrity means the application and its data have not been tampered with, corrupted, or modified maliciously or accidentally during development, transmission, storage, or execution. Loss of integrity can result in backdoors, logic bombs, corrupted databases, or trojanized binaries. Hashing is a primary mechanism for verifying integrity. A cryptographic hash function (such as SHA-256 or SHA-3) takes input of any size and produces a fixed-length digest. Secure hash functions exhibit key properties: they are one-way (pre-image resistant), so the original input cannot be derived from the digest; they are collision resistant, meaning it is computationally infeasible to find two inputs producing the same hash; and they demonstrate the avalanche effect, where a tiny change in input drastically changes the output. By comparing a computed hash against a known-good value, developers and users can detect unauthorized modification. Deprecated algorithms like MD5 and SHA-1 should be avoided because of demonstrated collision attacks. Hashing is also used for secure password storage (with salting) and in HMACs for message authentication. Code signing extends hashing by adding authenticity and non-repudiation. The developer or vendor computes a hash of the software and encrypts that hash with their private key, creating a digital signature embedded in or attached to the code. Recipients use the publisher's public key, validated through a certificate issued by a trusted Certificate Authority, to decrypt the signature and compare it against a freshly computed hash. A match confirms both that the code has not been altered and that it genuinely originated from the claimed publisher. Code signing is essential for secure software distribution, patch management, mobile app stores, driver installation, and defending the software supply chain against tampering.

Integrity, Hashing and Code Signing (CSSLP Domain 1: Secure Software Concepts)

Why This Topic Matters
Integrity is one of the three pillars of the CIA triad (Confidentiality, Integrity, Availability) and is a core security concept in CSSLP Domain 1. For a software professional, integrity is not an abstract idea: it is the assurance that code, data, configuration files, updates and build artifacts have not been altered, accidentally or maliciously, from their intended state. Supply-chain attacks such as SolarWinds, tampered open-source packages, and malware that patches legitimate binaries all exploit a failure of integrity. The CSSLP exam expects you to understand how integrity is achieved technically (hashing, message authentication codes, digital signatures, code signing) and how those mechanisms fit into the software development life cycle (SDLC), from source control through build, release, deployment and update.

What Integrity Means in Secure Software
Integrity is the property that information and systems are accurate, complete and have not been modified in an unauthorized manner. In software security it has several faces:
• Data integrity: stored or transmitted data remains unchanged except by authorized processes.
• Code integrity: executables, libraries, scripts and firmware are exactly what the publisher released.
• System integrity: the running environment (OS, configuration, dependencies) has not been tampered with.
• Referential and semantic integrity: data relationships and business rules remain consistent (often enforced through database constraints and input validation).
Closely related concepts you must be able to distinguish: authenticity (proof of origin, who created or sent it), non-repudiation (the originator cannot later deny having created or sent it), and availability (the resource is accessible when needed). Hashing alone provides integrity. Adding a key (MAC/HMAC) adds authenticity. Adding asymmetric cryptography (digital signatures) adds authenticity and non-repudiation.

Hashing: The Foundation of Integrity Checking
A cryptographic hash function takes an input of arbitrary length and produces a fixed-length output called a hash, digest, fingerprint or checksum. Properties the exam expects you to know:
• Deterministic: the same input always yields the same output.
• Fixed length: SHA-256 always produces 256 bits regardless of input size.
• One-way (pre-image resistance): given a hash, it is computationally infeasible to find the original input.
• Second pre-image resistance: given an input, it is infeasible to find a different input with the same hash.
• Collision resistance: it is infeasible to find any two different inputs that produce the same hash.
• Avalanche effect: a one-bit change in input produces a drastically different digest.
• Fast to compute (which is why plain hashes are a poor choice for password storage without salting and key stretching).

Common algorithms: MD5 (128-bit, broken, collisions are trivial, do not use for security), SHA-1 (160-bit, deprecated, practical collisions demonstrated in 2017), SHA-2 family (SHA-224, SHA-256, SHA-384, SHA-512, currently recommended), SHA-3 (Keccak-based, approved alternative), and specialized password hashing functions such as bcrypt, scrypt, PBKDF2 and Argon2 which deliberately add salt and computational cost.

How hashing is used for integrity: the publisher computes a digest of a file and publishes it. The recipient recomputes the digest and compares. If they match, the file is unchanged. The weakness: a plain hash proves integrity only if the hash itself is obtained through a trusted channel. If an attacker can replace both the file and the posted hash, the check is defeated. This limitation is exactly why MACs and digital signatures exist.

Hashing vs. Encryption vs. Encoding
Exam questions often test this distinction. Encoding (Base64, URL encoding) is reversible and provides no security. Encryption is reversible with a key and provides confidentiality. Hashing is one-way and provides integrity. If a question asks how to verify a downloaded file has not changed, the answer involves hashing, not encryption.

Salting and Password Hashing
A salt is a random value appended to input before hashing so identical passwords produce different hashes and precomputed rainbow tables are useless. A pepper is a secret value stored separately from the database. Key stretching (iterating the hash thousands of times) slows brute-force attacks. On the exam, if the scenario is storing passwords, prefer bcrypt, scrypt, PBKDF2 or Argon2 with a unique salt per user over a single SHA-256 pass.

Message Authentication Codes (MAC and HMAC)
A MAC combines a shared secret key with the message to produce a tag. HMAC (Hash-based MAC, e.g., HMAC-SHA256) is the most common construction. Because only parties holding the key can produce a valid tag, HMAC provides integrity and authenticity. It does not provide non-repudiation because both sender and receiver share the same key, so either could have produced the tag. HMACs are used in API request signing, session tokens, JWTs (HS256), and protecting cookies from tampering.

Digital Signatures
A digital signature uses asymmetric cryptography. Process:
1. The signer computes a hash of the message or code.
2. The signer encrypts that hash with their private key, producing the signature.
3. The recipient recomputes the hash of the received content.
4. The recipient decrypts the signature with the signer's public key and compares the two hashes.
If they match, the content is unaltered (integrity), it came from the holder of the private key (authenticity), and the signer cannot deny signing it (non-repudiation). Common algorithms: RSA, DSA, ECDSA, EdDSA (Ed25519). Remember the key direction: sign with private, verify with public; encrypt with recipient's public, decrypt with recipient's private.

Code Signing
Code signing is the application of digital signatures to software artifacts: executables, installers, drivers, libraries, scripts, mobile apps, container images, firmware and packages. Its purpose is to let operating systems, browsers, app stores and users verify that code came from a known publisher and has not been modified since signing.

How it works end to end:
1. The publisher obtains a code-signing certificate from a Certificate Authority (CA) after identity validation (Standard or Extended Validation). The certificate binds the publisher's identity to a public key through PKI.
2. During the release process, the build system hashes the artifact and signs the hash with the publisher's private key. The signature and certificate are embedded in or attached to the file (Authenticode for Windows PE files, codesign for macOS and iOS, jarsigner for Java, GPG signatures for Linux packages, Sigstore/cosign or Docker Content Trust for container images).
3. Optionally, a timestamp from a trusted Timestamp Authority (TSA) is added so the signature remains valid after the certificate expires, proving the code was signed while the certificate was valid.
4. At install or load time, the platform verifies the certificate chain to a trusted root, checks revocation status (CRL or OCSP), recomputes the hash and verifies the signature. Mismatches or untrusted publishers produce warnings or block execution (for example, Windows SmartScreen, macOS Gatekeeper, driver signature enforcement, Secure Boot).

Private key protection is the critical control. If an attacker steals a code-signing key, they can produce malware that appears legitimate (Stuxnet used stolen certificates). Best practices: store keys in Hardware Security Modules (HSMs) or cloud key vaults, require multi-person authorization for release signing, keep signing servers isolated from developer workstations, use short-lived or ephemeral signing where possible, audit every signing event, and have a revocation plan. Industry baseline requirements now mandate hardware-protected keys for publicly trusted code-signing certificates.

Integrity Throughout the SDLC
The CSSLP expects you to connect these mechanisms to lifecycle phases:
• Requirements: capture integrity requirements explicitly (what must be tamper-evident, what level of assurance, regulatory drivers).
• Design: choose algorithms (SHA-2/SHA-3, HMAC, RSA/ECDSA), decide where verification happens, design secure update mechanisms that validate signatures before applying.
• Implementation: use vetted cryptographic libraries, never roll your own hash or signature code, use constant-time comparison to avoid timing attacks on MAC verification.
• Source control: signed commits and tags, protected branches, code review.
• Build and dependencies: pin dependency versions, verify hashes of downloaded packages (lock files), generate a Software Bill of Materials (SBOM), reproducible builds, sign build outputs; frameworks like SLSA describe levels of supply-chain integrity.
• Release and deployment: code signing with HSM-protected keys, timestamping, publishing hashes over authenticated channels, secure update channels that reject unsigned or downgraded versions.
• Operations: file integrity monitoring (Tripwire-style baselines), runtime application integrity checks, Secure Boot and measured boot, revocation handling.

Common Threats Against Integrity
Man-in-the-middle modification of downloads, tampered update servers, dependency confusion and typosquatting in package repositories, compromised build pipelines, stolen signing keys, hash collision attacks against weak algorithms (MD5, SHA-1), downgrade attacks that force use of unsigned legacy versions, and TOCTOU (time-of-check to time-of-use) races where a file is verified and then swapped before use. Countermeasures map directly to the mechanisms above.

Exam Tips: Answering Questions on Integrity, Hashing and Code Signing
1. Map the requirement to the mechanism. If the question asks only whether data changed, the answer is a hash. If it asks whether data changed and came from a trusted party sharing a secret, the answer is HMAC. If it requires proof of origin that cannot be denied, the answer is a digital signature or code signing. Non-repudiation always implies asymmetric cryptography and a private key.
2. Know the key directions cold. Signing uses the sender's private key; verification uses the sender's public key. Questions frequently swap these to create distractors.
3. Reject deprecated algorithms. Any answer recommending MD5 or SHA-1 for new security functions is wrong. Prefer SHA-256 or stronger, SHA-3, and for passwords bcrypt, scrypt, PBKDF2 or Argon2 with salts.
4. Hashing is not encryption. If an option suggests decrypting a hash or recovering the original from a digest, eliminate it. Hashes are one-way.
5. A published hash alone is only as trustworthy as its channel. If the scenario has the hash hosted on the same compromised server as the file, the correct improvement is a digital signature or distributing the hash through an independent authenticated channel.
6. Code signing proves publisher identity and non-modification, not that code is safe or bug-free. Watch for options that overstate what a signature guarantees. Signed malware exists.
7. Protect the private key. When a question asks for the most important control in a code-signing program, the answer usually involves HSM storage, restricted access, separation of duties and auditing of the signing key, not the algorithm choice.
8. Timestamping is the answer to why a signature should remain valid after the certificate expires.
9. Revocation matters. If a key is compromised, the correct response includes revoking the certificate, re-signing legitimate code with a new key and notifying users, not simply issuing a patch.
10. Think lifecycle. CSSLP favors answers that build integrity in early (requirements and design) and enforce it in the pipeline (signed commits, verified dependencies, signed builds) over answers that only add a check at the end.
11. Secure updates should verify the signature before installation, use an authenticated channel, and prevent downgrade to older vulnerable versions.
12. Watch for the best answer, not just a correct one. Several options may improve integrity; pick the one that most directly addresses the specific property the question names (integrity, authenticity or non-repudiation) with the least complexity and strongest assurance.
13. Vocabulary precision. Digest, hash, fingerprint and checksum are often used interchangeably, but a CRC checksum detects accidental errors and is not cryptographically secure; a cryptographic hash resists intentional tampering.
14. Salting is about uniqueness, not secrecy. Salts can be stored in plaintext next to the hash; their job is to defeat precomputation. A pepper is the secret component.

Quick Reference Summary
• Hash: integrity only, one-way, fixed length, use SHA-2 or SHA-3.
• HMAC: integrity plus authenticity, shared secret key, no non-repudiation.
• Digital signature: integrity plus authenticity plus non-repudiation, private key signs, public key verifies.
• Code signing: digital signatures applied to software, backed by PKI certificates, timestamped, verified at install or load, dependent on rigorous private key protection.
• In the SDLC: define integrity requirements, design verification points, use vetted libraries, sign commits and artifacts, verify dependencies, protect keys in HSMs, monitor integrity in operations.
Master these distinctions and you will be able to dissect almost any CSSLP question on this topic by identifying which security property is being asked for and selecting the mechanism that delivers exactly that property.
Test mode:
More Integrity, Hashing and Code Signing questions
20 questions (total)