Back to glossary

Cryptographic Verification

Table of Contents

What is cryptographic verification?

Cryptographic verification is a process that uses mathematical algorithms to confirm the authenticity, integrity, and origin of data. It uses techniques such as hashing and digital signatures to verify information has not been tampered with or altered during transmission or storage.

It serves three purposes:

  • Authenticity: Confirms data is genuine and from the indicated sender. 
  • Integrity: Ensures information hasn’t been changed.
  • Non-repudiation: Proves the sender actually sent the message. 

How cryptographic verification works

Diagram illustrating the cryptographic verification process  including the digital signature and verification processes.
Digital signature and verification processes

  1. Hash generation: A hash function creates a fixed-length string (hash) from input data.
  2. Signature creation: The sender encrypts the hash with their private key, creating a digital signature.
  3. Transmission: The sender transmits the data and digital signature.
  4. Recipient verification
    • The recipient generates a new hash from the received data.
    • The recipient decrypts the signature using the sender's public key.
  5. Integrity check: Matching hashes confirm data integrity; mismatches indicate tampering.

Example: Cryptocurrency transaction verification

  1. Alice creates a transaction to send 1 BTC to Bob and signs it with her private key.
  2. Alice broadcasts the transaction, including transaction details and digital signature, to the Bitcoin network.
  3. Network nodes verify the transaction by:
    • Hashing the transaction details.
    • Using Alice's public key to decrypt the digital signature.
    • Comparing the decrypted hash with the hash of the transaction details.
  4. If the hashes match, nodes confirm that Alice authorized the transaction and it hasn't been tampered with.
  5. Once verified by enough nodes, the transaction is included in a block and added to the blockchain.

Where is cryptographic verification used?

Cryptographic verification is widely employed across sectors and industries:

  • Blockchain networks: Validate on-chain transactions and uphold ledger integrity, e.g., Ethereum’s use of digital signatures to verify transaction authenticity.
  • Enterprise: Secure communications and protecting sensitive data. For example, a company using encrypted VPNs to safeguard internal communications.
  • Finance: To secure financial transactions and verify digital signatures on contracts, such as using cryptographic verification in SWIFT messages for international bank transfers.
  • Individuals: Personal communications with secure messaging apps for end-to-end encrypted chats.

Cryptographic verification in blockchain

Cryptographic verification guarantees blockchain transactions are authenticated, secure, and immutable. Here’s how:

  1. Transaction integrity: Each transaction is hashed where any alteration to the transaction data results in a different hash, making tampering easily detectable.
  2. Hash functions: Each block contains a hash of the previous block, forming a secure chain. If any block is altered, it changes that block's hash, which then causes a mismatch with the next block's stored previous hash.
  3. Digital signatures: Used to verify transaction authenticity. For example, in Ethereum:
    • A user signs a transaction with their private key.
    • The signature is verified only if the user's public key matches the private key used to sign the transaction.
  4. Merkle Trees: Allow quick, efficient verification of large sets of transactions in blocks without verifying each transaction individually.
  5. Sybil resistance mechanisms: Proof of Work (PoW) and Proof of Stake (PoS) serve as sybil resistance mechanisms within their respective consensus algorithms, using cryptographic puzzles and validator’s stake, respectively, to validate transactions and add new blocks.

In practice

Let's look at a practical example of digital signatures using ether.js, a widely-used Ethereum library. When we create a digital signature, several things happen behind the scenes:

First, let’s sign a message:

import { ethers } from 'ethers';

async function createSignature() {
    try {
        // Create a wallet with a private key (NEVER use this private key in production!)
        const privateKey = "your_priv_key";
        const wallet = new ethers.Wallet(privateKey);

        // The message we want to sign
        const message = "Hi, from Cyfrin";

        // Sign the message
        const signature = await wallet.signMessage(message);
        console.log("Message:", message);
        console.log("Signer address:", wallet.address);
        console.log("Signature:", signature);

    } catch (error) {
        console.error("Error:", error.message);
    }
}

// Run the function
createSignature();

The library handles the cryptographic heavy lifting: it hashes our message using keccak256 and creates a signature using ECDSA (Elliptic Curve Digital Signature Algorithm), the standard signature mechanism in Ethereum.

This generates:
Message: Hi, from Cyfrin

Signer address: 0xd520d565812F31345c32314e949a39FbB382551B

Signature: 0xa672589ad60e71fca65d10b018f94148603e3251abced9bc61bb855208637e064141f8662f56af0c0c159374aa6692f040292cd1efec8cc20b370473c7e6dc341c

To verify this signature, we can use this example:

import { ethers } from "ethers";

const message = "Hi, from Cyfrin";
const signature = "0xa672589ad60e71fca65d10b018f94148603e3251abced9bc61bb855208637e064141f8662f56af0c0c159374aa6692f040292cd1efec8cc20b370473c7e6dc341c";
const expectedSigner = "0xd520d565812F31345c32314e949a39FbB382551B";

try {
  const recoveredAddress = ethers.verifyMessage(message, signature);
  const isValid =
    recoveredAddress.toLowerCase() === expectedSigner.toLowerCase();

  if (isValid) {
    console.log("✅ Signature is valid!");
    console.log(`Message was signed by: ${recoveredAddress}`);
  } else {
    console.log("❌ Invalid signature!");
    console.log(`Message was NOT signed by ${expectedSigner}`);
  }
} catch (error) {
  console.log("❌ Error verifying signature:", error.message);
}

When the message and signature match, the verification succeeds and it outputs:

✅ Signature is valid!

Message was signed by: 0xd520d565812F31345c32314e949a39FbB382551B

However, if even a single character in the message is changed (e.g., "Cyfrin" to "Cyfri"), the verification fails:

❌ Invalid signature!

Message was NOT signed by 0xd520d565812F31345c32314e949a39FbB382551B

The verification process recreates the message hash and uses the signature to recover the signer's address. Even if one character in the message changes, it produces a different hash and verification fails. The signature is uniquely tied to both the message and the signer's private key, which shows that modifying the message would invalidate the signature. 

Related Terms

No items found.