A database backup is about to leave the building. A user downloads a release file from your site. Your service receives a notification from another application and needs to know whether it was altered on the way.

These sound like security problems, and they are. But they are not the same security problem. The backup needs to stay private. The downloaded file needs to match what the publisher released. The notification needs to come from a party your service trusts.

Encryption, hashing, and digital signatures are often mentioned together because real systems use them together. They are not interchangeable tools. Picking the wrong one can leave a system exposed while still giving everyone involved the warm feeling that "we use crypto."

Here is the short version:

  • Encryption is for keeping data readable only to someone with the right key.
  • Hashing turns data into a fixed-size digest that can help detect changes, if you have a trusted digest to compare against.
  • A digital signature lets someone check that data matches a signature made with a particular private key, if they trust the corresponding public key.

To understand why those distinctions matter, start with the jobs a system is trying to do.

Three Different Security Goals

Confidentiality means limiting who can read information. If a storage device is lost or a network connection is observed, confidential data should not become readable to an unauthorized party.

Integrity means being able to detect unauthorized changes. If a configuration file is edited or a message is modified in transit, the recipient should have a way to notice.

Authenticity means having evidence about where data came from. A recipient might need to know that a message was produced by a particular service, or that a release was approved by the team that publishes it.

These goals overlap in practice, but one does not automatically provide the others. A scrambled message may be private but still vulnerable to undetected modification. A hash can help detect a changed file but does not tell you who created the expected hash. A signature can establish that a particular key signed a message, while leaving the message completely public.

Think of them as different questions to ask about data, not different levels of the same lock.

Encryption: Who Can Read This?

Encryption takes readable data, called plaintext, and transforms it into ciphertext using a key. Someone with the appropriate key can decrypt the ciphertext and recover the original data. Someone without that key should not be able to do so in any practical amount of time.

A familiar example is a database containing private customer information. Encrypting selected fields can reduce the damage if a backup or storage volume is exposed. The data is still present, but it is not immediately useful to someone who cannot access the decryption key.

Symmetric encryption uses the same secret key to encrypt and decrypt. It is efficient for large amounts of data, but every party that needs to decrypt must get that secret key.

Public-key cryptography uses a shareable public key and a protected private key. Depending on the scheme, it can encrypt data or establish a shared key. Applications generally do not encrypt every byte with a public-key algorithm. They use a public-key operation to establish or protect a symmetric key, then use symmetric encryption for the payload.

Hiding contents does not necessarily detect changes to ciphertext. Authenticated encryption provides confidentiality while also detecting tampering. It can also protect selected visible information, such as a record identifier, without encrypting it.

Ask more than "Is this encrypted?" Where is the key, who can use it, and how can access change? If an application stores the key beside the ciphertext under the same access controls, encryption may offer little protection against a compromised application. Key access, rotation, backups, and recovery are part of the design.

Hashing: Does This Data Match?

A cryptographic hash function maps input of any length to a fixed-size hash or digest. The same input gives the same digest; a small change should produce a different one.

A hash is not encrypted data and cannot be decrypted. Preimage resistance means it should be impractical to find an input for a given digest. Collision resistance means it should be impractical to find two inputs with the same digest. Collisions must exist because infinitely many inputs map to a fixed-size output. The goal is to make finding a useful collision infeasible.

If you download a release file, you can compare its digest with an expected digest received through a trusted channel. A mismatch means the file changed or was damaged. But if an attacker can replace both file and digest, the check still succeeds. A hash does not prove who published its expected value. A signature or another authenticated channel can establish that trust.

Ordinary checksums catch accidental corruption. Cryptographic hashes are designed to resist deliberate manipulation, but neither establishes identity alone.

Password storage needs a dedicated password-hashing scheme, not reversible encryption or a fast general-purpose hash. After a database leak, attackers can test guesses against stored fast hashes. Password-hashing schemes make each guess deliberately expensive. A unique salt, stored with each result, prevents identical passwords from producing identical hashes and makes precomputed lookup tables less useful. Choose resource settings for the application and revisit them over time.

Digital Signatures: Does This Match a Trusted Key?

A digital signature is created with a private signing key and checked with the corresponding public verification key. The signer applies a signature scheme to a message. The recipient checks the signature against the message and public key.

If someone changes the message after it was signed, verification should fail. If verification succeeds, the recipient has evidence that the signature matches that message and that the corresponding private key was used, assuming the scheme and implementation are sound.

Notice what this does not say: the recipient has not necessarily learned the real-world identity of the signer. A public key is just data until the recipient has a reason to trust that it belongs to the expected publisher. That reason might be a certificate, a key pinned in an application, or a key obtained through a well-established distribution channel. The signature ties a message to a key. The surrounding trust system ties that key to an identity.

A signature also does not make the message secret. Anyone can read a signed release manifest if it is published openly. The signature gives readers a way to check that the manifest has not changed and matches the release key they trust.

This is why "signing is encryption with the private key" is a misleading shortcut. A signature is not created by encrypting a message, and verification is not decryption with a public key. Signature schemes and encryption schemes are designed for different operations and security properties. A private signing key should be used for signing, not treated as a general-purpose decryption tool.

The term non-repudiation sometimes appears in discussions of signatures. A signature can provide evidence that a key was used, but it cannot, by itself, prove which human was operating the key, that the key was never copied, or that the signer understood and approved the message. Key custody, account authorization, device security, and the legal context all matter.

