DEV Community

Cover image for Beyond Checksums: Securing File Transfers with HMAC-SHA256
Aditya R
Aditya R

Posted on • Originally published at Medium

Beyond Checksums: Securing File Transfers with HMAC-SHA256

In my previous blog, we explored how to verify file integrity during transfers using SHA-256 checksums.
That approach is effective in ensuring the file is intact β€” but it has a limitation: anyone who can get hold of the file can also generate the same SHA-256 hash.

So how do we make it tamper-proof and also be able to verify authenticity without jumping to heavy public key cryptography?
The answer: HMAC-SHA256.

🧠 What is HMAC-SHA256?

HMAC stands for Hash-based Message Authentication Code.
It’s a cryptographic technique where:

  • You take your file (or message),
  • Combine it with a secret key that is known only to sender and receiver
  • Run it through a hashing algorithm like SHA-256. The result is a hash that can only be reproduced if you have both the exact file and the shared secret key.

Why this matters:
If an attacker changes the file, or tries to generate a fake hash without the secret key, the verification will fail.

βš™οΈ High-Level Workflow

Sender side:

  • Generate HMAC-SHA256 hash of the file using the shared secret key.
  • Send both the file and the generated HMAC hash.

Receiver side:

  • Recompute HMAC-SHA256 hash of the received file using the same key.
  • Compare it with the sent hash.
  • Match βœ… β†’ file is intact and authenticated. Mismatch ❌ β†’ file is tampered or key mismatch.

High Level Workflow

πŸ”‘ How to Generate the Secret Key

The security of HMAC entirely depends on the strength and secrecy of the key. A good secret key should:

  • Be long enough (at least 32 bytes for SHA-256).
  • Be generated using a cryptographically secure random generator.
  • Never be hardcoded in source code.
  • Be stored securely (e.g., in environment variables, secrets manager, or secure vault).

πŸ“Œ Example β€” Generate a Secret Key in Python

def generate_secret_key(key_outfile):
    # Generate a 32 byte(256-bit) random key
    key = secrets.token_bytes(32)
    encoded_key = base64.urlsafe_b64encode(key).decode()

    # Store the Key in a txt file for sharing it across 
    with open(key_outfile, "w") as fout:
        fout.write(encoded_key)

    print("Secret file generated")

# key_outfile is the file path to where the secret key is stored.
Enter fullscreen mode Exit fullscreen mode

The above code generates a random base64-encoded key and stores it in a file, which can then be shared securely between systems.

πŸ’‘ Pro Tip:
Use a Secrets Manager (like AWS Secrets Manager, HashiCorp Vault, Azure Key Vault) to store and retrieve the key securely.
Rotate keys periodically to minimize risk.

πŸ“Œ Example β€” Generating HMAC-SHA256 Hash in Python

# Function to generate the HMAC SHA-256 Hash 
def generate_hash(file_path, secret_key):
    with open(file_path, 'rb') as fin:
        file_data = fin.read()

    hash = hmac.new(secret_key.encode(), file_data, hashlib.sha256).hexdigest()
    return hash

# file_path : Path to the file for which hash is to be generated 
# secret_key : Secret Key to be used
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ Example β€” Verifying HMAC-SHA256 Hash in Python

# Function to verify the hash of the given file 
def verify_hash(file_path, secret_key, file_hash):

    # Compute the Hash of the File 
    calculated_hash = generate_hash(file_path=file_path, secret_key=secret_key)

    # Match the hash with the received hash 
    is_hash_valid = hmac.compare_digest(calculated_hash, file_hash)
    return is_hash_valid

# generate_hash Function as provided earlier
Enter fullscreen mode Exit fullscreen mode

βœ… Pros

Adds authentication: Ensures that only systems with the shared secret can generate the correct hash.
Simple to implement: Works with most programming languages and libraries.
Lightweight: No heavy cryptographic key pairs required.

❌ Cons

Key management: Both parties must securely store and protect the shared key.
Not for untrusted distribution: If the key is leaked, security is compromised.
Still no confidentiality: File content is not encrypted.

πŸ“Œ Ideal Use Cases

  • Internal file transfers between trusted systems that share a secure key.
  • Batch jobs or ETL processes where both ends are controlled environments.
  • Verifying sensitive configuration files or scripts within DevOps pipelines.
  • Ensuring authenticity of firmware updates within closed networks.

🧭 Final Thoughts

HMAC-SHA256 is a powerful upgrade from plain SHA-256 checksums, giving you both integrity and authenticity without overcomplicating the setup.
It’s a great fit for controlled environments where a shared secret can be securely managed.

Given that the secret needs to be securely shared and managed, in my next post, I will explore a way where the secret no longer needs to be shared.

I have posted the code in Github.

Top comments (0)