Today’s focus was on understanding how blockchain handles cryptographic hashing and how Solidity interacts with cryptographic functions. This is essential for data integrity, digital signatures, and secure transactions in smart contracts.
A hash function is a one-way function that takes an
input and produces a fixed-length output (hash). On Ethereum, hashing is
commonly used for:
- Storing and verifying data without revealing the
original input.
- Checking integrity to ensure data hasn’t been
tampered with.
- Generating digital signatures for authentication and
security.
Ethereum primarily uses Keccak-256, a variant of SHA-3, as its hashing function.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract HashingExample {
function generateHash(string memory input) public pure returns (bytes32) {
return keccak256(abi.encodePacked(input));
}
}
keccak256(abi.encodePacked(input))
→ Hashes the input
string.Hashes can be stored on-chain inside contract
storage or logs, but because blockchain space is expensive, many
projects:
- Store the hash on-chain but keep the raw data
off-chain (e.g., IPFS, Arweave).
- Use Merkle Trees to efficiently store and verify
large datasets.
contract HashStorage {
mapping(bytes32 => bool) public storedHashes;
function storeHash(string memory data) public {
bytes32 hash = keccak256(abi.encodePacked(data));
storedHashes[hash] = true;
}
function verifyData(string memory data) public view returns (bool) {
bytes32 hash = keccak256(abi.encodePacked(data));
return storedHashes[hash];
}
}
mapping(bytes32 => bool) storedHashes
.true
, confirming the data was previously stored.This is how blockchain ensures data integrity without storing raw files.
Solidity doesn’t provide built-in asymmetric
encryption but supports:
- Keccak-256 hashing for data integrity.
- ECDSA (Elliptic Curve Digital Signatures) for
verifying signatures.
- Merkle Trees for efficient data verification.
Ethereum uses secp256k1, the same cryptographic curve as Bitcoin.
Example: Recovering a Signer’s Address from a Signature
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract SignatureVerification {
using ECDSA for bytes32;
function verifySigner(bytes32 hash, bytes memory signature, address expectedSigner) public pure returns (bool) {
return hash.recover(signature) == expectedSigner;
}
}
This is the foundation of wallet authentication and message verification in Web3.
contract CommitReveal {
mapping(address => bytes32) public commitments;
function commit(bytes32 hash) public {
commitments[msg.sender] = hash;
}
function reveal(string memory secret, uint number) public view returns (bool) {
return commitments[msg.sender] == keccak256(abi.encodePacked(secret, number));
}
}
Used for batch verification of data, such as whitelisting users for NFT mints or validating ownership.
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
contract MerkleExample {
bytes32 public rootHash; // The Merkle Root
function verifyProof(bytes32[] memory proof, bytes32 leaf) public view returns (bool) {
return MerkleProof.verify(proof, rootHash, leaf);
}
}
Today’s session deepened my understanding of how Solidity interacts with cryptography and how hashing secures blockchain operations. The next focus will be practical implementations of cryptographic methods in smart contract security and Web3 authentication.