Post
Share your knowledge.
It’s zk time. Let’s get weird ^^
Hey
“I know something, but I won’t tell you what and yet you’ll still believe me.”✨
Imagine this:
You prove you work at a certain company. ✅ Without revealing your email. ✅ Without doxxing your Web2 identity. ✅ Fully verifiable on-chain.
That’s the power of zero-knowledge proofs (zk proofs) and you don’t need a PhD in cryptography to start building with them anymore. Welcome to the world of zkApps: applications powered by cryptographic magic, but crafted with tools that feel just like writing regular code.
What is a zkApp (zero-knowledge app)?
A zkApp is an app where users can prove something about their private data without revealing the data itself. Think of it as flexing receipts… without showing your wallet.
These apps enable functionality we often only dream about—like verifying someone’s identity without revealing their name, or allowing users to vote on-chain without revealing their actual vote.
In the Sui ecosystem, zkApps take on an extra layer of potential. They bridge your off-chain secrets with on-chain logic, using tools like SP1 zkVM and Soundness Layer to make proof generation and verification more practical than ever.
Traditionally, writing a zk circuit required cryptographic expertise and weeks of effort. But zkVMs like SP1, Risc0, and Nexus have flipped the game. These virtual machines allow developers to express their logic in normal programming languages, generate a zk proof for the result, and submit it for on-chain verification.
This abstraction doesn’t just speed up development, it expands who can build zkApps. If you can write logic in Rust, you can build a zkApp. And if you use Soundness Layer, you can verify it on Sui.
zkDomain: Proving Email Ownership Without Exposure
Let’s consider a common scenario that a DAO wants to airdrop tokens to employees of a specific company.
But instead of collecting user emails and verifying them manually, which exposes Web2 identity and risks user privacy, we want users to prove they own an email at @soundness.xyz, without ever revealing the full address.
This is where the real-world magic of zk comes in.
If you have access to a company email that uses Google Workspace, you can authenticate via OpenID Connect (OIDC) and receive a signed JWT (JSON Web Token) from Google. This token contains metadata, including your email.
Now, instead of sending that JWT to the DAO, you generate a zk proof that says, “I have a valid Google-issued JWT, and my email ends with @soundness.xyz.” That proof is verified on-chain. No one ever sees your actual email. The DAO only sees that a proof has passed.
Access granted.
All the verification logic JWT parsing, signature validation, domain checking is run inside a zkVM program written in Rust, compiled by SP1.
You can peek into the full implementation here:
#![no_main]
sp1_zkvm::entrypoint!(main);
use lib::{split_email, split_jwt, pem_to_der};
use rsa::{pkcs8::DecodePublicKey, Pkcs1v15Sign, RsaPublicKey};
use sha2_v0_10_8::{Digest, Sha256};
pub fn main() {
// Read input values: JWT token, RSA public key, and the expected domain
let token = sp1_zkvm::io::read::<String>();
let rsa_public_key = sp1_zkvm::io::read::<String>();
let domain = sp1_zkvm::io::read::<String>();
// Commit the domain to the zk proof (so it’s publicly known)
sp1_zkvm::io::commit(&domain);
// Split the JWT into its components: header, payload, and signature
let (header, payload, signature) = split_jwt(&token)
.expect("Failed to decode JWT"); // Panic if JWT parsing fails
// Convert the PEM public key into DER format for RSA verification
let pk_der = pem_to_der(&rsa_public_key);
let public_key = RsaPublicKey::from_public_key_der(&pk_der).unwrap();
// Reconstruct the signing input (header + payload) as a string
let signing_input = format!(
"{}.{}",
token.split('.').collect::<Vec<&str>>()[0], // First part: header
token.split('.').collect::<Vec<&str>>()[1] // Second part: payload
);
// Hash the signing input using SHA256
let mut hasher = Sha256::new();
hasher.update(signing_input);
let hashed_msg = hasher.finalize();
// Verify the JWT signature using the provided RSA public key
let verification_result = match public_key.verify(Pkcs1v15Sign::new::<Sha256>(), &hashed_msg, &signature) {
Ok(_) => true, // Signature is valid
Err(_) => false, // Signature is invalid
};
// Commit the verification result (proof that the JWT is authentic)
sp1_zkvm::io::commit(&verification_result);
// Extract and split the email address from the JWT payload
let email_parts = split_email(payload.get("email").unwrap().to_string()).unwrap();
// Check if the email domain matches the expected domain
let verified = email_parts.domain == domain;
// Commit the verification result (proof that the email domain is correct)
sp1_zkvm::io::commit(&verified);
}
Only the domain, and whether or not the JWT was valid. That’s it. The user’s full email, original JWT, and any other personally identifiable information stays hidden, cryptographically sealed inside the proof.
Onchain Verification: From zkVM to Move
Of course, generating the proof is just one side of the coin. The real utility kicks in when you can verify that proof on-chain—and take action based on it.
Here’s where the Soundness Layer becomes a game-changer. Built for Sui, it acts as a zk verification layer that can process SP1-generated proofs—converted into Groth16 format, which Sui natively supports. You don’t need to mess with cryptographic primitives. You just write a smart contract in Move, pass the proof and the public inputs (like the expected domain), and let the verifier logic do the rest.
This means your DAO smart contract can now gate airdrops based on email domain ownership—without ever touching sensitive data. Soundness Layer handles the verification. Your smart contract handles the logic. The rest is magic.
Learn more about Soundness Layer here:
🔗 soundness.xyz/blog/soundness-layer
You can build authentication flows without passwords. You can design voting systems that guarantee anonymity. You can gate access to DAOs, events, or rewards based on criteria that remain completely private.
And crucially, you can do all of this using Rust + Sui + SP1 + Soundness Layer—without writing a single cryptographic constraint by hand.
We’re no longer talking about theoretical zk. We’re talking about zk you can ship. Because privacy isn’t just a feature, it’s a foundation. And with zk, it’s finally composable.
- Sui
- SDKs and Developer Tools
- Security Protocols
I love that the zk principle is starting to take over the world. Soon we won't need to open our eyes to know that the world exists😵💫
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
- Why does BCS require exact field order for deserialization when Move structs have named fields?53
- Multiple Source Verification Errors" in Sui Move Module Publications - Automated Error Resolution42
- Sui Transaction Failing: Objects Reserved for Another Transaction24
- How do ability constraints interact with dynamic fields in heterogeneous collections?04