Encryption, Hashing, Signatures, and HMAC Compared

MechanismMain jobKey modelCan the original be recovered?Typical use
EncryptionConfidentialitySecret key, or a public/private key schemeYes, with the appropriate keyProtecting stored or transmitted data
Cryptographic hashFixed-size digest for comparisonNo secret key requiredNoChecking data against a trusted digest
Digital signatureIntegrity and key-based authenticityPrivate signing key, public verification keyThe message is not hiddenVerifying a software release
HMACIntegrity and authenticity among shared-key holdersShared secret keyThe message is not hiddenAuthenticating a service-to-service message

The following notation is only a conceptual sketch. It is not executable code or an implementation recipe:

ciphertext = Encrypt(key, plaintext)
digest = Hash(message)
signature = Sign(privateKey, message)
valid = Verify(publicKey, message, signature)

These lines hide the difficult parts: safe key generation, authenticated encryption, encoding rules, signature formats, key distribution, and library-specific requirements. Do not turn this sketch into a homegrown crypto API.

HMAC: Integrity With a Shared Secret

A message authentication code, or MAC, is a tag that lets parties sharing a secret key check a message's integrity and authenticity. HMAC is a widely used construction that combines a cryptographic hash with a shared secret key.

Imagine two services that share a secret. One sends a request and an HMAC tag; the other uses the same secret to check whether the tag matches the request. A party without the secret should not be able to make a valid tag for a modified message.

That shared key creates an important difference from signatures. Every service that can verify an HMAC also has the secret needed to create one. If several services share that key, any one of them can produce a message that verifies as valid. With a digital signature, a recipient can verify using a public key without receiving the private signing key.

A MAC can be a good fit when a small, controlled group of services already shares a secret and all of them are permitted to authenticate messages. A signature can be a better fit when many recipients need to verify messages, but only one party should be able to create them. Neither choice removes the need to protect keys and define which messages are allowed.

How Real Systems Combine the Pieces

HTTPS is not "encryption turned on." TLS, the protocol underlying HTTPS, combines several cryptographic operations. During connection setup, the client and server establish keys and authenticate the server using the certificate and protocol checks. The resulting connection uses symmetric authenticated encryption to protect application data and detect tampering. The exact handshake details depend on the TLS version and configuration, but the important point is that the protocol uses different tools for different jobs.

A software release has a different shape. The publisher can make the file public, publish a digest, and sign release metadata that contains the expected digest. A user downloads the file, checks its digest against the signed metadata, and verifies the signature using a trusted release key. The file remains readable, but an attacker should not be able to quietly substitute a different file and make the verification pass.

A webhook signature follows a similar idea. The receiving service checks a signature or MAC over the request using a secret or public key established for that integration. That can help detect forged or changed requests. It does not make the request confidential, and it does not mean every action described by a valid request should automatically be authorized. The application still needs to validate the event and apply its own business rules.

flowchart TD
    Data[Data or message]
    Data --> Confidentiality[Goal: confidentiality]
    Data --> Integrity[Goal: integrity]
    Data --> Authenticity[Goal: authenticity]
    Confidentiality --> Encryption[Encryption]
    Encryption --> SecretKey[Appropriate decryption key]
    Integrity --> Hashing[Hash and compare]
    Hashing --> ExpectedDigest[Trusted expected digest]
    Authenticity --> Signature[Digital signature]
    Signature --> PrivateKey[Private key creates signature]
    Signature --> PublicKey[Trusted public key verifies signature]
    Encryption --> Protocol[Real protocols combine operations]
    Signature --> Protocol
    Hashing --> Protocol

The diagram is a map, not a recipe. In real systems, protocol details determine exactly which data is covered, how keys are authenticated, and how failures are handled.

Choosing the Right Tool

Before reaching for a cryptographic primitive, write down the property you need:

  • Need to keep data private? Use a reviewed encryption scheme and design how keys are stored, accessed, rotated, and recovered.
  • Need to verify a password? Use a dedicated password-hashing function with a unique salt and appropriate resource costs. Do not store plaintext passwords or encrypt passwords so they can be recovered.
  • Need to compare a file with a known value? A cryptographic hash can show whether it matches the expected digest. Make sure the digest itself comes from a trusted source if an attacker is in scope.
  • Need to check integrity between parties that share a secret? A MAC such as HMAC may fit, as long as every key holder is allowed to create valid messages.
  • Need many recipients to verify a message while limiting who can create it? A digital signature may fit. Establish a trustworthy way to distribute and validate the public key.

Do not invent a cipher, signature format, protocol, or key-management scheme. Use maintained cryptographic libraries and established protocols, and get qualified review for systems where failure would have serious consequences. Cryptography is full of details that look harmless until two components interpret them differently.

The Mental Model to Keep

Encryption asks, "Who can read this?" Hashing asks, "Does this data match this digest?" A signature asks, "Does this data match a signature made by the holder of this private key, and do I trust that key?" An HMAC asks a related question for parties that share a secret: "Does this message match a tag made by someone who knows that secret?"

Those questions are close enough to get mixed up and different enough that the mix-up matters. Choose the primitive that fits the security goal, then pay equal attention to the keys, identities, and trust relationships around it. That's where the actual system begins.