Cryptography Utilities
Overview
The Cryptography Utilities provide a set of cryptographic tools for Soroban smart contracts, including hash functions, Merkle tree verification, and Merkle-based distribution systems. These utilities enable secure data verification and efficient token distribution mechanisms. The Cryptography Utilities consist of two main packages:
- Crypto: A set of cryptographic primitives and utilities for Soroban contracts.
- Merkle Distributor: A system for distributing tokens or other assets using Merkle proofs for verification.
Crypto Package
The crypto package provides fundamental cryptographic primitives and utilities for Soroban contracts, with a focus on hashing and Merkle tree operations.
Key Components
Hashers
Provides a generic Hasher trait and implementations for common hash functions:
Sha256: Implementation of the SHA-256 hash functionKeccak256: Implementation of the Keccak-256 hash function (used in Ethereum)
Each hasher follows the same interface:
pub trait Hasher {
type Output;
fn new(e: &Env) -> Self;
fn update(&mut self, input: Bytes);
fn finalize(self) -> Self::Output;
}Hashable
The Hashable trait allows types to be hashed with any Hasher implementation:
pub trait Hashable {
fn hash<H: Hasher>(&self, hasher: &mut H);
}Built-in implementations are provided for BytesN<32> and Bytes.
Utility Functions
hash_pair: Hashes two values togethercommutative_hash_pair: Hashes two values in a deterministic order (important for Merkle trees)
Merkle Tree Verification
The Verifier struct provides functionality to verify Merkle proofs:
impl<H> Verifier<H>
where
H: Hasher<Output = Bytes32>,
{
pub fn verify(e: &Env, proof: Vec<Bytes32>, root: Bytes32, leaf: Bytes32) -> bool {
// Implementation verifies that the leaf is part of the tree defined by root
}
}Usage Examples
Hashing Data
use soroban_sdk::{Bytes, Env};
use stellar_contract_utils::crypto::keccak::Keccak256;
use stellar_contract_utils::crypto::hasher::Hasher;
// Hash some data with Keccak256
let e = Env::default();
let data = Bytes::from_slice(&e, "Hello, world!".as_bytes());
let mut hasher = Keccak256::new(&e);
hasher.update(data);
let hash = hasher.finalize();Verifying a Merkle Proof
use soroban_sdk::{BytesN, Env, Vec};
use stellar_crypto::keccak::Keccak256;
use stellar_crypto::merkle::Verifier;
// Verify that a leaf is part of a Merkle tree
let e = Env::default();
let root = /* merkle root as BytesN<32> */;
let leaf = /* leaf to verify as BytesN<32> */;
let proof = /* proof as Vec<BytesN<32>> */;
let is_valid = Verifier::<Keccak256>::verify(&e, proof, root, leaf);