Hashes, Signatures and Merkle Proofs: What Does Each Actually Prove?

A customer sends an approved order. A colleague sends its hash. A remote service sends a Merkle proof. All three may be useful, but they do not answer the same question. Confusing them can leave an application checking the right mathematics against the wrong trust assumption.

We will use one small C# example to compare the claims. Sphere 10 Framework supplies the hashing primitives, and its CryptoEx package supplies the signing implementation. The sample changes the order text and shows which checks reject it, rather than treating the presence of a cryptographic value as sufficient proof.

Different forms of evidence for data integrity, authorship and record inclusion.
Different forms of evidence for data integrity, authorship and record inclusion.

Contents

Install the Packages


dotnet new console --framework net10.0
dotnet add package Sphere10.Framework --version 3.1.3
dotnet add package Sphere10.Framework.CryptoEx --version 3.1.3

The complete downloadable project pins those versions. Its two-leaf tree makes the membership calculation visible. For a general dataset, the Framework proof tutorial demonstrates the collection-based API.

A Hash Identifies the Bytes You Checked


var hash = Hashers.Hash(CHF.SHA2_256, message);
var changed = Hashers.Hash(CHF.SHA2_256, altered);
Console.WriteLine(!hash.SequenceEqual(changed));

The result is True for the two messages in the sample. A hash is useful when a trusted source has already supplied the expected digest. If an attacker can replace both the message and the digest, recomputing the digest alone does not identify the sender. A digest downloaded from the same unauthenticated location as its file needs an additional trust mechanism.

A Signature Is Checked Against a Public Key


var signer = new ECDSA(ECDSAKeyType.SECP256K1);
var privateKey = signer.GeneratePrivateKey();
var publicKey = signer.DerivePublicKey(privateKey);
var signature = signer.Sign(privateKey, message);
Console.WriteLine(signer.Verify(signature, message, publicKey));
Console.WriteLine(signer.Verify(signature, altered, publicKey));

The original verifies and the altered message does not. This establishes a relationship between the signed bytes and the corresponding key, under the scheme's assumptions. The application still needs a trustworthy association between that public key and the person, device or authority it intends to accept. The sample creates an ephemeral key to demonstrate signing. A production application also needs a key-storage design.

A Merkle Proof Establishes Membership

In the sample, two leaf hashes produce one root. To check the first record, the verifier combines that record's leaf with the supplied sibling and compares the result with the expected root. Leaves and parent nodes have different prefixes so their roles are unambiguous in this illustrative tree.


var sibling = Leaf(Encoding.UTF8.GetBytes("Order 1043"));
var trustedRoot = Parent(Leaf(message), sibling);
var valid = trustedRoot.SequenceEqual(Parent(Leaf(message), sibling));

The downloadable project contains Leaf and Parent. Replacing message with altered makes this comparison False. The proof does not independently say who endorsed the dataset. A signed or otherwise trusted root can supply that additional boundary.

Read the Expected Result


Changed bytes change digest: True
Original signature verifies: True
Altered message verifies: False
Original two-leaf proof verifies: True
Altered two-leaf proof verifies: False

💡 You can use these mechanisms together by hashing records, placing their hashes in a Merkle tree, and signing or securely distributing the root. Keep the claim made by each layer distinct.

A dataset root can also change over time. Keep the root's version or context with the proof, and define what freshness means for the application. None of the three checks automatically supplies authorisation, replay prevention or business approval.

Continue with record inclusion proofs and Merkleized ObjectSpaces . The CryptoEx guide explains the Framework's supported signature abstractions. The useful engineering result is a precise verification claim, not simply more cryptographic terminology in the system.

Continue the Series

How to Prove One Record Belongs to a Dataset

How to Add Cryptographic Integrity to an Object Store

sample.zip
Download the complete worked example and build instructions (ZIP).

For the broader Sphere 10 development toolkit, see the Sphere10 Framework overview .