Hashing algorithms map arbitrary input to a fixed-length digest. A digest is not a unique identifier, encryption, or proof of authenticity by itself: collisions exist in every finite output space, low-entropy inputs can be guessed, and an attacker who can replace both a file and its unauthenticated checksum can defeat an integrity check.

📋 Table of Contents

Key Takeaways

  • Security properties are conditional: Pre-image, second-preimage, and collision resistance are distinct properties, and none makes a low-entropy secret unrecoverable.
  • Fast is not always desirable: SHA-2/SHA-3 are designed for general-purpose hashing; password storage needs a tunable, memory-hard or deliberately expensive KDF.
  • MD5/SHA-1 are legacy: Their collision weaknesses rule them out for adversarial integrity and signatures, though MD5 may still appear as an untrusted accidental-error checksum.
  • Applications need an authentication boundary: A checksum detects changes only when the expected digest is trusted; signatures or MACs provide stronger authenticity semantics.
  • Hashing vs. Encryption: Hashing is a one-way function for integrity, while encryption is a two-way function for confidentiality.
  • Choosing an Algorithm: Select an approved construction for the exact protocol, and calibrate password KDF parameters on production-like hardware.

What is a Hashing Algorithm?

A hashing algorithm is a mathematical function that takes an input (or 'message') and returns a fixed-size string of bytes. The output, known as the hash value or digest, appears random and changes significantly with even minor input modifications.

Key Characteristics of Hash Functions

  1. Deterministic: Same input always produces the same output.
  2. Fixed Size: Output length is constant regardless of input size.
  3. Construction-dependent cost: General hashes are fast; password KDFs intentionally consume time and memory.
  4. Pre-image Resistance: Difficult to reverse-engineer the input from the output.
  5. Avalanche Effect: Small input changes produce drastically different outputs.
  6. Collision Resistance: Difficult to find two different inputs with the same output.

Common Hashing Algorithms

Here’s a look at some of the most well-known hashing algorithms and their current security status.

MD5 (Message-Digest Algorithm 5)

  • Output Size: 128 bits
  • Security Status: ❌ Broken
  • Use Case: Do not use for signatures, password storage, or adversarial integrity. It may remain only for non-adversarial legacy checksums with explicit documentation.

SHA-1 (Secure Hash Algorithm 1)

  • Output Size: 160 bits
  • Security Status: ❌ Deprecated
  • Use Case: Do not use for new signatures or adversarial integrity protocols; migrate legacy dependencies under a defined compatibility plan.

SHA-256 (Secure Hash Algorithm 2, 256-bit)

  • Output Size: 256 bits
  • Security Status: Approved in many current protocols when used with the protocol's required construction.
  • Use Case: General-purpose hashing, content addressing, and signature/MAC schemes that explicitly select it.

SHA-512 (Secure Hash Algorithm 2, 512-bit)

  • Output Size: 512 bits
  • Security Status: Approved in many current protocols when used with the protocol's required construction.
  • Use Case: General-purpose hashing where the protocol specifies SHA-512; a larger digest is not automatically a better choice.

SHA-3

  • Output Size: Variable (224, 256, 384, 512 bits)
  • Security Status: Standardized alternative with a different internal design from SHA-2.
  • Use Case: Use when the protocol, interoperability target, or implementation policy selects SHA-3; “future-proof” is not a security guarantee.

Hashing in Action: Code Examples

Let's see how to generate hashes in different programming languages.

JavaScript (using Node.js)

javascript
const crypto = require('crypto');

function createHash(input, algorithm = 'sha256') {
  if (!['sha256', 'sha512', 'sha3-256'].includes(algorithm)) {
    throw new RangeError('algorithm is not approved for this example');
  }
  const hash = crypto.createHash(algorithm);
  hash.update(input);
  return hash.digest('hex');
}

const input = 'hello world';
console.log(`SHA-256: ${createHash(input)}`);
// Do not use a fast hash as a password KDF or adversarial integrity check.

Python

python
import hashlib

def create_hash(input_string, algorithm='sha256'):
  if algorithm not in {'sha256', 'sha512', 'sha3_256'}:
    raise ValueError("algorithm is not approved for this example")
  hasher = hashlib.new(algorithm)
  hasher.update(input_string.encode('utf-8'))
  return hasher.hexdigest()

input_str = 'hello world'
print(f"SHA-256: {create_hash(input_str)}")
print(f"SHA-512: {create_hash(input_str, 'sha512')}")

Java

java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.nio.charset.StandardCharsets;

public class HashingExample {
    public static String createHash(String input, String algorithm) {
        try {
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            byte[] encodedhash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(encodedhash);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static String bytesToHex(byte[] hash) {
        StringBuilder hexString = new StringBuilder(2 * hash.length);
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static void main(String[] args) {
        String input = "hello world";
        System.out.println("SHA-256: " + createHash(input, "SHA-256"));
        System.out.println("SHA-512: " + createHash(input, "SHA-512"));
    }
}

Practical Applications of Hashing

Hashing is used in a wide variety of applications to ensure security and efficiency.

  • Password Storage: Store passwords with a dedicated KDF such as Argon2id, bcrypt, or scrypt, including a unique salt and a calibrated cost. A plain SHA-256 digest is not a password-storage design.
  • Data Integrity: A digest can detect accidental changes when the expected digest comes from a trusted channel. For an attacker-resistant check, use an authenticated MAC, signature, or authenticated transport.
  • Digital Signatures: Signature schemes sign a message or its digest with a private key and verify with a public key; signing is not generic “encrypting the hash.”
  • Blockchain Technology: Hashes link data structures, but immutability and authenticity depend on consensus, key management, and the complete protocol.

Frequently Asked Questions (FAQ)

1. What is the difference between hashing and encryption?

Hashing is a fixed-output mapping; recovering an unknown input may be infeasible for high-entropy inputs, but guesses can still be tested and collisions always exist in finite output spaces. Encryption is a reversible confidentiality mechanism that uses a key.

2. Why is MD5 considered broken?

MD5 collision attacks are practical, so it must not protect signatures or adversarial integrity. A legacy MD5 checksum may detect accidental corruption only when the expected value comes from a trusted channel.

3. What is a "salt" in password hashing?

A salt is a unique random value supplied to a password KDF and stored with its encoded parameters. It prevents precomputed tables and makes equal passwords produce different outputs; it does not make weak passwords resistant to online or offline guessing by itself.

4. Which hashing algorithm should I use?

Choose the hash and construction required by the protocol, interoperability target, and threat model. Do not substitute SHA-256, SHA-512, or SHA-3 for a password KDF. For passwords, prefer a maintained Argon2id, bcrypt, or scrypt implementation (or PBKDF2 where required), then calibrate cost and rehash policy on production-like hardware.

5. Can a hash be "decrypted"?

There is no decryption operation for a hash. An attacker can guess candidate inputs and compare digests, so resistance depends on input entropy and the construction's security properties; passwords need a slow KDF.

Conclusion

Hashing algorithms are building blocks whose security depends on how they are composed. MD5 and SHA-1 are unsuitable for adversarial collision resistance; SHA-2 and SHA-3 are general-purpose families, while password storage requires a separate, tunable KDF and authenticated integrity often requires a MAC or signature.

Choose the construction, parameters, key management, and verification channel together, and document what an observed digest does and does not prove.